summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2021-01-25 10:49:03 -0800
committerJames M Snell <jasnell@gmail.com>2021-01-30 07:49:28 -0800
commitc3d6d50309a5046c98475e99c13f48a8fee12ac7 (patch)
treec429781c87603dcd4905998bbc9bd073399c2f67
parentf763a80ab59bbaa0fcf5f3b0519a70336ee88744 (diff)
downloadnode-new-c3d6d50309a5046c98475e99c13f48a8fee12ac7.tar.gz
quic: remove quic
PR-URL: https://github.com/nodejs/node/pull/37067 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
-rw-r--r--.github/CODEOWNERS15
-rw-r--r--.github/workflows/build-windows.yml4
-rw-r--r--.github/workflows/test-linux.yml16
-rw-r--r--.github/workflows/test-macos.yml4
-rw-r--r--LICENSE52
-rwxr-xr-xconfigure.py60
-rw-r--r--deps/nghttp3/COPYING22
-rw-r--r--deps/nghttp3/lib/includes/config.h39
-rw-r--r--deps/nghttp3/lib/includes/nghttp3/nghttp3.h1801
-rw-r--r--deps/nghttp3/lib/includes/nghttp3/version.h46
-rw-r--r--deps/nghttp3/lib/nghttp3_buf.c90
-rw-r--r--deps/nghttp3/lib/nghttp3_buf.h74
-rw-r--r--deps/nghttp3/lib/nghttp3_conn.c3250
-rw-r--r--deps/nghttp3/lib/nghttp3_conn.h263
-rw-r--r--deps/nghttp3/lib/nghttp3_conv.c134
-rw-r--r--deps/nghttp3/lib/nghttp3_conv.h219
-rw-r--r--deps/nghttp3/lib/nghttp3_debug.c61
-rw-r--r--deps/nghttp3/lib/nghttp3_debug.h44
-rw-r--r--deps/nghttp3/lib/nghttp3_err.c123
-rw-r--r--deps/nghttp3/lib/nghttp3_err.h34
-rw-r--r--deps/nghttp3/lib/nghttp3_frame.c200
-rw-r--r--deps/nghttp3/lib/nghttp3_frame.h214
-rw-r--r--deps/nghttp3/lib/nghttp3_gaptr.c119
-rw-r--r--deps/nghttp3/lib/nghttp3_gaptr.h98
-rw-r--r--deps/nghttp3/lib/nghttp3_http.c840
-rw-r--r--deps/nghttp3/lib/nghttp3_http.h146
-rw-r--r--deps/nghttp3/lib/nghttp3_idtr.c88
-rw-r--r--deps/nghttp3/lib/nghttp3_idtr.h99
-rw-r--r--deps/nghttp3/lib/nghttp3_ksl.c722
-rw-r--r--deps/nghttp3/lib/nghttp3_ksl.h335
-rw-r--r--deps/nghttp3/lib/nghttp3_macro.h47
-rw-r--r--deps/nghttp3/lib/nghttp3_map.c337
-rw-r--r--deps/nghttp3/lib/nghttp3_map.h153
-rw-r--r--deps/nghttp3/lib/nghttp3_mem.c77
-rw-r--r--deps/nghttp3/lib/nghttp3_mem.h45
-rw-r--r--deps/nghttp3/lib/nghttp3_pq.c168
-rw-r--r--deps/nghttp3/lib/nghttp3_pq.h129
-rw-r--r--deps/nghttp3/lib/nghttp3_qpack.c4096
-rw-r--r--deps/nghttp3/lib/nghttp3_qpack.h966
-rw-r--r--deps/nghttp3/lib/nghttp3_qpack_huffman.c122
-rw-r--r--deps/nghttp3/lib/nghttp3_qpack_huffman.h108
-rw-r--r--deps/nghttp3/lib/nghttp3_qpack_huffman_data.c4981
-rw-r--r--deps/nghttp3/lib/nghttp3_range.c62
-rw-r--r--deps/nghttp3/lib/nghttp3_range.h81
-rw-r--r--deps/nghttp3/lib/nghttp3_rcbuf.c109
-rw-r--r--deps/nghttp3/lib/nghttp3_rcbuf.h82
-rw-r--r--deps/nghttp3/lib/nghttp3_ringbuf.c159
-rw-r--r--deps/nghttp3/lib/nghttp3_ringbuf.h113
-rw-r--r--deps/nghttp3/lib/nghttp3_str.c110
-rw-r--r--deps/nghttp3/lib/nghttp3_str.h40
-rw-r--r--deps/nghttp3/lib/nghttp3_stream.c1282
-rw-r--r--deps/nghttp3/lib/nghttp3_stream.h406
-rw-r--r--deps/nghttp3/lib/nghttp3_tnode.c110
-rw-r--r--deps/nghttp3/lib/nghttp3_tnode.h85
-rw-r--r--deps/nghttp3/lib/nghttp3_vec.c64
-rw-r--r--deps/nghttp3/lib/nghttp3_vec.h35
-rw-r--r--deps/nghttp3/lib/nghttp3_version.c39
-rw-r--r--deps/nghttp3/nghttp3.gyp67
-rw-r--r--deps/ngtcp2/.gitignore4
-rw-r--r--deps/ngtcp2/COPYING22
-rw-r--r--deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h621
-rw-r--r--deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h34
-rw-r--r--deps/ngtcp2/crypto/openssl/openssl.c496
-rw-r--r--deps/ngtcp2/crypto/shared.c786
-rw-r--r--deps/ngtcp2/crypto/shared.h189
-rw-r--r--deps/ngtcp2/lib/includes/config.h39
-rw-r--r--deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h3396
-rw-r--r--deps/ngtcp2/lib/includes/ngtcp2/version.h45
-rw-r--r--deps/ngtcp2/lib/ngtcp2_acktr.c318
-rw-r--r--deps/ngtcp2/lib/ngtcp2_acktr.h221
-rw-r--r--deps/ngtcp2/lib/ngtcp2_addr.c92
-rw-r--r--deps/ngtcp2/lib/ngtcp2_addr.h61
-rw-r--r--deps/ngtcp2/lib/ngtcp2_buf.c44
-rw-r--r--deps/ngtcp2/lib/ngtcp2_buf.h79
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cc.c526
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cc.h137
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cid.c117
-rw-r--r--deps/ngtcp2/lib/ngtcp2_cid.h137
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conn.c10100
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conn.h698
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conv.c251
-rw-r--r--deps/ngtcp2/lib/ngtcp2_conv.h282
-rw-r--r--deps/ngtcp2/lib/ngtcp2_crypto.c732
-rw-r--r--deps/ngtcp2/lib/ngtcp2_crypto.h106
-rw-r--r--deps/ngtcp2/lib/ngtcp2_err.c138
-rw-r--r--deps/ngtcp2/lib/ngtcp2_err.h34
-rw-r--r--deps/ngtcp2/lib/ngtcp2_gaptr.c129
-rw-r--r--deps/ngtcp2/lib/ngtcp2_gaptr.h103
-rw-r--r--deps/ngtcp2/lib/ngtcp2_idtr.c86
-rw-r--r--deps/ngtcp2/lib/ngtcp2_idtr.h95
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ksl.c715
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ksl.h333
-rw-r--r--deps/ngtcp2/lib/ngtcp2_log.c747
-rw-r--r--deps/ngtcp2/lib/ngtcp2_log.h80
-rw-r--r--deps/ngtcp2/lib/ngtcp2_macro.h53
-rw-r--r--deps/ngtcp2/lib/ngtcp2_map.c333
-rw-r--r--deps/ngtcp2/lib/ngtcp2_map.h151
-rw-r--r--deps/ngtcp2/lib/ngtcp2_mem.c75
-rw-r--r--deps/ngtcp2/lib/ngtcp2_mem.h43
-rw-r--r--deps/ngtcp2/lib/ngtcp2_path.c74
-rw-r--r--deps/ngtcp2/lib/ngtcp2_path.h63
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pkt.c2271
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pkt.h1126
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ppe.c229
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ppe.h153
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pq.c164
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pq.h126
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pv.c155
-rw-r--r--deps/ngtcp2/lib/ngtcp2_pv.h163
-rw-r--r--deps/ngtcp2/lib/ngtcp2_qlog.c1225
-rw-r--r--deps/ngtcp2/lib/ngtcp2_qlog.h140
-rw-r--r--deps/ngtcp2/lib/ngtcp2_range.c61
-rw-r--r--deps/ngtcp2/lib/ngtcp2_range.h80
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rcvry.h42
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ringbuf.c114
-rw-r--r--deps/ngtcp2/lib/ngtcp2_ringbuf.h110
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rob.c327
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rob.h203
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rst.c107
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rst.h75
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rtb.c1172
-rw-r--r--deps/ngtcp2/lib/ngtcp2_rtb.h408
-rw-r--r--deps/ngtcp2/lib/ngtcp2_str.c98
-rw-r--r--deps/ngtcp2/lib/ngtcp2_str.h85
-rw-r--r--deps/ngtcp2/lib/ngtcp2_strm.c664
-rw-r--r--deps/ngtcp2/lib/ngtcp2_strm.h266
-rw-r--r--deps/ngtcp2/lib/ngtcp2_vec.c232
-rw-r--r--deps/ngtcp2/lib/ngtcp2_vec.h114
-rw-r--r--deps/ngtcp2/lib/ngtcp2_version.c39
-rw-r--r--deps/ngtcp2/ngtcp2.gyp118
-rw-r--r--deps/openssl/openssl.gyp7
-rw-r--r--deps/openssl/patches/0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch2363
-rw-r--r--doc/api/errors.md31
-rw-r--r--doc/api/index.md1
-rw-r--r--doc/api/net.md9
-rw-r--r--doc/api/quic.md2518
-rw-r--r--doc/guides/maintaining-ngtcp2-nghttp3.md59
-rw-r--r--doc/guides/maintaining-openssl.md29
-rw-r--r--lib/internal/errors.js13
-rw-r--r--lib/internal/quic/core.js3326
-rw-r--r--lib/internal/quic/util.js1052
-rw-r--r--lib/net.js25
-rw-r--r--node.gyp56
-rw-r--r--node.gypi18
-rw-r--r--src/async_wrap.h6
-rw-r--r--src/env.h43
-rw-r--r--src/node_binding.cc7
-rw-r--r--src/node_errors.h6
-rw-r--r--src/node_http_common.h2
-rw-r--r--src/node_mem.h2
-rw-r--r--src/node_metadata.cc10
-rw-r--r--src/node_metadata.h7
-rw-r--r--src/node_native_module.cc4
-rw-r--r--src/quic/node_quic.cc271
-rw-r--r--src/quic/node_quic_buffer-inl.h98
-rw-r--r--src/quic/node_quic_buffer.cc166
-rw-r--r--src/quic/node_quic_buffer.h239
-rw-r--r--src/quic/node_quic_crypto.cc748
-rw-r--r--src/quic/node_quic_crypto.h144
-rw-r--r--src/quic/node_quic_default_application.cc177
-rw-r--r--src/quic/node_quic_default_application.h60
-rw-r--r--src/quic/node_quic_http3_application.cc941
-rw-r--r--src/quic/node_quic_http3_application.h331
-rw-r--r--src/quic/node_quic_session-inl.h447
-rw-r--r--src/quic/node_quic_session.cc3963
-rw-r--r--src/quic/node_quic_session.h1531
-rw-r--r--src/quic/node_quic_socket-inl.h192
-rw-r--r--src/quic/node_quic_socket.cc1202
-rw-r--r--src/quic/node_quic_socket.h609
-rw-r--r--src/quic/node_quic_state.h82
-rw-r--r--src/quic/node_quic_stream-inl.h180
-rw-r--r--src/quic/node_quic_stream.cc548
-rw-r--r--src/quic/node_quic_stream.h409
-rw-r--r--src/quic/node_quic_util-inl.h435
-rw-r--r--src/quic/node_quic_util.h394
-rw-r--r--test/cctest/test_quic_buffer.cc206
-rw-r--r--test/cctest/test_quic_cid.cc31
-rw-r--r--test/common/index.js2
-rw-r--r--test/common/quic.js38
-rw-r--r--test/parallel/test-process-versions.js5
-rw-r--r--test/parallel/test-quic-binding.js56
-rw-r--r--test/parallel/test-quic-blocklist.js52
-rw-r--r--test/parallel/test-quic-client-connect-multiple-parallel.js61
-rw-r--r--test/parallel/test-quic-client-connect-multiple-sequential.js63
-rw-r--r--test/parallel/test-quic-client-empty-preferred-address.js52
-rw-r--r--test/parallel/test-quic-client-server.js364
-rw-r--r--test/parallel/test-quic-errors-quicsession-openstream.js86
-rw-r--r--test/parallel/test-quic-errors-quicsocket-connect.js235
-rw-r--r--test/parallel/test-quic-errors-quicsocket-create.js166
-rw-r--r--test/parallel/test-quic-errors-quicsocket-listen.js173
-rw-r--r--test/parallel/test-quic-http3-client-server.js151
-rw-r--r--test/parallel/test-quic-http3-push.js159
-rw-r--r--test/parallel/test-quic-http3-trailers.js104
-rw-r--r--test/parallel/test-quic-idle-timeout.js70
-rw-r--r--test/parallel/test-quic-ipv6only.js115
-rw-r--r--test/parallel/test-quic-keylog.js66
-rw-r--r--test/parallel/test-quic-maxconnectionsperhost.js73
-rw-r--r--test/parallel/test-quic-process-cleanup.js55
-rw-r--r--test/parallel/test-quic-qlog.js76
-rw-r--r--test/parallel/test-quic-quicendpoint-address.js94
-rw-r--r--test/parallel/test-quic-quicsession-resume.js97
-rw-r--r--test/parallel/test-quic-quicsession-send-fd.js99
-rw-r--r--test/parallel/test-quic-quicsession-send-file-close-before-open.js53
-rw-r--r--test/parallel/test-quic-quicsession-send-file-open-error-handled.js51
-rw-r--r--test/parallel/test-quic-quicsession-send-file-open-error.js51
-rw-r--r--test/parallel/test-quic-quicsession-server-destroy-early.js54
-rw-r--r--test/parallel/test-quic-quicsocket-close.js19
-rw-r--r--test/parallel/test-quic-quicsocket-packetloss-stream-rx.js98
-rw-r--r--test/parallel/test-quic-quicsocket-packetloss-stream-tx.js98
-rw-r--r--test/parallel/test-quic-quicsocket-serverbusy.js52
-rw-r--r--test/parallel/test-quic-quicsocket.js150
-rw-r--r--test/parallel/test-quic-quicstream-close-early.js84
-rw-r--r--test/parallel/test-quic-quicstream-destroy.js59
-rw-r--r--test/parallel/test-quic-quicstream-identifiers.js141
-rw-r--r--test/parallel/test-quic-server-busy-event-error-async.js32
-rw-r--r--test/parallel/test-quic-server-busy-event-error.js32
-rw-r--r--test/parallel/test-quic-server-listening-event-error-async.js33
-rw-r--r--test/parallel/test-quic-server-listening-event-error.js33
-rw-r--r--test/parallel/test-quic-server-ready-event-error-async.js31
-rw-r--r--test/parallel/test-quic-server-ready-event-error.js31
-rw-r--r--test/parallel/test-quic-server-session-event-error-async.js65
-rw-r--r--test/parallel/test-quic-server-session-event-error.js65
-rw-r--r--test/parallel/test-quic-simple-client-migrate.js96
-rw-r--r--test/parallel/test-quic-simple-server-bidi.js55
-rw-r--r--test/parallel/test-quic-simple-server-uni.js60
-rw-r--r--test/parallel/test-quic-socket-close-event-error-async.js31
-rw-r--r--test/parallel/test-quic-socket-close-event-error.js31
-rw-r--r--test/parallel/test-quic-statelessreset.js71
-rw-r--r--test/parallel/test-quic-with-fake-udp.js60
-rw-r--r--test/pummel/test-heapdump-quic.js152
-rw-r--r--test/sequential/test-async-wrap-getasyncid.js6
-rw-r--r--tools/doc/type-parser.js4
-rwxr-xr-xtools/license-builder.sh6
-rw-r--r--vcbuild.bat5
234 files changed, 16 insertions, 83440 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 47f7380d36..a0e2650143 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -39,7 +39,7 @@
/doc/api/net.md @nodejs/net
/lib/dgram.js @nodejs/net
/lib/dns.js @nodejs/net
-/lib/net.js @nodejs/net @nodejs/quic
+/lib/net.js @nodejs/net
/lib/internal/dgram.js @nodejs/net
/lib/internal/dns/* @nodejs/net
/lib/internal/net.js @nodejs/net
@@ -59,7 +59,7 @@
/lib/crypto.js @nodejs/crypto
/lib/tls.js @nodejs/crypto @nodejs/net
/src/node_crypto* @nodejs/crypto
-/src/crypto/* @nodejs/crypto @nodejs/quic
+/src/crypto/* @nodejs/crypto
# http
@@ -68,7 +68,7 @@
/lib/_http_* @nodejs/http @nodejs/net
/lib/http.js @nodejs/http @nodejs/net
/lib/https.js @nodejs/crypto @nodejs/net @nodejs/http
-/src/node_http_common* @nodejs/http @nodejs/http2 @nodejs/quic @nodejs/net
+/src/node_http_common* @nodejs/http @nodejs/http2 @nodejs/net
/src/node_http_parser.cc @nodejs/http @nodejs/net
# http2
@@ -80,15 +80,6 @@
/src/node_http2* @nodejs/http2 @nodejs/net
/src/node_mem* @nodejs/http2
-# quic
-
-/deps/ngtcp2/ @nodejs/quic
-/deps/nghttp3/ @nodejs/quic
-/doc/api/quic.md @nodejs/quic
-/lib/internal/quic/ @nodejs/quic
-/src/node_bob* @nodejs/quic
-/src/quic/ @nodejs/quic
-
# modules
/doc/api/modules.md @nodejs/modules
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index 2a021723e6..d3e1e43392 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -14,7 +14,7 @@ env:
FLAKY_TESTS: dontcare
jobs:
- build-windows-with-quic:
+ build-windows:
if: github.event.pull_request.draft == false
runs-on: windows-latest
steps:
@@ -28,4 +28,4 @@ jobs:
- name: Environment Information
run: npx envinfo
- name: Build
- run: ./vcbuild.bat experimental-quic
+ run: ./vcbuild.bat
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 9d9b007b8f..4196813981 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -29,19 +29,3 @@ jobs:
run: make build-ci -j2 V=1 CONFIG_FLAGS="--error-on-warn"
- name: Test
run: make run-ci -j2 V=1 TEST_CI_ARGS="-p actions"
-
- test-linux-with-quic:
- if: github.event.pull_request.draft == false
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@v2
- with:
- python-version: ${{ env.PYTHON_VERSION }}
- - name: Environment Information
- run: npx envinfo
- - name: Build
- run: make build-ci -j2 V=1 CONFIG_FLAGS="--error-on-warn --experimental-quic"
- - name: Test
- run: make run-ci -j2 V=1 TEST_CI_ARGS="-p actions"
diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml
index a476e6a08c..462e2ea35b 100644
--- a/.github/workflows/test-macos.yml
+++ b/.github/workflows/test-macos.yml
@@ -14,7 +14,7 @@ env:
FLAKY_TESTS: dontcare
jobs:
- test-macOS-with-quic:
+ test-macOS:
if: github.event.pull_request.draft == false
runs-on: macos-latest
steps:
@@ -26,6 +26,6 @@ jobs:
- name: Environment Information
run: npx envinfo
- name: Build
- run: make build-ci -j2 V=1 CONFIG_FLAGS="--error-on-warn --experimental-quic"
+ run: make build-ci -j2 V=1 CONFIG_FLAGS="--error-on-warn"
- name: Test
run: make run-ci -j2 V=1 TEST_CI_ARGS="-p actions"
diff --git a/LICENSE b/LICENSE
index 2d4040e537..a62f3ad825 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1333,58 +1333,6 @@ The externally maintained libraries used by Node.js are:
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
-- ngtcp2, located at deps/ngtcp2, is licensed as follows:
- """
- The MIT License
-
- Copyright (c) 2016 ngtcp2 contributors
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- """
-
-- nghttp3, located at deps/nghttp3, is licensed as follows:
- """
- The MIT License
-
- Copyright (c) 2019 nghttp3 contributors
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- """
-
- node-inspect, located at deps/node-inspect, is licensed as follows:
"""
Copyright Node.js contributors. All rights reserved.
diff --git a/configure.py b/configure.py
index 8ed8524b26..096d40a13a 100755
--- a/configure.py
+++ b/configure.py
@@ -122,12 +122,6 @@ parser.add_argument('--error-on-warn',
default=None,
help='Turn compiler warnings into errors for node core sources.')
-parser.add_argument('--experimental-quic',
- action='store_true',
- dest='experimental_quic',
- default=None,
- help='enable experimental quic support')
-
parser.add_argument('--gdb',
action='store_true',
dest='gdb',
@@ -289,50 +283,6 @@ shared_optgroup.add_argument('--shared-nghttp2-libpath',
dest='shared_nghttp2_libpath',
help='a directory to search for the shared nghttp2 DLLs')
-shared_optgroup.add_argument('--shared-ngtcp2',
- action='store_true',
- dest='shared_ngtcp2',
- default=None,
- help='link to a shared ngtcp2 DLL instead of static linking')
-
-shared_optgroup.add_argument('--shared-ngtcp2-includes',
- action='store',
- dest='shared_ngtcp2_includes',
- help='directory containing ngtcp2 header files')
-
-shared_optgroup.add_argument('--shared-ngtcp2-libname',
- action='store',
- dest='shared_ngtcp2_libname',
- default='ngtcp2',
- help='alternative lib name to link to [default: %(default)s]')
-
-shared_optgroup.add_argument('--shared-ngtcp2-libpath',
- action='store',
- dest='shared_ngtcp2_libpath',
- help='a directory to search for the shared ngtcp2 DLLs')
-
-shared_optgroup.add_argument('--shared-nghttp3',
- action='store_true',
- dest='shared_nghttp3',
- default=None,
- help='link to a shared nghttp3 DLL instead of static linking')
-
-shared_optgroup.add_argument('--shared-nghttp3-includes',
- action='store',
- dest='shared_nghttp3_includes',
- help='directory containing nghttp3 header files')
-
-shared_optgroup.add_argument('--shared-nghttp3-libname',
- action='store',
- dest='shared_nghttp3_libname',
- default='nghttp3',
- help='alternative lib name to link to [default: %(default)s]')
-
-shared_optgroup.add_argument('--shared-nghttp3-libpath',
- action='store',
- dest='shared_nghttp3_libpath',
- help='a directory to search for the shared nghttp3 DLLs')
-
shared_optgroup.add_argument('--shared-openssl',
action='store_true',
dest='shared_openssl',
@@ -1290,14 +1240,6 @@ def configure_node(o):
else:
o['variables']['debug_nghttp2'] = 'false'
- if options.experimental_quic:
- if options.shared_openssl:
- raise Exception('QUIC requires a modified version of OpenSSL and '
- 'cannot be enabled when using --shared-openssl.')
- o['variables']['experimental_quic'] = 1
- else:
- o['variables']['experimental_quic'] = 'false'
-
o['variables']['node_no_browser_globals'] = b(options.no_browser_globals)
o['variables']['node_shared'] = b(options.shared)
@@ -1421,8 +1363,6 @@ def configure_openssl(o):
without_ssl_error('--openssl-fips')
if options.openssl_default_cipher_list:
without_ssl_error('--openssl-default-cipher-list')
- if options.experimental_quic:
- without_ssl_error('--experimental-quic')
return
if options.use_openssl_ca_store:
diff --git a/deps/nghttp3/COPYING b/deps/nghttp3/COPYING
deleted file mode 100644
index 37562ea58c..0000000000
--- a/deps/nghttp3/COPYING
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License
-
-Copyright (c) 2019 nghttp3 contributors
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/deps/nghttp3/lib/includes/config.h b/deps/nghttp3/lib/includes/config.h
deleted file mode 100644
index 0aee7749ba..0000000000
--- a/deps/nghttp3/lib/includes/config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-/* Edited to match src/node.h. */
-#include <stdint.h>
-
-#ifdef _WIN32
-#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
-typedef intptr_t ssize_t;
-# define _SSIZE_T_
-# define _SSIZE_T_DEFINED
-#endif
-#else // !_WIN32
-# include <sys/types.h> // size_t, ssize_t
-#endif // _WIN32
-
-#ifdef _MSC_VER
-# include <intrin.h>
-# define __builtin_popcount __popcnt
-#endif
-
-/* Define to 1 to enable debug output. */
-/* #undef DEBUGBUILD */
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-/* #undef HAVE_ARPA_INET_H */
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
diff --git a/deps/nghttp3/lib/includes/nghttp3/nghttp3.h b/deps/nghttp3/lib/includes/nghttp3/nghttp3.h
deleted file mode 100644
index 3ace46856b..0000000000
--- a/deps/nghttp3/lib/includes/nghttp3/nghttp3.h
+++ /dev/null
@@ -1,1801 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2018 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2017 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_H
-#define NGHTTP3_H
-
-/* Define WIN32 when build target is Win32 API (borrowed from
- libcurl) */
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-/* MSVC < 2013 does not have inttypes.h because it is not C99
- compliant. See compiler macros and version number in
- https://sourceforge.net/p/predef/wiki/Compilers/ */
-# include <stdint.h>
-#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
-# include <inttypes.h>
-#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
-#include <sys/types.h>
-#include <stdarg.h>
-#include <stddef.h>
-
-#include <nghttp3/version.h>
-
-#ifdef NGHTTP3_STATICLIB
-# define NGHTTP3_EXTERN
-#elif defined(WIN32)
-# ifdef BUILDING_NGHTTP3
-# define NGHTTP3_EXTERN __declspec(dllexport)
-# else /* !BUILDING_NGHTTP3 */
-# define NGHTTP3_EXTERN __declspec(dllimport)
-# endif /* !BUILDING_NGHTTP3 */
-#else /* !defined(WIN32) */
-# ifdef BUILDING_NGHTTP3
-# define NGHTTP3_EXTERN __attribute__((visibility("default")))
-# else /* !BUILDING_NGHTTP3 */
-# define NGHTTP3_EXTERN
-# endif /* !BUILDING_NGHTTP3 */
-#endif /* !defined(WIN32) */
-
-typedef ptrdiff_t nghttp3_ssize;
-
-/* NGHTTP3_ALPN_H3 is a serialized form of HTTP/3 ALPN protocol
- identifier this library supports. Notice that the first byte is
- the length of the following protocol identifier. */
-#define NGHTTP3_ALPN_H3 "\x5h3-29"
-
-typedef enum {
- NGHTTP3_ERR_INVALID_ARGUMENT = -101,
- NGHTTP3_ERR_NOBUF = -102,
- NGHTTP3_ERR_INVALID_STATE = -103,
- NGHTTP3_ERR_WOULDBLOCK = -104,
- NGHTTP3_ERR_STREAM_IN_USE = -105,
- NGHTTP3_ERR_PUSH_ID_BLOCKED = -106,
- NGHTTP3_ERR_MALFORMED_HTTP_HEADER = -107,
- NGHTTP3_ERR_REMOVE_HTTP_HEADER = -108,
- NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING = -109,
- NGHTTP3_ERR_TOO_LATE = -110,
- NGHTTP3_ERR_QPACK_FATAL = -111,
- NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE = -112,
- NGHTTP3_ERR_IGNORE_STREAM = -113,
- NGHTTP3_ERR_STREAM_NOT_FOUND = -114,
- NGHTTP3_ERR_IGNORE_PUSH_PROMISE = -115,
- NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED = -402,
- NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR = -403,
- NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR = -404,
- NGHTTP3_ERR_H3_FRAME_UNEXPECTED = -408,
- NGHTTP3_ERR_H3_FRAME_ERROR = -409,
- NGHTTP3_ERR_H3_MISSING_SETTINGS = -665,
- NGHTTP3_ERR_H3_INTERNAL_ERROR = -667,
- NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM = -668,
- NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR = -669,
- NGHTTP3_ERR_H3_ID_ERROR = -670,
- NGHTTP3_ERR_H3_SETTINGS_ERROR = -671,
- NGHTTP3_ERR_H3_STREAM_CREATION_ERROR = -672,
- NGHTTP3_ERR_FATAL = -900,
- NGHTTP3_ERR_NOMEM = -901,
- NGHTTP3_ERR_CALLBACK_FAILURE = -902
-} nghttp3_lib_error;
-
-#define NGHTTP3_H3_NO_ERROR 0x0100
-#define NGHTTP3_H3_GENERAL_PROTOCOL_ERROR 0x0101
-#define NGHTTP3_H3_INTERNAL_ERROR 0x0102
-#define NGHTTP3_H3_STREAM_CREATION_ERROR 0x0103
-#define NGHTTP3_H3_CLOSED_CRITICAL_STREAM 0x0104
-#define NGHTTP3_H3_FRAME_UNEXPECTED 0x0105
-#define NGHTTP3_H3_FRAME_ERROR 0x0106
-#define NGHTTP3_H3_EXCESSIVE_LOAD 0x0107
-#define NGHTTP3_H3_ID_ERROR 0x0108
-#define NGHTTP3_H3_SETTINGS_ERROR 0x0109
-#define NGHTTP3_H3_MISSING_SETTINGS 0x010a
-#define NGHTTP3_H3_REQUEST_REJECTED 0x010b
-#define NGHTTP3_H3_REQUEST_CANCELLED 0x010c
-#define NGHTTP3_H3_REQUEST_INCOMPLETE 0x010d
-#define NGHTTP3_H3_CONNECT_ERROR 0x010f
-#define NGHTTP3_H3_VERSION_FALLBACK 0x0110
-#define NGHTTP3_QPACK_DECOMPRESSION_FAILED 0x0200
-#define NGHTTP3_QPACK_ENCODER_STREAM_ERROR 0x0201
-#define NGHTTP3_QPACK_DECODER_STREAM_ERROR 0x0202
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace malloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`nghttp3_mem` structure.
- */
-typedef void *(*nghttp3_malloc)(size_t size, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace free(). The |mem_user_data| is
- * the mem_user_data member of :type:`nghttp3_mem` structure.
- */
-typedef void (*nghttp3_free)(void *ptr, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace calloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`nghttp3_mem` structure.
- */
-typedef void *(*nghttp3_calloc)(size_t nmemb, size_t size, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace realloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`nghttp3_mem` structure.
- */
-typedef void *(*nghttp3_realloc)(void *ptr, size_t size, void *mem_user_data);
-
-/**
- * @struct
- *
- * Custom memory allocator functions and user defined pointer. The
- * |mem_user_data| member is passed to each allocator function. This
- * can be used, for example, to achieve per-session memory pool.
- *
- * In the following example code, ``my_malloc``, ``my_free``,
- * ``my_calloc`` and ``my_realloc`` are the replacement of the
- * standard allocators ``malloc``, ``free``, ``calloc`` and
- * ``realloc`` respectively::
- *
- * void *my_malloc_cb(size_t size, void *mem_user_data) {
- * return my_malloc(size);
- * }
- *
- * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); }
- *
- * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) {
- * return my_calloc(nmemb, size);
- * }
- *
- * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) {
- * return my_realloc(ptr, size);
- * }
- *
- * void conn_new() {
- * nghttp3_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb,
- * my_realloc_cb};
- *
- * ...
- * }
- */
-typedef struct {
- /**
- * An arbitrary user supplied data. This is passed to each
- * allocator function.
- */
- void *mem_user_data;
- /**
- * Custom allocator function to replace malloc().
- */
- nghttp3_malloc malloc;
- /**
- * Custom allocator function to replace free().
- */
- nghttp3_free free;
- /**
- * Custom allocator function to replace calloc().
- */
- nghttp3_calloc calloc;
- /**
- * Custom allocator function to replace realloc().
- */
- nghttp3_realloc realloc;
-} nghttp3_mem;
-
-/**
- * @function
- *
- * `nghttp3_mem_default` returns the default memory allocator which
- * uses malloc/calloc/realloc/free.
- */
-NGHTTP3_EXTERN const nghttp3_mem *nghttp3_mem_default(void);
-
-/**
- * @struct
- *
- * nghttp3_vec is struct iovec compatible structure to reference
- * arbitrary array of bytes.
- */
-typedef struct {
- /**
- * base points to the data.
- */
- uint8_t *base;
- /**
- * len is the number of bytes which the buffer pointed by base
- * contains.
- */
- size_t len;
-} nghttp3_vec;
-
-struct nghttp3_rcbuf;
-
-/**
- * @struct
- *
- * :type:`nghttp3_rcbuf` is the object representing reference counted
- * buffer. The details of this structure are intentionally hidden
- * from the public API.
- */
-typedef struct nghttp3_rcbuf nghttp3_rcbuf;
-
-/**
- * @function
- *
- * `nghttp3_rcbuf_incref` increments the reference count of |rcbuf| by
- * 1.
- */
-NGHTTP3_EXTERN void nghttp3_rcbuf_incref(nghttp3_rcbuf *rcbuf);
-
-/**
- * @function
- *
- * `nghttp3_rcbuf_decref` decrements the reference count of |rcbuf| by
- * 1. If the reference count becomes zero, the object pointed by
- * |rcbuf| will be freed. In this case, application must not use
- * |rcbuf| again.
- */
-NGHTTP3_EXTERN void nghttp3_rcbuf_decref(nghttp3_rcbuf *rcbuf);
-
-/**
- * @function
- *
- * `nghttp3_rcbuf_get_buf` returns the underlying buffer managed by
- * |rcbuf|.
- */
-NGHTTP3_EXTERN nghttp3_vec nghttp3_rcbuf_get_buf(const nghttp3_rcbuf *rcbuf);
-
-/**
- * @function
- *
- * `nghttp3_rcbuf_is_static` returns nonzero if the underlying buffer
- * is statically allocated, and 0 otherwise. This can be useful for
- * language bindings that wish to avoid creating duplicate strings for
- * these buffers.
- */
-NGHTTP3_EXTERN int nghttp3_rcbuf_is_static(const nghttp3_rcbuf *rcbuf);
-
-/**
- * @struct
- *
- * :type:`nghttp3_buf` is the variable size buffer.
- */
-typedef struct {
- /**
- * begin points to the beginning of the buffer.
- */
- uint8_t *begin;
- /**
- * end points to the one beyond of the last byte of the buffer
- */
- uint8_t *end;
- /**
- * pos pointers to the start of data. Typically, this points to the
- * point that next data should be read. Initially, it points to
- * |begin|.
- */
- uint8_t *pos;
- /**
- * last points to the one beyond of the last data of the buffer.
- * Typically, new data is written at this point. Initially, it
- * points to |begin|.
- */
- uint8_t *last;
-} nghttp3_buf;
-
-/**
- * @function
- *
- * `nghttp3_buf_init` initializes empty |buf|.
- */
-NGHTTP3_EXTERN void nghttp3_buf_init(nghttp3_buf *buf);
-
-/**
- * @function
- *
- * `nghttp3_buf_free` frees resources allocated for |buf| using |mem|
- * as memory allocator. buf->begin must be a heap buffer allocated by
- * |mem|.
- */
-NGHTTP3_EXTERN void nghttp3_buf_free(nghttp3_buf *buf, const nghttp3_mem *mem);
-
-/**
- * @function
- *
- * `nghttp3_buf_left` returns the number of additional bytes which can
- * be written to the underlying buffer. In other words, it returns
- * buf->end - buf->last.
- */
-NGHTTP3_EXTERN size_t nghttp3_buf_left(const nghttp3_buf *buf);
-
-/**
- * @function
- *
- * `nghttp3_buf_len` returns the number of bytes left to read. In
- * other words, it returns buf->last - buf->pos.
- */
-NGHTTP3_EXTERN size_t nghttp3_buf_len(const nghttp3_buf *buf);
-
-/**
- * @function
- *
- * `nghttp3_buf_reset` sets buf->pos and buf->last to buf->begin.
- */
-NGHTTP3_EXTERN void nghttp3_buf_reset(nghttp3_buf *buf);
-
-/**
- * @enum
- *
- * :type:`nghttp3_nv_flag` is the flags for header field name/value
- * pair.
- */
-typedef enum {
- /**
- * :enum:`NGHTTP3_NV_FLAG_NONE` indicates no flag set.
- */
- NGHTTP3_NV_FLAG_NONE = 0,
- /**
- * :enum:`NGHTTP3_NV_FLAG_NEVER_INDEX` indicates that this
- * name/value pair must not be indexed. Other implementation calls
- * this bit as "sensitive".
- */
- NGHTTP3_NV_FLAG_NEVER_INDEX = 0x01,
- /**
- * :enum:`NGHTTP3_NV_FLAG_NO_COPY_NAME` is set solely by
- * application. If this flag is set, the library does not make a
- * copy of header field name. This could improve performance.
- */
- NGHTTP3_NV_FLAG_NO_COPY_NAME = 0x02,
- /**
- * :enum:`NGHTTP3_NV_FLAG_NO_COPY_VALUE` is set solely by
- * application. If this flag is set, the library does not make a
- * copy of header field value. This could improve performance.
- */
- NGHTTP3_NV_FLAG_NO_COPY_VALUE = 0x04
-} nghttp3_nv_flag;
-
-/**
- * @struct
- *
- * :type:`nghttp3_nv` is the name/value pair, which mainly used to
- * represent header fields.
- */
-typedef struct {
- /**
- * name is the header field name.
- */
- uint8_t *name;
- /**
- * value is the header field value.
- */
- uint8_t *value;
- /**
- * namelen is the length of the |name|, excluding terminating NULL.
- */
- size_t namelen;
- /**
- * valuelen is the length of the |value|, excluding terminating
- * NULL.
- */
- size_t valuelen;
- /**
- * flags is bitwise OR of one or more of :type:`nghttp3_nv_flag`.
- */
- uint8_t flags;
-} nghttp3_nv;
-
-/* Generated by mkstatichdtbl.py */
-typedef enum {
- NGHTTP3_QPACK_TOKEN__AUTHORITY = 0,
- NGHTTP3_QPACK_TOKEN__PATH = 8,
- NGHTTP3_QPACK_TOKEN_AGE = 43,
- NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION = 52,
- NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH = 55,
- NGHTTP3_QPACK_TOKEN_COOKIE = 68,
- NGHTTP3_QPACK_TOKEN_DATE = 69,
- NGHTTP3_QPACK_TOKEN_ETAG = 71,
- NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE = 74,
- NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH = 75,
- NGHTTP3_QPACK_TOKEN_LAST_MODIFIED = 77,
- NGHTTP3_QPACK_TOKEN_LINK = 78,
- NGHTTP3_QPACK_TOKEN_LOCATION = 79,
- NGHTTP3_QPACK_TOKEN_REFERER = 83,
- NGHTTP3_QPACK_TOKEN_SET_COOKIE = 85,
- NGHTTP3_QPACK_TOKEN__METHOD = 1,
- NGHTTP3_QPACK_TOKEN__SCHEME = 9,
- NGHTTP3_QPACK_TOKEN__STATUS = 11,
- NGHTTP3_QPACK_TOKEN_ACCEPT = 25,
- NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING = 27,
- NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES = 29,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS = 32,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 38,
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL = 46,
- NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING = 53,
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE = 57,
- NGHTTP3_QPACK_TOKEN_RANGE = 82,
- NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY = 86,
- NGHTTP3_QPACK_TOKEN_VARY = 92,
- NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS = 94,
- NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION = 98,
- NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE = 28,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS = 30,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS = 35,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS = 39,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS = 40,
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD = 41,
- NGHTTP3_QPACK_TOKEN_ALT_SVC = 44,
- NGHTTP3_QPACK_TOKEN_AUTHORIZATION = 45,
- NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY = 56,
- NGHTTP3_QPACK_TOKEN_EARLY_DATA = 70,
- NGHTTP3_QPACK_TOKEN_EXPECT_CT = 72,
- NGHTTP3_QPACK_TOKEN_FORWARDED = 73,
- NGHTTP3_QPACK_TOKEN_IF_RANGE = 76,
- NGHTTP3_QPACK_TOKEN_ORIGIN = 80,
- NGHTTP3_QPACK_TOKEN_PURPOSE = 81,
- NGHTTP3_QPACK_TOKEN_SERVER = 84,
- NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN = 89,
- NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS = 90,
- NGHTTP3_QPACK_TOKEN_USER_AGENT = 91,
- NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR = 95,
- NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS = 96,
- /* Additional header fields for HTTP messaging validation */
- NGHTTP3_QPACK_TOKEN_HOST = 1000,
- NGHTTP3_QPACK_TOKEN_CONNECTION,
- NGHTTP3_QPACK_TOKEN_KEEP_ALIVE,
- NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION,
- NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING,
- NGHTTP3_QPACK_TOKEN_UPGRADE,
- NGHTTP3_QPACK_TOKEN_TE,
- NGHTTP3_QPACK_TOKEN__PROTOCOL,
- NGHTTP3_QPACK_TOKEN_PRIORITY
-} nghttp3_qpack_token;
-
-/**
- * @struct
- *
- * nghttp3_qpack_nv represents header field name/value pair just like
- * :type:`nghttp3_nv`. It is an extended version of
- * :type:`nghttp3_nv` and has reference counted buffers and tokens
- * which might be useful for applications.
- */
-typedef struct {
- /* The buffer containing header field name. NULL-termination is
- guaranteed. */
- nghttp3_rcbuf *name;
- /* The buffer containing header field value. NULL-termination is
- guaranteed. */
- nghttp3_rcbuf *value;
- /* nghttp3_qpack_token value for name. It could be -1 if we have no
- token for that header field name. */
- int32_t token;
- /* Bitwise OR of one or more of nghttp3_nv_flag. */
- uint8_t flags;
-} nghttp3_qpack_nv;
-
-struct nghttp3_qpack_encoder;
-
-/**
- * @struct
- *
- * :type:`nghttp3_qpack_encoder` is QPACK encoder.
- */
-typedef struct nghttp3_qpack_encoder nghttp3_qpack_encoder;
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_new` initializes QPACK encoder. |pencoder|
- * must be non-NULL pointer. |max_dtable_size| is the maximum dynamic
- * table size. |max_blocked| is the maximum number of streams which
- * can be blocked. |mem| is a memory allocator. This function
- * allocates memory for :type:`nghttp3_qpack_encoder` itself and
- * assigns its pointer to |*pencoder| if it succeeds.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- */
-NGHTTP3_EXTERN int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
- size_t max_dtable_size,
- size_t max_blocked,
- const nghttp3_mem *mem);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_del` frees memory allocated for |encoder|.
- * This function frees memory pointed by |encoder| itself.
- */
-NGHTTP3_EXTERN void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_encode` encodes the list of header fields
- * |nva|. |nvlen| is the length of |nva|. |stream_id| is the
- * identifier of the stream which this header fields belong to. This
- * function writes header block prefix, encoded header fields, and
- * encoder stream to |pbuf|, |rbuf|, and |ebuf| respectively. The
- * last field of nghttp3_buf will be adjusted when data is written.
- * An application should write |pbuf| and |rbuf| to the request stream
- * in this order.
- *
- * The buffer pointed by |pbuf|, |rbuf|, and |ebuf| can be empty
- * buffer. It is fine to pass a buffer initialized by
- * nghttp3_buf_init(buf). This function allocates memory for these
- * buffers as necessary. In particular, it frees and expands buffer
- * if the current capacity of buffer is not enough. If begin field of
- * any buffer is not NULL, it must be allocated by the same memory
- * allocator passed to `nghttp3_qpack_encoder_new()`.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory
- * :enum:`NGHTTP3_ERR_QPACK_FATAL`
- * |encoder| is in unrecoverable error state and cannot be used
- * anymore.
- */
-NGHTTP3_EXTERN int nghttp3_qpack_encoder_encode(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *pbuf, nghttp3_buf *rbuf,
- nghttp3_buf *ebuf, int64_t stream_id, const nghttp3_nv *nva, size_t nvlen);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_read_decoder` reads decoder stream. The
- * buffer pointed by |src| of length |srclen| contains decoder stream.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory
- * :enum:`NGHTTP3_ERR_QPACK_FATAL`
- * |encoder| is in unrecoverable error state and cannot be used
- * anymore.
- * :enum:`NGHTTP3_ERR_QPACK_DECODER_STREAM`
- * |encoder| is unable to process input because it is malformed.
- */
-NGHTTP3_EXTERN nghttp3_ssize nghttp3_qpack_encoder_read_decoder(
- nghttp3_qpack_encoder *encoder, const uint8_t *src, size_t srclen);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_set_max_dtable_size` sets max dynamic table
- * size to |max_dtable_size|.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * :enum:`NGHTTP3_ERR_INVALID_ARGUMENT`
- * |max_dtable_size| exceeds the hard limit that decoder specifies.
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_encoder_set_max_dtable_size(nghttp3_qpack_encoder *encoder,
- size_t max_dtable_size);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_set_hard_max_dtable_size` sets hard maximum
- * dynamic table size to |hard_max_dtable_size|.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * TBD
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_encoder_set_hard_max_dtable_size(nghttp3_qpack_encoder *encoder,
- size_t hard_max_dtable_size);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_set_max_blocked` sets the number of streams
- * which can be blocked to |max_blocked|.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * TBD
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_encoder_set_max_blocked(nghttp3_qpack_encoder *encoder,
- size_t max_blocked);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_ack_header` tells |encoder| that header
- * block for a stream denoted by |stream_id| was acknowledged by
- * decoder. This function is provided for debugging purpose only. In
- * HTTP/3, |encoder| knows acknowledgement of header block by reading
- * decoder stream with `nghttp3_qpack_encoder_read_decoder()`.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_encoder_ack_header(nghttp3_qpack_encoder *encoder,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_add_insert_count` increments known received
- * count of |encoder| by |n|. This function is provided for debugging
- * purpose only. In HTTP/3, |encoder| increments known received count
- * by reading decoder stream with
- * `nghttp3_qpack_encoder_read_decoder()`.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- * :enum:`NGHTTP3_QPACK_DECODER_STREAM`
- * |n| is too large.
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_encoder_add_insert_count(nghttp3_qpack_encoder *encoder,
- uint64_t n);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_ack_everything` tells |encoder| that all
- * encoded header blocks are acknowledged. This function is provided
- * for debugging purpose only. In HTTP/3, |encoder| knows this by
- * reading decoder stream with `nghttp3_qpack_encoder_read_decoder()`.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_encoder_ack_everything(nghttp3_qpack_encoder *encoder);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_cancel_stream` tells |encoder| that stream
- * denoted by |stream_id| is cancelled. This function is provided for
- * debugging purpose only. In HTTP/3, |encoder| knows this by reading
- * decoder stream with `nghttp3_qpack_encoder_read_decoder()`.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_encoder_cancel_stream(nghttp3_qpack_encoder *encoder,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_qpack_encoder_get_num_blocked` returns the number of
- * streams which is potentially blocked at decoder side.
- */
-NGHTTP3_EXTERN size_t
-nghttp3_qpack_encoder_get_num_blocked(nghttp3_qpack_encoder *encoder);
-
-struct nghttp3_qpack_stream_context;
-
-/**
- * @struct
- *
- * :type:`nghttp3_qpack_stream_context` is a decoder context for an
- * individual stream.
- */
-typedef struct nghttp3_qpack_stream_context nghttp3_qpack_stream_context;
-
-/**
- * @function
- *
- * `nghttp3_qpack_stream_context_new` initializes stream context.
- * |psctx| must be non-NULL pointer. |stream_id| is stream ID. |mem|
- * is a memory allocator. This function allocates memory for
- * :type:`nghttp3_qpack_stream_context` itself and assigns its pointer
- * to |*psctx| if it succeeds.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx,
- int64_t stream_id, const nghttp3_mem *mem);
-
-/**
- * @function
- *
- * `nghttp3_qpack_stream_context_del` frees memory allocated for
- * |sctx|. This function frees memory pointed by |sctx| itself.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_stream_context_del(nghttp3_qpack_stream_context *sctx);
-
-/**
- * @function
- *
- * `nghttp3_qpack_stream_context_get_ricnt` returns required insert
- * count.
- */
-NGHTTP3_EXTERN uint64_t
-nghttp3_qpack_stream_context_get_ricnt(nghttp3_qpack_stream_context *sctx);
-
-struct nghttp3_qpack_decoder;
-
-/**
- * @struct
- *
- * `nghttp3_qpack_decoder` is QPACK decoder.
- */
-typedef struct nghttp3_qpack_decoder nghttp3_qpack_decoder;
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_new` initializes QPACK decoder. |pdecoder|
- * must be non-NULL pointer. |max_dtable_size| is the maximum dynamic
- * table size. |max_blocked| is the maximum number of streams which
- * can be blocked. |mem| is a memory allocator. This function
- * allocates memory for :type:`nghttp3_qpack_decoder` itself and
- * assigns its pointer to |*pdecoder| if it succeeds.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- */
-NGHTTP3_EXTERN int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
- size_t max_dtable_size,
- size_t max_blocked,
- const nghttp3_mem *mem);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_del` frees memory allocated for |decoder|.
- * This function frees memory pointed by |decoder| itself.
- */
-NGHTTP3_EXTERN void nghttp3_qpack_decoder_del(nghttp3_qpack_decoder *decoder);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_read_encoder` reads encoder stream. The
- * buffer pointed by |src| of length |srclen| contains encoder stream.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- * :enum:`NGHTTP3_ERR_QPACK_FATAL`
- * |decoder| is in unrecoverable error state and cannot be used
- * anymore.
- * :enum:`NGHTTP3_ERR_QPACK_ENCODER_STREAM`
- * Could not interpret encoder stream instruction.
- */
-NGHTTP3_EXTERN nghttp3_ssize nghttp3_qpack_decoder_read_encoder(
- nghttp3_qpack_decoder *decoder, const uint8_t *src, size_t srclen);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_get_icnt` returns insert count.
- */
-NGHTTP3_EXTERN uint64_t
-nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder);
-
-/**
- * @enum
- *
- * :type:`nghttp3_qpack_decode_flag` is a set of flags for decoder.
- */
-typedef enum {
- /**
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_NONE` indicates that no flag
- * set.
- */
- NGHTTP3_QPACK_DECODE_FLAG_NONE,
- /**
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_EMIT` indicates that a header
- * field is successfully decoded.
- */
- NGHTTP3_QPACK_DECODE_FLAG_EMIT = 0x01,
- /**
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` indicates that all header
- * fields have been decoded.
- */
- NGHTTP3_QPACK_DECODE_FLAG_FINAL = 0x02,
- /**
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_BLOCKED` indicates that decoding
- * has been blocked.
- */
- NGHTTP3_QPACK_DECODE_FLAG_BLOCKED = 0x04
-} nghttp3_qpack_decode_flag;
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_read_request` reads request stream. The
- * request stream is given as the buffer pointed by |src| of length
- * |srclen|. |sctx| is the stream context and it must be initialized
- * by `nghttp3_qpack_stream_context_init()`. |*pflags| must be
- * non-NULL pointer. |nv| must be non-NULL pointer.
- *
- * If this function succeeds, it assigns flags to |*pflags|. If
- * |*pflags| has :enum:`NGHTTP3_QPACK_DECODE_FLAG_EMIT` set, a decoded
- * header field is assigned to |nv|. If |*pflags| has
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_FINAL` set, all header fields have
- * been successfully decoded. If |*pflags| has
- * :enum:`NGHTTP3_QPACK_DECODE_FLAG_BLOCKED` set, decoding is blocked
- * due to required insert count.
- *
- * When a header field is decoded, an application receives it in |nv|.
- * nv->name and nv->value are reference counted buffer, and their
- * reference counts are already incremented for application use.
- * Therefore, when application finishes processing the header field,
- * it must call nghttp3_rcbuf_decref(nv->name) and
- * nghttp3_rcbuf_decref(nv->value) or memory leak might occur.
- *
- * This function returns the number of bytes read, or one of the
- * following negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- * :enum:`NGHTTP3_ERR_QPACK_FATAL`
- * |decoder| is in unrecoverable error state and cannot be used
- * anymore.
- * :enum:`NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED`
- * Could not interpret header block instruction.
- * :enum:`NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE`
- * Header field is too large.
- */
-NGHTTP3_EXTERN nghttp3_ssize nghttp3_qpack_decoder_read_request(
- nghttp3_qpack_decoder *decoder, nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv, uint8_t *pflags, const uint8_t *src, size_t srclen,
- int fin);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_write_decoder` writes decoder stream into
- * |dbuf|.
- *
- * The caller must ensure that nghttp3_buf_left(dbuf) >=
- * nghttp3_qpack_decoder_get_decoder_streamlen(decoder).
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_decoder_write_decoder(nghttp3_qpack_decoder *decoder,
- nghttp3_buf *dbuf);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_get_decoder_streamlen` returns the length of
- * decoder stream.
- */
-NGHTTP3_EXTERN size_t
-nghttp3_qpack_decoder_get_decoder_streamlen(nghttp3_qpack_decoder *decoder);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_cancel_stream` cancels header decoding for
- * stream denoted by |stream_id|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- * :enum:`NGHTTP3_ERR_QPACK_FATAL`
- * Decoder stream overflow.
- */
-NGHTTP3_EXTERN int
-nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_set_dtable_cap` sets |cap| as maximum
- * dynamic table size. Normally, the maximum capacity is communicated
- * in encoder stream. This function is provided for debugging and
- * testing purpose.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_decoder_set_dtable_cap(nghttp3_qpack_decoder *decoder,
- size_t cap);
-
-/**
- * @function
- *
- * `nghttp3_qpack_decoder_set_max_concurrent_streams` tells |decoder|
- * the maximum number of concurrent streams that a remote endpoint can
- * open, including both bidirectional and unidirectional streams which
- * potentially receive QPACK encoded HEADERS frame. This value is
- * used as a hint to limit the length of decoder stream.
- */
-NGHTTP3_EXTERN void
-nghttp3_qpack_decoder_set_max_concurrent_streams(nghttp3_qpack_decoder *decoder,
- size_t max_concurrent_streams);
-
-/**
- * @function
- *
- * `nghttp3_strerror` returns textual representation of |liberr| which
- * should be one of error codes defined in :type:`nghttp3_lib_error`.
- */
-NGHTTP3_EXTERN const char *nghttp3_strerror(int liberr);
-
-/**
- * @function
- *
- * `nghttp3_err_infer_quic_app_error_code` returns a QUIC application
- * error code which corresponds to |liberr|.
- */
-NGHTTP3_EXTERN uint64_t nghttp3_err_infer_quic_app_error_code(int liberr);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_debug_vprintf_callback` is a callback function
- * invoked when the library outputs debug logging. The function is
- * called with arguments suitable for ``vfprintf(3)``
- *
- * The debug output is only enabled if the library is built with
- * ``DEBUGBUILD`` macro defined.
- */
-typedef void (*nghttp3_debug_vprintf_callback)(const char *format,
- va_list args);
-
-/**
- * @function
- *
- * `nghttp3_set_debug_vprintf_callback` sets a debug output callback
- * called by the library when built with ``DEBUGBUILD`` macro defined.
- * If this option is not used, debug log is written into standard
- * error output.
- *
- * For builds without ``DEBUGBUILD`` macro defined, this function is
- * noop.
- *
- * Note that building with ``DEBUGBUILD`` may cause significant
- * performance penalty to libnghttp3 because of extra processing. It
- * should be used for debugging purpose only.
- *
- * .. Warning::
- *
- * Building with ``DEBUGBUILD`` may cause significant performance
- * penalty to libnghttp3 because of extra processing. It should be
- * used for debugging purpose only. We write this two times because
- * this is important.
- */
-NGHTTP3_EXTERN void nghttp3_set_debug_vprintf_callback(
- nghttp3_debug_vprintf_callback debug_vprintf_callback);
-
-struct nghttp3_conn;
-typedef struct nghttp3_conn nghttp3_conn;
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_acked_stream_data` is a callback function which is
- * invoked when data sent on stream denoted by |stream_id| supplied
- * from application is acknowledged by remote endpoint. The number of
- * bytes acknowledged is given in |datalen|.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_acked_stream_data)(nghttp3_conn *conn, int64_t stream_id,
- size_t datalen, void *conn_user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_conn_stream_close` is a callback function which is
- * invoked when a stream identified by |stream_id| is closed.
- * |app_error_code| indicates the reason of this closure.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_stream_close)(nghttp3_conn *conn, int64_t stream_id,
- uint64_t app_error_code,
- void *conn_user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_recv_data` is a callback function which is invoked
- * when a part of request or response body on stream identified by
- * |stream_id| is received. |data| points to the received data and
- * its length is |datalen|.
- *
- * The application is responsible for increasing flow control credit
- * by |datalen| bytes.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_recv_data)(nghttp3_conn *conn, int64_t stream_id,
- const uint8_t *data, size_t datalen,
- void *conn_user_data, void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_deferred_consume` is a callback function which is
- * invoked when the library consumed |consumed| bytes for a stream
- * identified by |stream_id|. This callback is used to notify the
- * consumed bytes for stream blocked by QPACK decoder. The
- * application is responsible for increasing flow control credit by
- * |consumed| bytes.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_deferred_consume)(nghttp3_conn *conn, int64_t stream_id,
- size_t consumed, void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_begin_headers)(nghttp3_conn *conn, int64_t stream_id,
- void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_recv_header)(nghttp3_conn *conn, int64_t stream_id,
- int32_t token, nghttp3_rcbuf *name,
- nghttp3_rcbuf *value, uint8_t flags,
- void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_end_headers)(nghttp3_conn *conn, int64_t stream_id,
- void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_begin_push_promise)(nghttp3_conn *conn, int64_t stream_id,
- int64_t push_id, void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_recv_push_promise)(nghttp3_conn *conn, int64_t stream_id,
- int64_t push_id, int32_t token,
- nghttp3_rcbuf *name,
- nghttp3_rcbuf *value, uint8_t flags,
- void *conn_user_data,
- void *stream_user_data);
-
-typedef int (*nghttp3_end_push_promise)(nghttp3_conn *conn, int64_t stream_id,
- int64_t push_id, void *conn_user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_end_stream` is a callback function which is invoked
- * when the receiving side of stream is closed. For server, this
- * callback function is invoked when HTTP request is received
- * completely. For client, this callback function is invoked when
- * HTTP response is received completely.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_end_stream)(nghttp3_conn *conn, int64_t stream_id,
- void *conn_user_data, void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_cancel_push` is a callback function which is invoked
- * when the push identified by |push_id| is cancelled by remote
- * endpoint. If a stream has been bound to the push ID, |stream_id|
- * contains the stream ID and |stream_user_data| points to the stream
- * user data. Otherwise, |stream_id| is -1 and |stream_user_data| is
- * NULL.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_cancel_push)(nghttp3_conn *conn, int64_t push_id,
- int64_t stream_id, void *conn_user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_send_stop_sending` is a callback function which is
- * invoked when the library asks application to send STOP_SENDING to
- * the stream identified by |stream_id|. |app_error_code| indicates
- * the reason for this action.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_send_stop_sending)(nghttp3_conn *conn, int64_t stream_id,
- uint64_t app_error_code,
- void *conn_user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_push_stream` is a callback function which is invoked
- * when a push stream identified by |stream_id| is opened with
- * |push_id|.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning :enum:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the
- * caller immediately. Any values other than 0 is treated as
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*nghttp3_push_stream)(nghttp3_conn *conn, int64_t push_id,
- int64_t stream_id, void *conn_user_data);
-
-typedef struct {
- nghttp3_acked_stream_data acked_stream_data;
- nghttp3_stream_close stream_close;
- nghttp3_recv_data recv_data;
- nghttp3_deferred_consume deferred_consume;
- nghttp3_begin_headers begin_headers;
- nghttp3_recv_header recv_header;
- nghttp3_end_headers end_headers;
- nghttp3_begin_headers begin_trailers;
- nghttp3_recv_header recv_trailer;
- nghttp3_end_headers end_trailers;
- nghttp3_begin_push_promise begin_push_promise;
- nghttp3_recv_push_promise recv_push_promise;
- nghttp3_end_push_promise end_push_promise;
- nghttp3_cancel_push cancel_push;
- nghttp3_send_stop_sending send_stop_sending;
- nghttp3_push_stream push_stream;
- nghttp3_end_stream end_stream;
-} nghttp3_conn_callbacks;
-
-typedef struct {
- uint64_t max_field_section_size;
- uint64_t max_pushes;
- size_t qpack_max_table_capacity;
- size_t qpack_blocked_streams;
-} nghttp3_conn_settings;
-
-NGHTTP3_EXTERN void
-nghttp3_conn_settings_default(nghttp3_conn_settings *settings);
-
-NGHTTP3_EXTERN int
-nghttp3_conn_client_new(nghttp3_conn **pconn,
- const nghttp3_conn_callbacks *callbacks,
- const nghttp3_conn_settings *settings,
- const nghttp3_mem *mem, void *conn_user_data);
-
-NGHTTP3_EXTERN int
-nghttp3_conn_server_new(nghttp3_conn **pconn,
- const nghttp3_conn_callbacks *callbacks,
- const nghttp3_conn_settings *settings,
- const nghttp3_mem *mem, void *conn_user_data);
-
-NGHTTP3_EXTERN void nghttp3_conn_del(nghttp3_conn *conn);
-
-/**
- * @function
- *
- * `nghttp3_conn_bind_control_stream` binds stream denoted by
- * |stream_id| to outgoing unidirectional control stream.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_INVALID_STATE`
- * Control stream has already corresponding stream ID.
- * TBD
- */
-NGHTTP3_EXTERN int nghttp3_conn_bind_control_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_bind_qpack_streams` binds stream denoted by
- * |qenc_stream_id| to outgoing QPACK encoder stream and stream
- * denoted by |qdec_stream_id| to outgoing QPACK encoder stream.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_INVALID_STATE`
- * QPACK encoder/decoder stream have already corresponding stream
- * IDs.
- * TBD
- */
-NGHTTP3_EXTERN int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn,
- int64_t qenc_stream_id,
- int64_t qdec_stream_id);
-
-/**
- * @function
- *
- * nghttp3_conn_read_stream reads data |src| of length |srclen| on
- * stream identified by |stream_id|. It returns the number of bytes
- * consumed. The "consumed" means that application can increase flow
- * control credit (both stream and connection) of underlying QUIC
- * connection by that amount. It does not include the amount of data
- * carried by DATA frame which contains application data (excluding
- * any control or QPACK unidirectional streams) . See
- * type:`nghttp3_recv_data` to handle those bytes. If |fin| is
- * nonzero, this is the last data from remote endpoint in this stream.
- */
-NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn,
- int64_t stream_id,
- const uint8_t *src,
- size_t srclen, int fin);
-
-/**
- * @function
- *
- * `nghttp3_conn_writev_stream` stores stream data to send to |vec| of
- * length |veccnt| and returns the number of nghttp3_vec object in
- * which it stored data. It stores stream ID to |*pstream_id|. An
- * application has to call `nghttp3_conn_add_write_offset` to inform
- * |conn| of the actual number of bytes that underlying QUIC stack
- * accepted. |*pfin| will be nonzero if this is the last data to
- * send. If there is no stream to write data or send fin, this
- * function returns 0, and -1 is assigned to |*pstream_id|.
- */
-NGHTTP3_EXTERN nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn,
- int64_t *pstream_id,
- int *pfin,
- nghttp3_vec *vec,
- size_t veccnt);
-
-/**
- * @function
- *
- * `nghttp3_conn_add_write_offset` tells |conn| the number of bytes
- * |n| for stream denoted by |stream_id| QUIC stack accepted.
- *
- * If stream has no data to send but just sends fin (closing the write
- * side of a stream), the number of bytes sent is 0. It is important
- * to call this function even if |n| is 0 in this case. It is safe to
- * call this function if |n| is 0.
- *
- * `nghttp3_conn_writev_stream` must be called before calling this
- * function to get data to send, and those data must be fed into QUIC
- * stack.
- */
-NGHTTP3_EXTERN int nghttp3_conn_add_write_offset(nghttp3_conn *conn,
- int64_t stream_id, size_t n);
-
-/**
- * @function
- *
- * `nghttp3_conn_add_ack_offset` tells |conn| the number of bytes |n|
- * for stream denoted by |stream_id| QUIC stack has acknowledged.
- */
-NGHTTP3_EXTERN int nghttp3_conn_add_ack_offset(nghttp3_conn *conn,
- int64_t stream_id, uint64_t n);
-
-/**
- * @function
- *
- * `nghttp3_conn_block_stream` tells the library that stream
- * identified by |stream_id| is blocked due to QUIC flow control.
- */
-NGHTTP3_EXTERN int nghttp3_conn_block_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_unblock_stream` tells the library that stream
- * identified by |stream_id| which was blocked by QUIC flow control is
- * unblocked.
- */
-NGHTTP3_EXTERN int nghttp3_conn_unblock_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_resume_stream` resumes stream identified by
- * |stream_id| which was previously unable to provide data.
- */
-NGHTTP3_EXTERN int nghttp3_conn_resume_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_close_stream` closes stream identified by
- * |stream_id|. |app_error_code| is the reason of the closure.
- */
-NGHTTP3_EXTERN int nghttp3_conn_close_stream(nghttp3_conn *conn,
- int64_t stream_id,
- uint64_t app_error_code);
-
-/**
- * @function
- *
- * `nghttp3_conn_reset_stream` must be called if stream identified by
- * |stream_id| is reset by a remote endpoint. This is required in
- * order to cancel QPACK stream.
- */
-NGHTTP3_EXTERN int nghttp3_conn_reset_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-typedef enum {
- NGHTTP3_DATA_FLAG_NONE = 0x00,
- /**
- * ``NGHTTP3_DATA_FLAG_EOF`` indicates that all request or response
- * body has been provided to the library. It also indicates that
- * sending side of stream is closed unless
- * :enum:`NGHTTP3_DATA_FLAG_NO_END_STREAM` is given at the same
- * time.
- */
- NGHTTP3_DATA_FLAG_EOF = 0x01,
- /**
- * ``NGHTTP3_DATA_FLAG_NO_END_STREAM`` indicates that sending side
- * of stream is not closed even if NGHTTP3_DATA_FLAG_EOF is set.
- * Usually this flag is used to send trailer fields with
- * `nghttp3_conn_submit_trailers()`. If
- * `nghttp3_conn_submit_trailers()` has been called, regardless of
- * this flag, the submitted trailer fields are sent.
- */
- NGHTTP3_DATA_FLAG_NO_END_STREAM = 0x02
-} nghttp3_data_flag;
-
-/**
- * @function
- *
- * `nghttp3_conn_set_max_client_streams_bidi` tells |conn| the
- * cumulative number of bidirectional streams that client can open.
- */
-NGHTTP3_EXTERN void
-nghttp3_conn_set_max_client_streams_bidi(nghttp3_conn *conn,
- uint64_t max_streams);
-
-/**
- * @function
- *
- * `nghttp3_conn_set_max_concurrent_streams` tells |conn| the maximum
- * number of concurrent streams that a remote endpoint can open,
- * including both bidirectional and unidirectional streams which
- * potentially receive QPACK encoded HEADERS frame. This value is
- * used as a hint to limit the internal resource consumption.
- */
-NGHTTP3_EXTERN void
-nghttp3_conn_set_max_concurrent_streams(nghttp3_conn *conn,
- size_t max_concurrent_streams);
-
-/**
- * @functypedef
- *
- * :type:`nghttp3_read_data_callback` is a callback function invoked
- * when the library asks an application to provide stream data for a
- * stream denoted by |stream_id|.
- *
- * The library provides |vec| of length |veccnt| to the application.
- * The application should fill data and its length to |vec|. It has
- * to return the number of the filled objects. The application must
- * retain data until they are safe to free. It is notified by
- * :type:`nghttp3_acked_stream_data` callback.
- *
- * If this is the last data to send (or there is no data to send
- * because all data have been sent already), set
- * :enum:`NGHTTP3_DATA_FLAG_EOF` to |*pflags|.
- *
- * If the application is unable to provide data temporarily, return
- * :enum:`NGHTTP3_ERR_WOULDBLOCK`. When it is ready to provide
- * data, call `nghttp3_conn_resume_stream()`.
- *
- * The callback should return the number of objects in |vec| that the
- * application filled if it succeeds, or
- * :enum:`NGHTTP3_ERR_CALLBACK_FAILURE`.
- *
- * TODO Add NGHTTP3_ERR_TEMPORAL_CALLBACK_FAILURE to reset just this
- * stream.
- */
-typedef nghttp3_ssize (*nghttp3_read_data_callback)(
- nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec, size_t veccnt,
- uint32_t *pflags, void *conn_user_data, void *stream_user_data);
-
-/**
- * @struct
- *
- * :type:`nghttp3_data_reader` specifies the way how to generate
- * request or response body.
- */
-typedef struct {
- /**
- * read_data is a callback function to generate body.
- */
- nghttp3_read_data_callback read_data;
-} nghttp3_data_reader;
-
-/**
- * @function
- *
- * `nghttp3_conn_submit_request` submits HTTP request header fields
- * and body on the stream identified by |stream_id|. |stream_id| must
- * be a client initiated bidirectional stream. Only client can submit
- * HTTP request. |nva| of length |nvlen| specifies HTTP request
- * header fields. |dr| specifies a request body. If there is no
- * request body, specify NULL. If |dr| is NULL, it implies the end of
- * stream. |stream_user_data| is an opaque pointer attached to the
- * stream.
- */
-NGHTTP3_EXTERN int nghttp3_conn_submit_request(
- nghttp3_conn *conn, int64_t stream_id, const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_data_reader *dr, void *stream_user_data);
-
-/**
- * @function
- *
- * `nghttp3_conn_submit_push_promise` submits push promise on the
- * stream identified by |stream_id|. |stream_id| must be a client
- * initiated bidirectional stream. Only server can submit push
- * promise. On success, a push ID is assigned to |*ppush_id|. |nva|
- * of length |nvlen| specifies HTTP request header fields. In order
- * to submit HTTP response, first call
- * `nghttp3_conn_bind_push_stream()` and then
- * `nghttp3_conn_submit_response()`.
- */
-NGHTTP3_EXTERN int nghttp3_conn_submit_push_promise(nghttp3_conn *conn,
- int64_t *ppush_id,
- int64_t stream_id,
- const nghttp3_nv *nva,
- size_t nvlen);
-
-/**
- * @function
- *
- * `nghttp3_conn_submit_info` submits HTTP non-final response header
- * fields on the stream identified by |stream_id|. |nva| of length
- * |nvlen| specifies HTTP response header fields.
- */
-NGHTTP3_EXTERN int nghttp3_conn_submit_info(nghttp3_conn *conn,
- int64_t stream_id,
- const nghttp3_nv *nva,
- size_t nvlen);
-
-/**
- * @function
- *
- * `nghttp3_conn_submit_response` submits HTTP response header fields
- * and body on the stream identified by |stream_id|. |nva| of length
- * |nvlen| specifies HTTP response header fields. |dr| specifies a
- * response body. If there is no response body, specify NULL. If
- * |dr| is NULL, it implies the end of stream.
- */
-NGHTTP3_EXTERN int nghttp3_conn_submit_response(nghttp3_conn *conn,
- int64_t stream_id,
- const nghttp3_nv *nva,
- size_t nvlen,
- const nghttp3_data_reader *dr);
-
-/**
- * @function
- *
- * `nghttp3_conn_submit_trailers` submits HTTP trailer fields on the
- * stream identified by |stream_id|. |nva| of length |nvlen|
- * specifies HTTP trailer fields. Calling this function implies the
- * end of stream.
- */
-NGHTTP3_EXTERN int nghttp3_conn_submit_trailers(nghttp3_conn *conn,
- int64_t stream_id,
- const nghttp3_nv *nva,
- size_t nvlen);
-
-/**
- * @function
- *
- * `nghttp3_conn_bind_push_stream` binds the stream identified by
- * |stream_id| to the push identified by |push_id|. |stream_id| must
- * be a server initiated unidirectional stream. |push_id| must be
- * obtained from `nghttp3_conn_submit_push_promise()`. To send
- * response to this push, call `nghttp3_conn_submit_response()`.
- */
-NGHTTP3_EXTERN int nghttp3_conn_bind_push_stream(nghttp3_conn *conn,
- int64_t push_id,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_cancel_push` cancels the push identified by
- * |push_id|. It is not possible to cancel the push after the
- * response stream opens. In that case, send RESET_STREAM (if |conn|
- * is server) or STOP_SENDING (if |conn| is client) on the underlying
- * QUIC stream.
- */
-NGHTTP3_EXTERN int nghttp3_conn_cancel_push(nghttp3_conn *conn,
- int64_t push_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_set_stream_user_data` sets |stream_user_data| to the
- * stream identified by |stream_id|.
- */
-NGHTTP3_EXTERN int nghttp3_conn_set_stream_user_data(nghttp3_conn *conn,
- int64_t stream_id,
- void *stream_user_data);
-
-/**
- * @function
- *
- * `nghttp3_conn_get_frame_payload_left` returns the number of bytes
- * left to read current frame payload for a stream denoted by
- * |stream_id|. If no such stream is found, it returns
- * :enum:`NGHTTP3_ERR_STREAM_NOT_FOUND`.
- */
-NGHTTP3_EXTERN int64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @macro
- *
- * :macro:`NGHTTP3_DEFAULT_URGENCY` is the default urgency level.
- */
-#define NGHTTP3_DEFAULT_URGENCY 1
-
-/**
- * @macro
- *
- * :macro:`NGHTTP3_URGENCY_HIGH` is the highest urgency level.
- */
-#define NGHTTP3_URGENCY_HIGH 0
-
-/**
- * @macro
- *
- * :macro:`NGHTTP3_URGENCY_LOW` is the lowest urgency level.
- */
-#define NGHTTP3_URGENCY_LOW 7
-
-/**
- * @macro
- *
- * :macro:`NGHTTP3_URGENCY_LEVELS` is the number of urgency levels.
- */
-#define NGHTTP3_URGENCY_LEVELS (NGHTTP3_URGENCY_LOW + 1)
-
-/**
- * @struct
- *
- * :type:`nghttp3_pri` represents HTTP priority.
- */
-typedef struct nghttp3_pri {
- /**
- * urgency is the urgency of a stream, it must be in
- * [NGHTTP3_URGENCY_HIGH, NGHTTP3_URGENCY_LOW], inclusive, and 0 is
- * the highest urgency.
- */
- uint32_t urgency;
- /**
- * inc indicates that a content can be processed incrementally or
- * not. If inc is 0, it cannot be processed incrementally. If inc
- * is 1, it can be processed incrementally. Other value is not
- * permitted.
- */
- int inc;
-} nghttp3_pri;
-
-/**
- * @function
- *
- * `nghttp3_conn_get_stream_priority` stores stream priority of a
- * stream denoted by |stream_id| into |*dest|. Only server can use
- * this function.
- *
- * This function must not be called if |conn| is initialized as
- * client.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_STREAM_NOT_FOUND`
- * Stream not found.
- */
-NGHTTP3_EXTERN int nghttp3_conn_get_stream_priority(nghttp3_conn *conn,
- nghttp3_pri *dest,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_conn_set_stream_priority` updates stream priority of a
- * stream denoted by |stream_id| by the value pointed by |pri|.
- *
- * This function must not be called if |conn| is initialized as
- * client.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_STREAM_NOT_FOUND`
- * Stream not found.
- * :enum:`NGHTTP3_ERR_NOMEM`
- * Out of memory.
- */
-NGHTTP3_EXTERN int nghttp3_conn_set_stream_priority(nghttp3_conn *conn,
- int64_t stream_id,
- const nghttp3_pri *pri);
-
-/**
- * @function
- *
- * `nghttp3_conn_is_remote_qpack_encoder_stream` returns nonzero if a
- * stream denoted by |stream_id| is QPACK encoder stream of a remote
- * endpoint.
- */
-NGHTTP3_EXTERN int
-nghttp3_conn_is_remote_qpack_encoder_stream(nghttp3_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `nghttp3_vec_len` returns the sum of length in |vec| of |cnt|
- * elements.
- */
-NGHTTP3_EXTERN size_t nghttp3_vec_len(const nghttp3_vec *vec, size_t cnt);
-
-/**
- * @function
- *
- * `nghttp3_vec_empty` returns nonzero if |vec| of |cnt| elements has
- * 0 length data.
- */
-NGHTTP3_EXTERN int nghttp3_vec_empty(const nghttp3_vec *vec, size_t cnt);
-
-/**
- * @function
- *
- * `nghttp3_vec_consume` removes first |len| bytes from |*pvec| of
- * |*pcnt| elements. The adjusted vector and number of elements are
- * stored in |*pvec| and |*pcnt| respectively.
- */
-NGHTTP3_EXTERN void nghttp3_vec_consume(nghttp3_vec **pvec, size_t *pcnt,
- size_t len);
-
-/**
- * @function
- *
- * `nghttp3_check_header_name` returns nonzero if HTTP header field
- * name |name| of length |len| is valid according to
- * http://tools.ietf.org/html/rfc7230#section-3.2
- *
- * Because this is a header field name in HTTP/3, the upper cased
- * alphabet is treated as error.
- */
-NGHTTP3_EXTERN int nghttp3_check_header_name(const uint8_t *name, size_t len);
-
-/**
- * @function
- *
- * `nghttp3_check_header_value` returns nonzero if HTTP header field
- * value |value| of length |len| is valid according to
- * http://tools.ietf.org/html/rfc7230#section-3.2
- */
-NGHTTP3_EXTERN int nghttp3_check_header_value(const uint8_t *value, size_t len);
-
-/**
- * @function
- *
- * `nghttp3_http_parse_priority` parses priority HTTP header field
- * stored in the buffer pointed by |value| of length |len|. If it
- * successfully processed header field value, it stores the result
- * into |*dest|. This function just overwrites what it sees in the
- * header field value and does not initialize any field in |*dest|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGHTTP3_ERR_INVALID_ARGUMENT`
- * The function could not parse the provided value.
- */
-NGHTTP3_EXTERN int nghttp3_http_parse_priority(nghttp3_pri *dest,
- const uint8_t *value,
- size_t len);
-
-/**
- * @macro
- *
- * The age of :type:`nghttp3_info`
- */
-#define NGHTTP3_VERSION_AGE 1
-
-/**
- * @struct
- *
- * This struct is what `nghttp3_version()` returns. It holds
- * information about the particular nghttp3 version.
- */
-typedef struct {
- /**
- * Age of this struct. This instance of nghttp3 sets it to
- * :macro:`NGHTTP3_VERSION_AGE` but a future version may bump it and
- * add more struct fields at the bottom
- */
- int age;
- /**
- * the :macro:`NGHTTP3_VERSION_NUM` number (since age ==1)
- */
- int version_num;
- /**
- * points to the :macro:`NGHTTP3_VERSION` string (since age ==1)
- */
- const char *version_str;
- /* -------- the above fields all exist when age == 1 */
-} nghttp3_info;
-
-/**
- * @function
- *
- * Returns a pointer to a nghttp3_info struct with version information
- * about the run-time library in use. The |least_version| argument
- * can be set to a 24 bit numerical value for the least accepted
- * version number and if the condition is not met, this function will
- * return a ``NULL``. Pass in 0 to skip the version checking.
- */
-NGHTTP3_EXTERN nghttp3_info *nghttp3_version(int least_version);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* NGHTTP3_H */
diff --git a/deps/nghttp3/lib/includes/nghttp3/version.h b/deps/nghttp3/lib/includes/nghttp3/version.h
deleted file mode 100644
index 69d29e9f14..0000000000
--- a/deps/nghttp3/lib/includes/nghttp3/version.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2016 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_VERSION_H
-#define NGHTTP3_VERSION_H
-
-/**
- * @macro
- *
- * Version number of the nghttp3 library release.
- */
-#define NGHTTP3_VERSION "0.1.0-DEV"
-
-/**
- * @macro
- *
- * Numerical representation of the version number of the nghttp3
- * library 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 NGHTTP3_VERSION_NUM 0x000100
-
-#endif /* NGHTTP3_VERSION_H */
diff --git a/deps/nghttp3/lib/nghttp3_buf.c b/deps/nghttp3/lib/nghttp3_buf.c
deleted file mode 100644
index aae075a73c..0000000000
--- a/deps/nghttp3/lib/nghttp3_buf.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_buf.h"
-
-void nghttp3_buf_init(nghttp3_buf *buf) {
- buf->begin = buf->end = buf->pos = buf->last = NULL;
-}
-
-void nghttp3_buf_wrap_init(nghttp3_buf *buf, uint8_t *src, size_t len) {
- buf->begin = buf->pos = buf->last = src;
- buf->end = buf->begin + len;
-}
-
-void nghttp3_buf_free(nghttp3_buf *buf, const nghttp3_mem *mem) {
- nghttp3_mem_free(mem, buf->begin);
-}
-
-size_t nghttp3_buf_left(const nghttp3_buf *buf) {
- return (size_t)(buf->end - buf->last);
-}
-
-size_t nghttp3_buf_len(const nghttp3_buf *buf) {
- return (size_t)(buf->last - buf->pos);
-}
-
-size_t nghttp3_buf_cap(const nghttp3_buf *buf) {
- return (size_t)(buf->end - buf->begin);
-}
-
-void nghttp3_buf_reset(nghttp3_buf *buf) { buf->pos = buf->last = buf->begin; }
-
-int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem) {
- uint8_t *p;
- nghttp3_ssize pos_offset, last_offset;
-
- if ((size_t)(buf->end - buf->begin) >= size) {
- return 0;
- }
-
- pos_offset = buf->pos - buf->begin;
- last_offset = buf->last - buf->begin;
-
- p = nghttp3_mem_realloc(mem, buf->begin, size);
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- buf->begin = p;
- buf->end = p + size;
- buf->pos = p + pos_offset;
- buf->last = p + last_offset;
-
- return 0;
-}
-
-void nghttp3_buf_swap(nghttp3_buf *a, nghttp3_buf *b) {
- nghttp3_buf c = *a;
-
- *a = *b;
- *b = c;
-}
-
-void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
- nghttp3_buf_type type) {
- tbuf->buf = *buf;
- tbuf->type = type;
-}
diff --git a/deps/nghttp3/lib/nghttp3_buf.h b/deps/nghttp3/lib/nghttp3_buf.h
deleted file mode 100644
index 493d81be31..0000000000
--- a/deps/nghttp3/lib/nghttp3_buf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_BUF_H
-#define NGHTTP3_BUF_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-
-void nghttp3_buf_wrap_init(nghttp3_buf *buf, uint8_t *src, size_t len);
-
-/*
- * nghttp3_buf_cap returns the capacity of the buffer. In other
- * words, it returns buf->end - buf->begin.
- */
-size_t nghttp3_buf_cap(const nghttp3_buf *buf);
-
-int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem);
-
-/*
- * nghttp3_buf_swap swaps |a| and |b|.
- */
-void nghttp3_buf_swap(nghttp3_buf *a, nghttp3_buf *b);
-
-typedef enum {
- /* NGHTTP3_BUF_TYPE_PRIVATE indicates that memory is allocated for
- this buffer only and should be freed after its use. */
- NGHTTP3_BUF_TYPE_PRIVATE,
- /* NGHTTP3_BUF_TYPE_SHARED indicates that buffer points to shared
- memory. */
- NGHTTP3_BUF_TYPE_SHARED,
- /* NGHTTP3_BUF_TYPE_ALIEN indicates that the buffer points to a
- memory which comes from outside of the library. */
- NGHTTP3_BUF_TYPE_ALIEN,
-} nghttp3_buf_type;
-
-typedef struct {
- nghttp3_buf buf;
- nghttp3_buf_type type;
-} nghttp3_typed_buf;
-
-void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
- nghttp3_buf_type type);
-
-void nghttp3_typed_buf_free(nghttp3_typed_buf *tbuf);
-
-#endif /* NGHTTP3_BUF_H */
diff --git a/deps/nghttp3/lib/nghttp3_conn.c b/deps/nghttp3/lib/nghttp3_conn.c
deleted file mode 100644
index 3d10f393bf..0000000000
--- a/deps/nghttp3/lib/nghttp3_conn.c
+++ /dev/null
@@ -1,3250 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_conn.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "nghttp3_mem.h"
-#include "nghttp3_macro.h"
-#include "nghttp3_err.h"
-#include "nghttp3_conv.h"
-#include "nghttp3_http.h"
-
-/*
- * conn_remote_stream_uni returns nonzero if |stream_id| is remote
- * unidirectional stream ID.
- */
-static int conn_remote_stream_uni(nghttp3_conn *conn, int64_t stream_id) {
- if (conn->server) {
- return (stream_id & 0x03) == 0x02;
- }
- return (stream_id & 0x03) == 0x03;
-}
-
-static int conn_call_begin_headers(nghttp3_conn *conn, nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.begin_headers) {
- return 0;
- }
-
- rv = conn->callbacks.begin_headers(conn, stream->node.nid.id, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_end_headers(nghttp3_conn *conn, nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.end_headers) {
- return 0;
- }
-
- rv = conn->callbacks.end_headers(conn, stream->node.nid.id, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_begin_trailers(nghttp3_conn *conn,
- nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.begin_trailers) {
- return 0;
- }
-
- rv = conn->callbacks.begin_trailers(conn, stream->node.nid.id,
- conn->user_data, stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_end_trailers(nghttp3_conn *conn, nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.end_trailers) {
- return 0;
- }
-
- rv = conn->callbacks.end_trailers(conn, stream->node.nid.id, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_begin_push_promise(nghttp3_conn *conn,
- nghttp3_stream *stream,
- int64_t push_id) {
- int rv;
-
- if (!conn->callbacks.begin_push_promise) {
- return 0;
- }
-
- rv = conn->callbacks.begin_push_promise(conn, stream->node.nid.id, push_id,
- conn->user_data, stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_end_push_promise(nghttp3_conn *conn,
- nghttp3_stream *stream, int64_t push_id) {
- int rv;
-
- if (!conn->callbacks.end_push_promise) {
- return 0;
- }
-
- rv = conn->callbacks.end_push_promise(conn, stream->node.nid.id, push_id,
- conn->user_data, stream->user_data);
- if (rv != 0) {
- /* TODO Allow ignore headers */
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_end_stream(nghttp3_conn *conn, nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.end_stream) {
- return 0;
- }
-
- rv = conn->callbacks.end_stream(conn, stream->node.nid.id, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_cancel_push(nghttp3_conn *conn, int64_t push_id,
- nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.cancel_push) {
- return 0;
- }
-
- rv = conn->callbacks.cancel_push(
- conn, push_id, stream ? stream->node.nid.id : -1, conn->user_data,
- stream ? stream->user_data : NULL);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_send_stop_sending(nghttp3_conn *conn,
- nghttp3_stream *stream,
- uint64_t app_error_code) {
- int rv;
-
- if (!conn->callbacks.send_stop_sending) {
- return 0;
- }
-
- rv = conn->callbacks.send_stop_sending(conn, stream->node.nid.id,
- app_error_code, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_push_stream(nghttp3_conn *conn, int64_t push_id,
- nghttp3_stream *stream) {
- int rv;
-
- if (!conn->callbacks.push_stream) {
- return 0;
- }
-
- rv = conn->callbacks.push_stream(conn, push_id, stream->node.nid.id,
- conn->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_deferred_consume(nghttp3_conn *conn,
- nghttp3_stream *stream,
- size_t nconsumed) {
- int rv;
-
- if (nconsumed == 0 || !conn->callbacks.deferred_consume) {
- return 0;
- }
-
- rv = conn->callbacks.deferred_consume(conn, stream->node.nid.id, nconsumed,
- conn->user_data, stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int ricnt_less(const nghttp3_pq_entry *lhsx,
- const nghttp3_pq_entry *rhsx) {
- nghttp3_stream *lhs =
- nghttp3_struct_of(lhsx, nghttp3_stream, qpack_blocked_pe);
- nghttp3_stream *rhs =
- nghttp3_struct_of(rhsx, nghttp3_stream, qpack_blocked_pe);
-
- return lhs->qpack_sctx.ricnt < rhs->qpack_sctx.ricnt;
-}
-
-static int cycle_less(const nghttp3_pq_entry *lhsx,
- const nghttp3_pq_entry *rhsx) {
- const nghttp3_tnode *lhs = nghttp3_struct_of(lhsx, nghttp3_tnode, pe);
- const nghttp3_tnode *rhs = nghttp3_struct_of(rhsx, nghttp3_tnode, pe);
-
- if (lhs->cycle == rhs->cycle) {
- return lhs->seq < rhs->seq;
- }
-
- return rhs->cycle - lhs->cycle <= NGHTTP3_TNODE_MAX_CYCLE_GAP;
-}
-
-static int conn_new(nghttp3_conn **pconn, int server,
- const nghttp3_conn_callbacks *callbacks,
- const nghttp3_conn_settings *settings,
- const nghttp3_mem *mem, void *user_data) {
- int rv;
- nghttp3_conn *conn;
- size_t i;
-
- conn = nghttp3_mem_calloc(mem, 1, sizeof(nghttp3_conn));
- if (conn == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- rv = nghttp3_map_init(&conn->streams, mem);
- if (rv != 0) {
- goto streams_init_fail;
- }
-
- rv = nghttp3_map_init(&conn->pushes, mem);
- if (rv != 0) {
- goto pushes_init_fail;
- }
-
- rv = nghttp3_qpack_decoder_init(&conn->qdec,
- settings->qpack_max_table_capacity,
- settings->qpack_blocked_streams, mem);
- if (rv != 0) {
- goto qdec_init_fail;
- }
-
- rv = nghttp3_qpack_encoder_init(&conn->qenc, 0, 0, mem);
- if (rv != 0) {
- goto qenc_init_fail;
- }
-
- nghttp3_pq_init(&conn->qpack_blocked_streams, ricnt_less, mem);
-
- for (i = 0; i < NGHTTP3_URGENCY_LEVELS; ++i) {
- nghttp3_pq_init(&conn->sched[i].spq, cycle_less, mem);
- }
-
- rv = nghttp3_idtr_init(&conn->remote.bidi.idtr, server, mem);
- if (rv != 0) {
- goto remote_bidi_idtr_init_fail;
- }
-
- rv = nghttp3_gaptr_init(&conn->remote.uni.push_idtr, mem);
- if (rv != 0) {
- goto push_idtr_init_fail;
- }
-
- conn->callbacks = *callbacks;
- conn->local.settings = *settings;
- nghttp3_conn_settings_default(&conn->remote.settings);
- conn->mem = mem;
- conn->user_data = user_data;
- conn->next_seq = 0;
- conn->server = server;
-
- *pconn = conn;
-
- return 0;
-
-push_idtr_init_fail:
- nghttp3_idtr_free(&conn->remote.bidi.idtr);
-remote_bidi_idtr_init_fail:
- nghttp3_qpack_encoder_free(&conn->qenc);
-qenc_init_fail:
- nghttp3_qpack_decoder_free(&conn->qdec);
-qdec_init_fail:
- nghttp3_map_free(&conn->pushes);
-pushes_init_fail:
- nghttp3_map_free(&conn->streams);
-streams_init_fail:
- nghttp3_mem_free(mem, conn);
-
- return rv;
-}
-
-int nghttp3_conn_client_new(nghttp3_conn **pconn,
- const nghttp3_conn_callbacks *callbacks,
- const nghttp3_conn_settings *settings,
- const nghttp3_mem *mem, void *user_data) {
- int rv;
-
- rv = conn_new(pconn, /* server = */ 0, callbacks, settings, mem, user_data);
- if (rv != 0) {
- return rv;
- }
-
- (*pconn)->remote.uni.unsent_max_pushes = settings->max_pushes;
-
- return 0;
-}
-
-int nghttp3_conn_server_new(nghttp3_conn **pconn,
- const nghttp3_conn_callbacks *callbacks,
- const nghttp3_conn_settings *settings,
- const nghttp3_mem *mem, void *user_data) {
- int rv;
-
- rv = conn_new(pconn, /* server = */ 1, callbacks, settings, mem, user_data);
- if (rv != 0) {
- return rv;
- }
-
- return 0;
-}
-
-static int free_push_promise(nghttp3_map_entry *ent, void *ptr) {
- nghttp3_push_promise *pp = nghttp3_struct_of(ent, nghttp3_push_promise, me);
- const nghttp3_mem *mem = ptr;
-
- nghttp3_push_promise_del(pp, mem);
-
- return 0;
-}
-
-static int free_stream(nghttp3_map_entry *ent, void *ptr) {
- nghttp3_stream *stream = nghttp3_struct_of(ent, nghttp3_stream, me);
-
- (void)ptr;
-
- nghttp3_stream_del(stream);
-
- return 0;
-}
-
-void nghttp3_conn_del(nghttp3_conn *conn) {
- size_t i;
-
- if (conn == NULL) {
- return;
- }
-
- nghttp3_buf_free(&conn->tx.qpack.ebuf, conn->mem);
- nghttp3_buf_free(&conn->tx.qpack.rbuf, conn->mem);
-
- nghttp3_gaptr_free(&conn->remote.uni.push_idtr);
-
- nghttp3_idtr_free(&conn->remote.bidi.idtr);
-
- for (i = 0; i < NGHTTP3_URGENCY_LEVELS; ++i) {
- nghttp3_pq_free(&conn->sched[i].spq);
- }
-
- nghttp3_pq_free(&conn->qpack_blocked_streams);
-
- nghttp3_qpack_encoder_free(&conn->qenc);
- nghttp3_qpack_decoder_free(&conn->qdec);
-
- nghttp3_map_each_free(&conn->pushes, free_push_promise, (void *)conn->mem);
- nghttp3_map_free(&conn->pushes);
-
- nghttp3_map_each_free(&conn->streams, free_stream, NULL);
- nghttp3_map_free(&conn->streams);
-
- nghttp3_mem_free(conn->mem, conn);
-}
-
-nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
- const uint8_t *src, size_t srclen,
- int fin) {
- nghttp3_stream *stream;
- size_t bidi_nproc;
- int rv;
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream == NULL) {
- /* TODO Assert idtr */
- /* QUIC transport ensures that this is new stream. */
- if (conn->server) {
- if (nghttp3_client_stream_bidi(stream_id)) {
- rv = nghttp3_idtr_open(&conn->remote.bidi.idtr, stream_id);
- assert(rv == 0);
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- } else {
- /* unidirectional stream */
- if (srclen == 0 && fin) {
- return 0;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- }
- if (rv != 0) {
- return rv;
- }
-
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
- stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
- } else if (nghttp3_stream_uni(stream_id)) {
- if (srclen == 0 && fin) {
- return 0;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- if (rv != 0) {
- return rv;
- }
-
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
- stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
- } else {
- /* client doesn't expect to receive new bidirectional stream
- from server. */
- return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
- }
- } else if (conn->server) {
- if (nghttp3_client_stream_bidi(stream_id)) {
- if (stream->rx.hstate == NGHTTP3_HTTP_STATE_NONE) {
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
- stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
- }
- }
- } else if (nghttp3_stream_uni(stream_id) &&
- stream->type == NGHTTP3_STREAM_TYPE_PUSH) {
- if (stream->rx.hstate == NGHTTP3_HTTP_STATE_NONE) {
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
- stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
- }
- }
-
- if (srclen == 0 && !fin) {
- return 0;
- }
-
- if (nghttp3_stream_uni(stream_id)) {
- return nghttp3_conn_read_uni(conn, stream, src, srclen, fin);
- }
-
- if (fin) {
- stream->flags |= NGHTTP3_STREAM_FLAG_READ_EOF;
- }
- return nghttp3_conn_read_bidi(conn, &bidi_nproc, stream, src, srclen, fin);
-}
-
-static nghttp3_ssize conn_read_type(nghttp3_conn *conn, nghttp3_stream *stream,
- const uint8_t *src, size_t srclen,
- int fin) {
- nghttp3_stream_read_state *rstate = &stream->rstate;
- nghttp3_varint_read_state *rvint = &rstate->rvint;
- nghttp3_ssize nread;
- int64_t stream_type;
-
- assert(srclen);
-
- nread = nghttp3_read_varint(rvint, src, srclen, fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- if (rvint->left) {
- return nread;
- }
-
- stream_type = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- switch (stream_type) {
- case NGHTTP3_STREAM_TYPE_CONTROL:
- if (conn->flags & NGHTTP3_CONN_FLAG_CONTROL_OPENED) {
- return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
- }
- conn->flags |= NGHTTP3_CONN_FLAG_CONTROL_OPENED;
- stream->type = NGHTTP3_STREAM_TYPE_CONTROL;
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_TYPE;
- break;
- case NGHTTP3_STREAM_TYPE_PUSH:
- if (conn->server) {
- return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
- }
- stream->type = NGHTTP3_STREAM_TYPE_PUSH;
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_PUSH_ID;
- break;
- case NGHTTP3_STREAM_TYPE_QPACK_ENCODER:
- if (conn->flags & NGHTTP3_CONN_FLAG_QPACK_ENCODER_OPENED) {
- return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
- }
- conn->flags |= NGHTTP3_CONN_FLAG_QPACK_ENCODER_OPENED;
- stream->type = NGHTTP3_STREAM_TYPE_QPACK_ENCODER;
- break;
- case NGHTTP3_STREAM_TYPE_QPACK_DECODER:
- if (conn->flags & NGHTTP3_CONN_FLAG_QPACK_DECODER_OPENED) {
- return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
- }
- conn->flags |= NGHTTP3_CONN_FLAG_QPACK_DECODER_OPENED;
- stream->type = NGHTTP3_STREAM_TYPE_QPACK_DECODER;
- break;
- default:
- stream->type = NGHTTP3_STREAM_TYPE_UNKNOWN;
- break;
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED;
-
- return nread;
-}
-
-static int conn_delete_stream(nghttp3_conn *conn, nghttp3_stream *stream);
-
-nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream,
- const uint8_t *src, size_t srclen,
- int fin) {
- nghttp3_ssize nread = 0;
- nghttp3_ssize nconsumed = 0;
- size_t push_nproc;
- int rv;
-
- assert(srclen || fin);
-
- if (!(stream->flags & NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED)) {
- if (srclen == 0 && fin) {
- /* Ignore stream if it is closed before reading stream header.
- If it is closed while reading it, return error, making it
- consistent in our code base. */
- if (stream->rstate.rvint.left) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- rv = conn_delete_stream(conn, stream);
- assert(0 == rv);
-
- return 0;
- }
- nread = conn_read_type(conn, stream, src, srclen, fin);
- if (nread < 0) {
- return (int)nread;
- }
- if (!(stream->flags & NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED)) {
- assert((size_t)nread == srclen);
- return (nghttp3_ssize)srclen;
- }
-
- src += nread;
- srclen -= (size_t)nread;
-
- if (srclen == 0) {
- return nread;
- }
- }
-
- switch (stream->type) {
- case NGHTTP3_STREAM_TYPE_CONTROL:
- if (fin) {
- return NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM;
- }
- nconsumed = nghttp3_conn_read_control(conn, stream, src, srclen);
- break;
- case NGHTTP3_STREAM_TYPE_PUSH:
- if (fin) {
- stream->flags |= NGHTTP3_STREAM_FLAG_READ_EOF;
- }
- nconsumed =
- nghttp3_conn_read_push(conn, &push_nproc, stream, src, srclen, fin);
- break;
- case NGHTTP3_STREAM_TYPE_QPACK_ENCODER:
- if (fin) {
- return NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM;
- }
- nconsumed = nghttp3_conn_read_qpack_encoder(conn, src, srclen);
- break;
- case NGHTTP3_STREAM_TYPE_QPACK_DECODER:
- if (fin) {
- return NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM;
- }
- nconsumed = nghttp3_conn_read_qpack_decoder(conn, src, srclen);
- break;
- case NGHTTP3_STREAM_TYPE_UNKNOWN:
- nconsumed = (nghttp3_ssize)srclen;
-
- rv = conn_call_send_stop_sending(conn, stream,
- NGHTTP3_H3_STREAM_CREATION_ERROR);
- if (rv != 0) {
- return rv;
- }
- break;
- default:
- /* unreachable */
- assert(0);
- }
-
- if (nconsumed < 0) {
- return nconsumed;
- }
-
- return nread + nconsumed;
-}
-
-static int frame_fin(nghttp3_stream_read_state *rstate, size_t len) {
- return (int64_t)len >= rstate->left;
-}
-
-nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
- nghttp3_stream *stream,
- const uint8_t *src, size_t srclen) {
- const uint8_t *p = src, *end = src + srclen;
- int rv;
- nghttp3_stream_read_state *rstate = &stream->rstate;
- nghttp3_varint_read_state *rvint = &rstate->rvint;
- nghttp3_ssize nread;
- size_t nconsumed = 0;
- int busy = 0;
- size_t len;
-
- assert(srclen);
-
- for (; p != end || busy;) {
- busy = 0;
- switch (rstate->state) {
- case NGHTTP3_CTRL_STREAM_STATE_FRAME_TYPE:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), /* fin = */ 0);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
-
- rstate->fr.hd.type = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH;
- if (p == end) {
- break;
- }
- /* Fall through */
- case NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), /* fin = */ 0);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
-
- rstate->left = rstate->fr.hd.length = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- if (!(conn->flags & NGHTTP3_CONN_FLAG_SETTINGS_RECVED)) {
- if (rstate->fr.hd.type != NGHTTP3_FRAME_SETTINGS) {
- return NGHTTP3_ERR_H3_MISSING_SETTINGS;
- }
- conn->flags |= NGHTTP3_CONN_FLAG_SETTINGS_RECVED;
- } else if (rstate->fr.hd.type == NGHTTP3_FRAME_SETTINGS) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
-
- switch (rstate->fr.hd.type) {
- case NGHTTP3_FRAME_CANCEL_PUSH:
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_CANCEL_PUSH;
- break;
- case NGHTTP3_FRAME_SETTINGS:
- /* SETTINGS frame might be empty. */
- if (rstate->left == 0) {
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS;
- break;
- case NGHTTP3_FRAME_GOAWAY:
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_GOAWAY;
- break;
- case NGHTTP3_FRAME_MAX_PUSH_ID:
- if (!conn->server) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_MAX_PUSH_ID;
- break;
- case NGHTTP3_FRAME_DATA:
- case NGHTTP3_FRAME_HEADERS:
- case NGHTTP3_FRAME_PUSH_PROMISE:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- default:
- /* TODO Handle reserved frame type */
- busy = 1;
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME;
- break;
- }
- break;
- case NGHTTP3_CTRL_STREAM_STATE_CANCEL_PUSH:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- assert(len > 0);
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
- rstate->fr.cancel_push.push_id = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- if (conn->server) {
- rv = nghttp3_conn_on_server_cancel_push(conn, &rstate->fr.cancel_push);
- } else {
- rv = nghttp3_conn_on_client_cancel_push(conn, &rstate->fr.cancel_push);
- }
- if (rv != 0) {
- return rv;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_CTRL_STREAM_STATE_SETTINGS:
- for (; p != end;) {
- if (rstate->left == 0) {
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
- /* Read Identifier */
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- assert(len > 0);
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS_ID;
- return (nghttp3_ssize)nconsumed;
- }
- rstate->fr.settings.iv[0].id = (uint64_t)rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- /* Read Value */
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- len -= (size_t)nread;
- if (len == 0) {
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE;
- break;
- }
-
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE;
- return (nghttp3_ssize)nconsumed;
- }
- rstate->fr.settings.iv[0].value = (uint64_t)rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- rv =
- nghttp3_conn_on_settings_entry_received(conn, &rstate->fr.settings);
- if (rv != 0) {
- return rv;
- }
- }
- break;
- case NGHTTP3_CTRL_STREAM_STATE_SETTINGS_ID:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- assert(len > 0);
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
- rstate->fr.settings.iv[0].id = (uint64_t)rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE;
-
- if (p == end) {
- return (nghttp3_ssize)nconsumed;
- }
- /* Fall through */
- case NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- assert(len > 0);
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
- rstate->fr.settings.iv[0].value = (uint64_t)rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- rv = nghttp3_conn_on_settings_entry_received(conn, &rstate->fr.settings);
- if (rv != 0) {
- return rv;
- }
-
- if (rstate->left) {
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_SETTINGS;
- break;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_CTRL_STREAM_STATE_GOAWAY:
- /* TODO Not implemented yet */
- rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME;
- break;
- case NGHTTP3_CTRL_STREAM_STATE_MAX_PUSH_ID:
- /* server side only */
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- assert(len > 0);
- nread = nghttp3_read_varint(rvint, p, len, frame_fin(rstate, len));
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- return (nghttp3_ssize)nconsumed;
- }
-
- if (conn->local.uni.max_pushes > (uint64_t)rvint->acc) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- conn->local.uni.max_pushes = (uint64_t)rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- p += len;
- nconsumed += len;
- rstate->left -= (int64_t)len;
-
- if (rstate->left) {
- return (nghttp3_ssize)nconsumed;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- default:
- /* unreachable */
- assert(0);
- }
- }
-
- return (nghttp3_ssize)nconsumed;
-}
-
-nghttp3_ssize nghttp3_conn_read_push(nghttp3_conn *conn, size_t *pnproc,
- nghttp3_stream *stream, const uint8_t *src,
- size_t srclen, int fin) {
- const uint8_t *p = src, *end = src ? src + srclen : src;
- int rv;
- nghttp3_stream_read_state *rstate = &stream->rstate;
- nghttp3_varint_read_state *rvint = &rstate->rvint;
- nghttp3_ssize nread;
- size_t nconsumed = 0;
- int busy = 0;
- size_t len;
- int64_t push_id;
-
- if (stream->pp &&
- (stream->pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL)) {
- *pnproc = srclen;
- return (nghttp3_ssize)srclen;
- }
-
- if (stream->flags & (NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED |
- NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED)) {
- *pnproc = 0;
-
- if (srclen == 0) {
- return 0;
- }
-
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- return 0;
- }
-
- for (; p != end || busy;) {
- busy = 0;
- switch (rstate->state) {
- case NGHTTP3_PUSH_STREAM_STATE_PUSH_ID:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- push_id = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- rv = nghttp3_conn_on_stream_push_id(conn, stream, push_id);
- if (rv != 0) {
- if (rv == NGHTTP3_ERR_IGNORE_STREAM) {
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_IGN_REST;
- break;
- }
- return (nghttp3_ssize)rv;
- }
-
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_FRAME_TYPE;
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED) {
- if (p != end) {
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- }
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
-
- if (end == p) {
- goto almost_done;
- }
-
- /* Fall through */
- case NGHTTP3_PUSH_STREAM_STATE_FRAME_TYPE:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- rstate->fr.hd.type = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_FRAME_LENGTH;
- if (p == end) {
- goto almost_done;
- }
- /* Fall through */
- case NGHTTP3_PUSH_STREAM_STATE_FRAME_LENGTH:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- rstate->left = rstate->fr.hd.length = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- switch (rstate->fr.hd.type) {
- case NGHTTP3_FRAME_DATA:
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_DATA_BEGIN);
- if (rv != 0) {
- return rv;
- }
- /* DATA frame might be empty. */
- if (rstate->left == 0) {
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_DATA_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_DATA;
- break;
- case NGHTTP3_FRAME_HEADERS:
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_HEADERS_BEGIN);
- if (rv != 0) {
- return rv;
- }
- if (rstate->left == 0) {
- rv = nghttp3_stream_empty_headers_allowed(stream);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_HEADERS_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- rv = conn_call_begin_headers(conn, stream);
- break;
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- rv = conn_call_begin_trailers(conn, stream);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- if (rv != 0) {
- return rv;
- }
-
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_HEADERS;
- break;
- case NGHTTP3_FRAME_PUSH_PROMISE:
- case NGHTTP3_FRAME_CANCEL_PUSH:
- case NGHTTP3_FRAME_SETTINGS:
- case NGHTTP3_FRAME_GOAWAY:
- case NGHTTP3_FRAME_MAX_PUSH_ID:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- default:
- /* TODO Handle reserved frame type */
- busy = 1;
- rstate->state = NGHTTP3_PUSH_STREAM_STATE_IGN_FRAME;
- break;
- }
- break;
- case NGHTTP3_PUSH_STREAM_STATE_DATA:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- rv = nghttp3_conn_on_data(conn, stream, p, len);
- if (rv != 0) {
- return rv;
- }
-
- p += len;
- rstate->left -= (int64_t)len;
-
- if (rstate->left) {
- goto almost_done;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_DATA_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_PUSH_STREAM_STATE_HEADERS:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- nread = nghttp3_conn_on_headers(conn, stream, NULL, p, len,
- (int64_t)len == rstate->left);
- if (nread < 0) {
- return nread;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- if (p != end && nghttp3_stream_get_buffered_datalen(stream) == 0) {
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- }
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
-
- if (rstate->left) {
- goto almost_done;
- }
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- rv = nghttp3_http_on_response_headers(&stream->rx.http);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_call_end_headers(conn, stream);
- break;
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- rv = conn_call_end_trailers(conn, stream);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_HEADERS_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_PUSH_STREAM_STATE_IGN_FRAME:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- p += len;
- nconsumed += len;
- rstate->left -= (int64_t)len;
-
- if (rstate->left) {
- goto almost_done;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_PUSH_STREAM_STATE_IGN_REST:
- nconsumed += (size_t)(end - p);
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
- }
-
-almost_done:
- if (fin) {
- switch (rstate->state) {
- case NGHTTP3_PUSH_STREAM_STATE_FRAME_TYPE:
- if (rvint->left) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_MSG_END);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGHTTP3_PUSH_STREAM_STATE_IGN_REST:
- break;
- default:
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
- }
-
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
-}
-
-static void conn_delete_push_promise(nghttp3_conn *conn,
- nghttp3_push_promise *pp) {
- int rv;
-
- rv = nghttp3_map_remove(&conn->pushes, (key_type)pp->node.nid.id);
- assert(0 == rv);
-
- if (!conn->server &&
- !(pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_PUSH_ID_RECLAIMED)) {
- ++conn->remote.uni.unsent_max_pushes;
- }
-
- nghttp3_push_promise_del(pp, conn->mem);
-}
-
-static int conn_delete_stream(nghttp3_conn *conn, nghttp3_stream *stream) {
- int rv;
-
- if (nghttp3_stream_bidi_or_push(stream)) {
- rv = nghttp3_http_on_remote_end_stream(stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- rv = conn_call_deferred_consume(conn, stream,
- nghttp3_stream_get_buffered_datalen(stream));
- if (rv != 0) {
- return rv;
- }
-
- if (conn->callbacks.stream_close) {
- rv = conn->callbacks.stream_close(conn, stream->node.nid.id,
- stream->error_code, conn->user_data,
- stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
- }
-
- rv = nghttp3_map_remove(&conn->streams, (key_type)stream->node.nid.id);
-
- assert(0 == rv);
-
- if (stream->pp) {
- assert(stream->type == NGHTTP3_STREAM_TYPE_PUSH);
-
- conn_delete_push_promise(conn, stream->pp);
- }
-
- nghttp3_stream_del(stream);
-
- return 0;
-}
-
-static int conn_process_blocked_stream_data(nghttp3_conn *conn,
- nghttp3_stream *stream) {
- nghttp3_buf *buf;
- size_t nproc;
- nghttp3_ssize nconsumed;
- int rv;
- size_t len;
-
- for (;;) {
- len = nghttp3_ringbuf_len(&stream->inq);
- if (len == 0) {
- break;
- }
- buf = nghttp3_ringbuf_get(&stream->inq, 0);
- if (nghttp3_stream_uni(stream->node.nid.id)) {
- nconsumed = nghttp3_conn_read_push(
- conn, &nproc, stream, buf->pos, nghttp3_buf_len(buf),
- len == 1 && (stream->flags & NGHTTP3_STREAM_FLAG_READ_EOF));
- } else {
- nconsumed = nghttp3_conn_read_bidi(
- conn, &nproc, stream, buf->pos, nghttp3_buf_len(buf),
- len == 1 && (stream->flags & NGHTTP3_STREAM_FLAG_READ_EOF));
- }
- if (nconsumed < 0) {
- return (int)nconsumed;
- }
-
- buf->pos += nproc;
-
- rv = conn_call_deferred_consume(conn, stream, (size_t)nconsumed);
- if (rv != 0) {
- return 0;
- }
-
- if (nghttp3_buf_len(buf) == 0) {
- nghttp3_buf_free(buf, stream->mem);
- nghttp3_ringbuf_pop_front(&stream->inq);
- }
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- break;
- }
- }
-
- if (!(stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) &&
- (stream->flags & NGHTTP3_STREAM_FLAG_CLOSED)) {
- assert(stream->qpack_blocked_pe.index == NGHTTP3_PQ_BAD_INDEX);
-
- rv = conn_delete_stream(conn, stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-nghttp3_ssize nghttp3_conn_read_qpack_encoder(nghttp3_conn *conn,
- const uint8_t *src,
- size_t srclen) {
- nghttp3_ssize nconsumed =
- nghttp3_qpack_decoder_read_encoder(&conn->qdec, src, srclen);
- nghttp3_stream *stream;
- int rv;
-
- if (nconsumed < 0) {
- return nconsumed;
- }
-
- for (; !nghttp3_pq_empty(&conn->qpack_blocked_streams);) {
- stream = nghttp3_struct_of(nghttp3_pq_top(&conn->qpack_blocked_streams),
- nghttp3_stream, qpack_blocked_pe);
- if (nghttp3_qpack_stream_context_get_ricnt(&stream->qpack_sctx) >
- nghttp3_qpack_decoder_get_icnt(&conn->qdec)) {
- break;
- }
-
- nghttp3_conn_qpack_blocked_streams_pop(conn);
- stream->qpack_blocked_pe.index = NGHTTP3_PQ_BAD_INDEX;
- stream->flags &= (uint16_t)~NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED;
-
- rv = conn_process_blocked_stream_data(conn, stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- return nconsumed;
-}
-
-nghttp3_ssize nghttp3_conn_read_qpack_decoder(nghttp3_conn *conn,
- const uint8_t *src,
- size_t srclen) {
- return nghttp3_qpack_encoder_read_decoder(&conn->qenc, src, srclen);
-}
-
-static int conn_update_stream_priority(nghttp3_conn *conn,
- nghttp3_stream *stream, uint8_t pri) {
- if (stream->node.pri == pri) {
- return 0;
- }
-
- nghttp3_conn_unschedule_stream(conn, stream);
-
- stream->node.pri = pri;
-
- assert(nghttp3_stream_bidi_or_push(stream));
-
- if (nghttp3_stream_require_schedule(stream)) {
- return nghttp3_conn_schedule_stream(conn, stream);
- }
-
- return 0;
-}
-
-nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc,
- nghttp3_stream *stream, const uint8_t *src,
- size_t srclen, int fin) {
- const uint8_t *p = src, *end = src ? src + srclen : src;
- int rv;
- nghttp3_stream_read_state *rstate = &stream->rstate;
- nghttp3_varint_read_state *rvint = &rstate->rvint;
- nghttp3_ssize nread;
- size_t nconsumed = 0;
- int busy = 0;
- size_t len;
- nghttp3_push_promise *pp;
- nghttp3_push_promise fake_pp = {{0}, {{0}, 0, {0}, 0, 0, 0}, {0}, NULL, -1,
- 0};
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- *pnproc = 0;
-
- if (srclen == 0) {
- return 0;
- }
-
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- return 0;
- }
-
- for (; p != end || busy;) {
- busy = 0;
- switch (rstate->state) {
- case NGHTTP3_REQ_STREAM_STATE_FRAME_TYPE:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- rstate->fr.hd.type = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
- rstate->state = NGHTTP3_REQ_STREAM_STATE_FRAME_LENGTH;
- if (p == end) {
- goto almost_done;
- }
- /* Fall through */
- case NGHTTP3_REQ_STREAM_STATE_FRAME_LENGTH:
- assert(end - p > 0);
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p), fin);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- rstate->left = rstate->fr.hd.length = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- switch (rstate->fr.hd.type) {
- case NGHTTP3_FRAME_DATA:
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_DATA_BEGIN);
- if (rv != 0) {
- return rv;
- }
- /* DATA frame might be empty. */
- if (rstate->left == 0) {
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_DATA_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
- rstate->state = NGHTTP3_REQ_STREAM_STATE_DATA;
- break;
- case NGHTTP3_FRAME_HEADERS:
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_HEADERS_BEGIN);
- if (rv != 0) {
- return rv;
- }
- if (rstate->left == 0) {
- rv = nghttp3_stream_empty_headers_allowed(stream);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(
- stream, NGHTTP3_HTTP_EVENT_HEADERS_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- rv = conn_call_begin_headers(conn, stream);
- break;
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- rv = conn_call_begin_trailers(conn, stream);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- if (rv != 0) {
- return rv;
- }
-
- rstate->state = NGHTTP3_REQ_STREAM_STATE_HEADERS;
- break;
- case NGHTTP3_FRAME_PUSH_PROMISE:
- if (conn->server) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
-
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- /* No stream->rx.hstate change with PUSH_PROMISE */
-
- rstate->state = NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE_PUSH_ID;
- break;
- case NGHTTP3_FRAME_CANCEL_PUSH:
- case NGHTTP3_FRAME_SETTINGS:
- case NGHTTP3_FRAME_GOAWAY:
- case NGHTTP3_FRAME_MAX_PUSH_ID:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- default:
- /* TODO Handle reserved frame type */
- busy = 1;
- rstate->state = NGHTTP3_REQ_STREAM_STATE_IGN_FRAME;
- break;
- }
- break;
- case NGHTTP3_REQ_STREAM_STATE_DATA:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- rv = nghttp3_conn_on_data(conn, stream, p, len);
- if (rv != 0) {
- return rv;
- }
- p += len;
- rstate->left -= (int64_t)len;
-
- if (rstate->left) {
- goto almost_done;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_DATA_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE_PUSH_ID:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- nread = nghttp3_read_varint(rvint, p, (size_t)(end - p),
- (int64_t)len == rstate->left);
- if (nread < 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
- if (rvint->left) {
- goto almost_done;
- }
-
- rstate->fr.push_promise.push_id = rvint->acc;
- nghttp3_varint_read_state_reset(rvint);
-
- if (rstate->left == 0) {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- rv = nghttp3_conn_on_push_promise_push_id(
- conn, rstate->fr.push_promise.push_id, stream);
- if (rv != 0) {
- if (rv == NGHTTP3_ERR_IGNORE_PUSH_PROMISE) {
- rstate->state = NGHTTP3_REQ_STREAM_STATE_IGN_PUSH_PROMISE;
- if (p == end) {
- goto almost_done;
- }
- break;
- }
-
- return rv;
- }
-
- rstate->state = NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE;
-
- if (p == end) {
- goto almost_done;
- }
- /* Fall through */
- case NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE:
- pp =
- nghttp3_conn_find_push_promise(conn, rstate->fr.push_promise.push_id);
-
- assert(pp);
-
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- nread = nghttp3_conn_on_headers(conn, stream, pp, p, len,
- (int64_t)len == rstate->left);
- if (nread < 0) {
- return nread;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- if (p != end && nghttp3_stream_get_buffered_datalen(stream) == 0) {
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- }
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
-
- if (rstate->left) {
- goto almost_done;
- }
-
- rv = nghttp3_http_on_request_headers(&pp->http);
- if (rv != 0) {
- return rv;
- }
-
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_RECVED;
-
- rv = conn_call_end_push_promise(conn, stream, pp->node.nid.id);
- if (rv != 0) {
- return rv;
- }
-
- if (!pp->stream && (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_CANCELLED)) {
- if (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL) {
- rv = conn_call_cancel_push(conn, pp->node.nid.id, pp->stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- conn_delete_push_promise(conn, pp);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
-
- if (pp->stream) {
- ++conn->remote.uni.unsent_max_pushes;
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_PUSH_ID_RECLAIMED;
-
- if (!(pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL)) {
- assert(pp->stream->flags & NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED);
-
- rv = conn_call_push_stream(conn, pp->node.nid.id, pp->stream);
- if (rv != 0) {
- return rv;
- }
-
- pp->stream->flags &=
- (uint16_t)~NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED;
-
- rv = conn_process_blocked_stream_data(conn, pp->stream);
- if (rv != 0) {
- return rv;
- }
- }
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_REQ_STREAM_STATE_IGN_PUSH_PROMISE:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- nread = nghttp3_conn_on_headers(conn, stream, &fake_pp, p, len,
- (int64_t)len == rstate->left);
- if (nread < 0) {
- return nread;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- if (p != end && nghttp3_stream_get_buffered_datalen(stream) == 0) {
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- }
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
-
- if (rstate->left) {
- goto almost_done;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_REQ_STREAM_STATE_HEADERS:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- nread = nghttp3_conn_on_headers(conn, stream, NULL, p, len,
- (int64_t)len == rstate->left);
- if (nread < 0) {
- return nread;
- }
-
- p += nread;
- nconsumed += (size_t)nread;
- rstate->left -= nread;
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED) {
- if (p != end && nghttp3_stream_get_buffered_datalen(stream) == 0) {
- rv = nghttp3_stream_buffer_data(stream, p, (size_t)(end - p));
- if (rv != 0) {
- return rv;
- }
- }
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
- }
-
- if (rstate->left) {
- goto almost_done;
- }
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
- rv = nghttp3_http_on_request_headers(&stream->rx.http);
- break;
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- rv = nghttp3_http_on_response_headers(&stream->rx.http);
- break;
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- rv = 0;
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- if (rv != 0) {
- return rv;
- }
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
- /* Only server utilizes priority information to schedule
- streams. */
- if (conn->server) {
- rv = conn_update_stream_priority(conn, stream, stream->rx.http.pri);
- if (rv != 0) {
- return rv;
- }
- }
- /* fall through */
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- rv = conn_call_end_headers(conn, stream);
- break;
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- rv = conn_call_end_trailers(conn, stream);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_HEADERS_END);
- assert(0 == rv);
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- case NGHTTP3_REQ_STREAM_STATE_IGN_FRAME:
- len = (size_t)nghttp3_min(rstate->left, (int64_t)(end - p));
- p += len;
- nconsumed += len;
- rstate->left -= (int64_t)len;
-
- if (rstate->left) {
- goto almost_done;
- }
-
- nghttp3_stream_read_state_reset(rstate);
- break;
- }
- }
-
-almost_done:
- if (fin) {
- switch (rstate->state) {
- case NGHTTP3_REQ_STREAM_STATE_FRAME_TYPE:
- if (rvint->left) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- rv = nghttp3_stream_transit_rx_http_state(stream,
- NGHTTP3_HTTP_EVENT_MSG_END);
- if (rv != 0) {
- return rv;
- }
- rv = conn_call_end_stream(conn, stream);
- if (rv != 0) {
- return rv;
- }
- break;
- default:
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
- }
-
- *pnproc = (size_t)(p - src);
- return (nghttp3_ssize)nconsumed;
-}
-
-int nghttp3_conn_on_data(nghttp3_conn *conn, nghttp3_stream *stream,
- const uint8_t *data, size_t datalen) {
- int rv;
-
- rv = nghttp3_http_on_data_chunk(stream, datalen);
- if (rv != 0) {
- return rv;
- }
-
- if (!conn->callbacks.recv_data) {
- return 0;
- }
-
- rv = conn->callbacks.recv_data(conn, stream->node.nid.id, data, datalen,
- conn->user_data, stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-int nghttp3_conn_on_push_promise_push_id(nghttp3_conn *conn, int64_t push_id,
- nghttp3_stream *stream) {
- int rv;
- nghttp3_gaptr *push_idtr = &conn->remote.uni.push_idtr;
- nghttp3_push_promise *pp;
-
- if (conn->remote.uni.max_pushes <= (uint64_t)push_id) {
- return NGHTTP3_ERR_H3_ID_ERROR;
- }
-
- pp = nghttp3_conn_find_push_promise(conn, push_id);
- if (pp) {
- if ((pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_BOUND) ||
- (pp->stream_id != -1 && pp->stream_id != stream->node.nid.id)) {
- return NGHTTP3_ERR_IGNORE_PUSH_PROMISE;
- }
- if (pp->stream) {
- assert(pp->stream->flags & NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED);
- /* Push unidirectional stream has already been received and
- blocked */
- } else if (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_CANCELLED) {
- /* We will call begin_push_promise callback even if push is
- cancelled */
- } else {
- return NGHTTP3_ERR_H3_FRAME_ERROR;
- }
-
- assert(pp->stream_id == -1);
-
- pp->stream_id = stream->node.nid.id;
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_BOUND;
- } else if (nghttp3_gaptr_is_pushed(push_idtr, (uint64_t)push_id, 1)) {
- return NGHTTP3_ERR_IGNORE_PUSH_PROMISE;
- } else {
- rv = nghttp3_gaptr_push(push_idtr, (uint64_t)push_id, 1);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_conn_create_push_promise(conn, &pp, push_id, &stream->node);
- if (rv != 0) {
- return rv;
- }
- }
-
- rv = conn_call_begin_push_promise(conn, stream, push_id);
- if (rv != 0) {
- return rv;
- }
-
- return 0;
-}
-
-int nghttp3_conn_on_client_cancel_push(nghttp3_conn *conn,
- const nghttp3_frame_cancel_push *fr) {
- nghttp3_push_promise *pp;
- nghttp3_gaptr *push_idtr = &conn->remote.uni.push_idtr;
- int rv;
-
- if (conn->remote.uni.max_pushes <= (uint64_t)fr->push_id) {
- return NGHTTP3_ERR_H3_ID_ERROR;
- }
-
- pp = nghttp3_conn_find_push_promise(conn, fr->push_id);
- if (pp == NULL) {
- if (nghttp3_gaptr_is_pushed(push_idtr, (uint64_t)fr->push_id, 1)) {
- /* push is already cancelled or server is misbehaving */
- return 0;
- }
-
- /* We have not received PUSH_PROMISE yet */
- rv = nghttp3_gaptr_push(push_idtr, (uint64_t)fr->push_id, 1);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_conn_create_push_promise(conn, &pp, fr->push_id, NULL);
- if (rv != 0) {
- return rv;
- }
-
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL;
-
- /* cancel_push callback will be called after PUSH_PROMISE frame is
- completely received. */
-
- return 0;
- }
-
- if (pp->stream) {
- return 0;
- }
-
- if (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECVED) {
- rv = conn_call_cancel_push(conn, pp->node.nid.id, pp->stream);
- if (rv != 0) {
- return rv;
- }
-
- conn_delete_push_promise(conn, pp);
-
- return 0;
- }
-
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL;
-
- return 0;
-}
-
-static nghttp3_pq *conn_get_sched_pq(nghttp3_conn *conn, nghttp3_tnode *tnode) {
- uint32_t urgency = nghttp3_pri_uint8_urgency(tnode->pri);
-
- assert(urgency < NGHTTP3_URGENCY_LEVELS);
-
- return &conn->sched[urgency].spq;
-}
-
-int nghttp3_conn_on_server_cancel_push(nghttp3_conn *conn,
- const nghttp3_frame_cancel_push *fr) {
- nghttp3_push_promise *pp;
- nghttp3_stream *stream;
- int rv;
-
- if (conn->local.uni.next_push_id <= fr->push_id) {
- return NGHTTP3_ERR_H3_ID_ERROR;
- }
-
- pp = nghttp3_conn_find_push_promise(conn, fr->push_id);
- if (pp == NULL) {
- return 0;
- }
-
- stream = pp->stream;
-
- rv = conn_call_cancel_push(conn, fr->push_id, stream);
- if (rv != 0) {
- return rv;
- }
-
- if (stream) {
- rv = nghttp3_conn_close_stream(conn, stream->node.nid.id,
- NGHTTP3_H3_REQUEST_CANCELLED);
- if (rv != 0) {
- assert(NGHTTP3_ERR_STREAM_NOT_FOUND != rv);
- return rv;
- }
- return 0;
- }
-
- nghttp3_tnode_unschedule(&pp->node, conn_get_sched_pq(conn, &pp->node));
-
- conn_delete_push_promise(conn, pp);
-
- return 0;
-}
-
-int nghttp3_conn_on_stream_push_id(nghttp3_conn *conn, nghttp3_stream *stream,
- int64_t push_id) {
- nghttp3_push_promise *pp;
- int rv;
-
- if (nghttp3_gaptr_is_pushed(&conn->remote.uni.push_idtr, (uint64_t)push_id,
- 1)) {
- pp = nghttp3_conn_find_push_promise(conn, push_id);
- if (pp) {
- if (pp->stream) {
- return NGHTTP3_ERR_H3_ID_ERROR;
- }
- pp->stream = stream;
- stream->pp = pp;
-
- assert(!(pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL));
- assert(!(pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL));
-
- if (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECVED) {
- ++conn->remote.uni.unsent_max_pushes;
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_PUSH_ID_RECLAIMED;
-
- return conn_call_push_stream(conn, push_id, stream);
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED;
-
- return 0;
- }
-
- /* Push ID has been received, but pp is gone. This means that
- push is cancelled or server is misbehaving. We have no
- information to distinguish the two, so just cancel QPACK stream
- just in case, and ask application to send STOP_SENDING and
- ignore all frames in this stream. */
- rv = nghttp3_qpack_decoder_cancel_stream(&conn->qdec, stream->node.nid.id);
- if (rv != 0) {
- return rv;
- }
- rv =
- conn_call_send_stop_sending(conn, stream, NGHTTP3_H3_REQUEST_CANCELLED);
- if (rv != 0) {
- return rv;
- }
- return NGHTTP3_ERR_IGNORE_STREAM;
- }
-
- if (conn->remote.uni.max_pushes <= (uint64_t)push_id) {
- return NGHTTP3_ERR_H3_ID_ERROR;
- }
-
- rv = nghttp3_gaptr_push(&conn->remote.uni.push_idtr, (uint64_t)push_id, 1);
- if (rv != 0) {
- return rv;
- }
-
- /* Don't know the associated stream of PUSH_PROMISE. It doesn't
- matter because client sends nothing to this stream. */
- rv = nghttp3_conn_create_push_promise(conn, &pp, push_id, NULL);
- if (rv != 0) {
- return rv;
- }
-
- pp->stream = stream;
- stream->pp = pp;
- stream->flags |= NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED;
-
- return 0;
-}
-
-static nghttp3_ssize conn_decode_headers(nghttp3_conn *conn,
- nghttp3_stream *stream,
- nghttp3_push_promise *pp,
- const uint8_t *src, size_t srclen,
- int fin) {
- nghttp3_ssize nread;
- int rv;
- nghttp3_qpack_decoder *qdec = &conn->qdec;
- nghttp3_qpack_nv nv;
- uint8_t flags;
- nghttp3_buf buf;
- nghttp3_recv_header recv_header = NULL;
- nghttp3_http_state *http;
- int request = 0;
- int trailers = 0;
- int ignore_pp = 0;
-
- if (pp) {
- request = 1;
- ignore_pp = pp->stream_id != stream->node.nid.id;
- if (ignore_pp) {
- http = NULL;
- } else {
- http = &pp->http;
- }
- } else {
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
- request = 1;
- /* Fall through */
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- recv_header = conn->callbacks.recv_header;
- break;
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- request = 1;
- /* Fall through */
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- trailers = 1;
- recv_header = conn->callbacks.recv_trailer;
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- http = &stream->rx.http;
- }
-
- nghttp3_buf_wrap_init(&buf, (uint8_t *)src, srclen);
- buf.last = buf.end;
-
- for (;;) {
- nread = nghttp3_qpack_decoder_read_request(qdec, &stream->qpack_sctx, &nv,
- &flags, buf.pos,
- nghttp3_buf_len(&buf), fin);
-
- if (nread < 0) {
- return (int)nread;
- }
-
- buf.pos += nread;
-
- if (flags & NGHTTP3_QPACK_DECODE_FLAG_BLOCKED) {
- if (conn->local.settings.qpack_blocked_streams <=
- nghttp3_pq_size(&conn->qpack_blocked_streams)) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED;
- rv = nghttp3_conn_qpack_blocked_streams_push(conn, stream);
- if (rv != 0) {
- return rv;
- }
- break;
- }
-
- if (flags & NGHTTP3_QPACK_DECODE_FLAG_FINAL) {
- nghttp3_qpack_stream_context_reset(&stream->qpack_sctx);
- break;
- }
-
- if (nread == 0) {
- break;
- }
-
- if (flags & NGHTTP3_QPACK_DECODE_FLAG_EMIT) {
- if (ignore_pp) {
- nghttp3_rcbuf_decref(nv.name);
- nghttp3_rcbuf_decref(nv.value);
-
- continue;
- }
-
- assert(http);
-
- rv = nghttp3_http_on_header(http, stream->rstate.fr.hd.type, &nv, request,
- trailers);
- switch (rv) {
- case NGHTTP3_ERR_MALFORMED_HTTP_HEADER:
- break;
- case NGHTTP3_ERR_REMOVE_HTTP_HEADER:
- rv = 0;
- break;
- case 0:
- if (pp) {
- if (conn->callbacks.recv_push_promise) {
- rv = conn->callbacks.recv_push_promise(
- conn, stream->node.nid.id, pp->node.nid.id, nv.token, nv.name,
- nv.value, nv.flags, conn->user_data, stream->user_data);
- }
- break;
- }
- if (recv_header) {
- rv = recv_header(conn, stream->node.nid.id, nv.token, nv.name,
- nv.value, nv.flags, conn->user_data,
- stream->user_data);
- }
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- nghttp3_rcbuf_decref(nv.name);
- nghttp3_rcbuf_decref(nv.value);
-
- if (rv != 0) {
- return rv;
- }
- }
- }
-
- return buf.pos - src;
-}
-
-nghttp3_ssize nghttp3_conn_on_headers(nghttp3_conn *conn,
- nghttp3_stream *stream,
- nghttp3_push_promise *pp,
- const uint8_t *src, size_t srclen,
- int fin) {
- if (srclen == 0 && !fin) {
- return 0;
- }
-
- return conn_decode_headers(conn, stream, pp, src, srclen, fin);
-}
-
-int nghttp3_conn_on_settings_entry_received(nghttp3_conn *conn,
- const nghttp3_frame_settings *fr) {
- const nghttp3_settings_entry *ent = &fr->iv[0];
- nghttp3_conn_settings *dest = &conn->remote.settings;
- int rv;
- size_t max_table_capacity = SIZE_MAX;
- size_t max_blocked_streams = SIZE_MAX;
-
- /* TODO Check for duplicates */
- switch (ent->id) {
- case NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE:
- dest->max_field_section_size = ent->value;
- break;
- case NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY:
- dest->qpack_max_table_capacity = (size_t)ent->value;
- max_table_capacity =
- nghttp3_min(max_table_capacity, dest->qpack_max_table_capacity);
- rv = nghttp3_qpack_encoder_set_hard_max_dtable_size(&conn->qenc,
- max_table_capacity);
- if (rv != 0) {
- return rv;
- }
- rv = nghttp3_qpack_encoder_set_max_dtable_size(&conn->qenc,
- max_table_capacity);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS:
- dest->qpack_blocked_streams = (size_t)ent->value;
- max_blocked_streams =
- nghttp3_min(max_blocked_streams, dest->qpack_blocked_streams);
- rv =
- nghttp3_qpack_encoder_set_max_blocked(&conn->qenc, max_blocked_streams);
- if (rv != 0) {
- return rv;
- }
- break;
- default:
- /* Ignore unknown settings ID */
- break;
- }
-
- return 0;
-}
-
-static int conn_stream_acked_data(nghttp3_stream *stream, int64_t stream_id,
- size_t datalen, void *user_data) {
- nghttp3_conn *conn = stream->conn;
- int rv;
-
- if (!conn->callbacks.acked_stream_data) {
- return 0;
- }
-
- rv = conn->callbacks.acked_stream_data(conn, stream_id, datalen,
- conn->user_data, user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream,
- int64_t stream_id) {
- nghttp3_stream *stream;
- int rv;
- nghttp3_stream_callbacks callbacks = {
- conn_stream_acked_data,
- };
-
- rv = nghttp3_stream_new(&stream, stream_id, conn->next_seq, &callbacks,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- stream->conn = conn;
-
- rv = nghttp3_map_insert(&conn->streams, &stream->me);
- if (rv != 0) {
- nghttp3_stream_del(stream);
- return rv;
- }
-
- ++conn->next_seq;
- *pstream = stream;
-
- return 0;
-}
-
-int nghttp3_conn_create_push_promise(nghttp3_conn *conn,
- nghttp3_push_promise **ppp,
- int64_t push_id,
- nghttp3_tnode *assoc_tnode) {
- nghttp3_push_promise *pp;
- int rv;
-
- rv = nghttp3_push_promise_new(&pp, push_id, conn->next_seq, assoc_tnode,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_map_insert(&conn->pushes, &pp->me);
- if (rv != 0) {
- nghttp3_push_promise_del(pp, conn->mem);
- return rv;
- }
-
- ++conn->next_seq;
- *ppp = pp;
-
- return 0;
-}
-
-nghttp3_stream *nghttp3_conn_find_stream(nghttp3_conn *conn,
- int64_t stream_id) {
- nghttp3_map_entry *me;
-
- me = nghttp3_map_find(&conn->streams, (key_type)stream_id);
- if (me == NULL) {
- return NULL;
- }
-
- return nghttp3_struct_of(me, nghttp3_stream, me);
-}
-
-nghttp3_push_promise *nghttp3_conn_find_push_promise(nghttp3_conn *conn,
- int64_t push_id) {
- nghttp3_map_entry *me;
-
- me = nghttp3_map_find(&conn->pushes, (key_type)push_id);
- if (me == NULL) {
- return NULL;
- }
-
- return nghttp3_struct_of(me, nghttp3_push_promise, me);
-}
-
-int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, int64_t stream_id) {
- nghttp3_stream *stream;
- nghttp3_frame_entry frent;
- int rv;
-
- assert(!conn->server || nghttp3_server_stream_uni(stream_id));
- assert(conn->server || nghttp3_client_stream_uni(stream_id));
-
- if (conn->tx.ctrl) {
- return NGHTTP3_ERR_INVALID_STATE;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- if (rv != 0) {
- return rv;
- }
-
- stream->type = NGHTTP3_STREAM_TYPE_CONTROL;
-
- conn->tx.ctrl = stream;
-
- rv = nghttp3_stream_write_stream_type(stream);
- if (rv != 0) {
- return rv;
- }
-
- frent.fr.hd.type = NGHTTP3_FRAME_SETTINGS;
- frent.aux.settings.local_settings = &conn->local.settings;
-
- return nghttp3_stream_frq_add(stream, &frent);
-}
-
-int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, int64_t qenc_stream_id,
- int64_t qdec_stream_id) {
- nghttp3_stream *stream;
- int rv;
-
- assert(!conn->server || nghttp3_server_stream_uni(qenc_stream_id));
- assert(!conn->server || nghttp3_server_stream_uni(qdec_stream_id));
- assert(conn->server || nghttp3_client_stream_uni(qenc_stream_id));
- assert(conn->server || nghttp3_client_stream_uni(qdec_stream_id));
-
- if (conn->tx.qenc || conn->tx.qdec) {
- return NGHTTP3_ERR_INVALID_STATE;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, qenc_stream_id);
- if (rv != 0) {
- return rv;
- }
-
- stream->type = NGHTTP3_STREAM_TYPE_QPACK_ENCODER;
-
- conn->tx.qenc = stream;
-
- rv = nghttp3_stream_write_stream_type(stream);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, qdec_stream_id);
- if (rv != 0) {
- return rv;
- }
-
- stream->type = NGHTTP3_STREAM_TYPE_QPACK_DECODER;
-
- conn->tx.qdec = stream;
-
- return nghttp3_stream_write_stream_type(stream);
-}
-
-static nghttp3_ssize conn_writev_stream(nghttp3_conn *conn, int64_t *pstream_id,
- int *pfin, nghttp3_vec *vec,
- size_t veccnt, nghttp3_stream *stream) {
- int rv;
- nghttp3_ssize n;
-
- assert(veccnt > 0);
-
- /* If stream is blocked by read callback, don't attempt to fill
- more. */
- if (!(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED)) {
- rv = nghttp3_stream_fill_outq(stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (!nghttp3_stream_uni(stream->node.nid.id) && conn->tx.qenc &&
- !nghttp3_stream_is_blocked(conn->tx.qenc)) {
- n = nghttp3_stream_writev(conn->tx.qenc, pfin, vec, veccnt);
- if (n < 0) {
- return n;
- }
- if (n) {
- *pstream_id = conn->tx.qenc->node.nid.id;
- return n;
- }
- }
-
- n = nghttp3_stream_writev(stream, pfin, vec, veccnt);
- if (n < 0) {
- return n;
- }
- /* We might just want to write stream fin without sending any stream
- data. */
- if (n == 0 && *pfin == 0) {
- return 0;
- }
-
- *pstream_id = stream->node.nid.id;
-
- return n;
-}
-
-nghttp3_ssize nghttp3_conn_writev_stream(nghttp3_conn *conn,
- int64_t *pstream_id, int *pfin,
- nghttp3_vec *vec, size_t veccnt) {
- nghttp3_ssize ncnt;
- nghttp3_stream *stream;
- int rv;
-
- *pstream_id = -1;
- *pfin = 0;
-
- if (veccnt == 0) {
- return 0;
- }
-
- if (conn->tx.ctrl && !nghttp3_stream_is_blocked(conn->tx.ctrl)) {
- if (!(conn->flags & NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED) &&
- conn->remote.uni.unsent_max_pushes > conn->remote.uni.max_pushes) {
- rv = nghttp3_conn_submit_max_push_id(conn);
- if (rv != 0) {
- return rv;
- }
- }
-
- ncnt =
- conn_writev_stream(conn, pstream_id, pfin, vec, veccnt, conn->tx.ctrl);
- if (ncnt) {
- return ncnt;
- }
- }
-
- if (conn->tx.qdec && !nghttp3_stream_is_blocked(conn->tx.qdec)) {
- rv = nghttp3_stream_write_qpack_decoder_stream(conn->tx.qdec);
- if (rv != 0) {
- return rv;
- }
-
- ncnt =
- conn_writev_stream(conn, pstream_id, pfin, vec, veccnt, conn->tx.qdec);
- if (ncnt) {
- return ncnt;
- }
- }
-
- if (conn->tx.qenc && !nghttp3_stream_is_blocked(conn->tx.qenc)) {
- ncnt =
- conn_writev_stream(conn, pstream_id, pfin, vec, veccnt, conn->tx.qenc);
- if (ncnt) {
- return ncnt;
- }
- }
-
- stream = nghttp3_conn_get_next_tx_stream(conn);
- if (stream == NULL) {
- return 0;
- }
-
- ncnt = conn_writev_stream(conn, pstream_id, pfin, vec, veccnt, stream);
- if (ncnt < 0) {
- return ncnt;
- }
-
- if (nghttp3_stream_bidi_or_push(stream) &&
- !nghttp3_stream_require_schedule(stream)) {
- nghttp3_conn_unschedule_stream(conn, stream);
- }
-
- return ncnt;
-}
-
-nghttp3_stream *nghttp3_conn_get_next_tx_stream(nghttp3_conn *conn) {
- size_t i;
- nghttp3_tnode *tnode;
- nghttp3_pq *pq;
-
- for (i = 0; i < NGHTTP3_URGENCY_LEVELS; ++i) {
- pq = &conn->sched[i].spq;
- if (nghttp3_pq_empty(pq)) {
- continue;
- }
-
- tnode = nghttp3_struct_of(nghttp3_pq_top(pq), nghttp3_tnode, pe);
-
- if (tnode->nid.type == NGHTTP3_NODE_ID_TYPE_PUSH) {
- return nghttp3_struct_of(tnode, nghttp3_push_promise, node)->stream;
- }
-
- return nghttp3_struct_of(tnode, nghttp3_stream, node);
- }
-
- return NULL;
-}
-
-int nghttp3_conn_add_write_offset(nghttp3_conn *conn, int64_t stream_id,
- size_t n) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
- int rv;
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- rv = nghttp3_stream_add_outq_offset(stream, n);
- if (rv != 0) {
- return rv;
- }
-
- stream->unscheduled_nwrite += n;
-
- if (!nghttp3_stream_bidi_or_push(stream)) {
- return 0;
- }
-
- if (!nghttp3_stream_require_schedule(stream)) {
- nghttp3_conn_unschedule_stream(conn, stream);
- return 0;
- }
-
- if (stream->unscheduled_nwrite < NGHTTP3_STREAM_MIN_WRITELEN) {
- return 0;
- }
-
- return nghttp3_conn_schedule_stream(conn, stream);
-}
-
-int nghttp3_conn_add_ack_offset(nghttp3_conn *conn, int64_t stream_id,
- uint64_t n) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- return nghttp3_stream_add_ack_offset(stream, n);
-}
-
-static int conn_submit_headers_data(nghttp3_conn *conn, nghttp3_stream *stream,
- const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_data_reader *dr) {
- int rv;
- nghttp3_nv *nnva;
- nghttp3_frame_entry frent;
-
- rv = nghttp3_nva_copy(&nnva, nva, nvlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- frent.fr.hd.type = NGHTTP3_FRAME_HEADERS;
- frent.fr.headers.nva = nnva;
- frent.fr.headers.nvlen = nvlen;
-
- rv = nghttp3_stream_frq_add(stream, &frent);
- if (rv != 0) {
- nghttp3_nva_del(nnva, conn->mem);
- return rv;
- }
-
- if (dr) {
- frent.fr.hd.type = NGHTTP3_FRAME_DATA;
- frent.aux.data.dr = *dr;
-
- rv = nghttp3_stream_frq_add(stream, &frent);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (nghttp3_stream_require_schedule(stream)) {
- return nghttp3_conn_schedule_stream(conn, stream);
- }
-
- return 0;
-}
-
-static nghttp3_tnode *stream_get_dependency_node(nghttp3_stream *stream) {
- if (stream->pp) {
- assert(stream->type == NGHTTP3_STREAM_TYPE_PUSH);
- return &stream->pp->node;
- }
-
- return &stream->node;
-}
-
-int nghttp3_conn_schedule_stream(nghttp3_conn *conn, nghttp3_stream *stream) {
- /* Assume that stream stays on the same urgency level */
- int rv;
-
- rv = nghttp3_tnode_schedule(stream_get_dependency_node(stream),
- conn_get_sched_pq(conn, &stream->node),
- stream->unscheduled_nwrite);
- if (rv != 0) {
- return rv;
- }
-
- stream->unscheduled_nwrite = 0;
-
- return 0;
-}
-
-int nghttp3_conn_ensure_stream_scheduled(nghttp3_conn *conn,
- nghttp3_stream *stream) {
- if (nghttp3_tnode_is_scheduled(stream_get_dependency_node(stream))) {
- return 0;
- }
-
- return nghttp3_conn_schedule_stream(conn, stream);
-}
-
-void nghttp3_conn_unschedule_stream(nghttp3_conn *conn,
- nghttp3_stream *stream) {
- nghttp3_tnode_unschedule(stream_get_dependency_node(stream),
- conn_get_sched_pq(conn, &stream->node));
-}
-
-int nghttp3_conn_submit_request(nghttp3_conn *conn, int64_t stream_id,
- const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_data_reader *dr,
- void *stream_user_data) {
- nghttp3_stream *stream;
- int rv;
-
- assert(!conn->server);
- assert(conn->tx.qenc);
-
- assert(nghttp3_client_stream_bidi(stream_id));
-
- /* TODO Should we check that stream_id is client stream_id? */
- /* TODO Check GOAWAY last stream ID */
- if (nghttp3_stream_uni(stream_id)) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream != NULL) {
- return NGHTTP3_ERR_STREAM_IN_USE;
- }
-
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- if (rv != 0) {
- return rv;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
- stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
- stream->user_data = stream_user_data;
-
- nghttp3_http_record_request_method(stream, nva, nvlen);
-
- if (dr == NULL) {
- stream->flags |= NGHTTP3_STREAM_FLAG_WRITE_END_STREAM;
- }
-
- return conn_submit_headers_data(conn, stream, nva, nvlen, dr);
-}
-
-int nghttp3_conn_submit_info(nghttp3_conn *conn, int64_t stream_id,
- const nghttp3_nv *nva, size_t nvlen) {
- nghttp3_stream *stream;
-
- /* TODO Verify that it is allowed to send info (non-final response)
- now. */
- assert(conn->server);
- assert(conn->tx.qenc);
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- return conn_submit_headers_data(conn, stream, nva, nvlen, NULL);
-}
-
-int nghttp3_conn_submit_response(nghttp3_conn *conn, int64_t stream_id,
- const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_data_reader *dr) {
- nghttp3_stream *stream;
-
- /* TODO Verify that it is allowed to send response now. */
- assert(conn->server);
- assert(conn->tx.qenc);
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- if (dr == NULL) {
- stream->flags |= NGHTTP3_STREAM_FLAG_WRITE_END_STREAM;
- }
-
- return conn_submit_headers_data(conn, stream, nva, nvlen, dr);
-}
-
-int nghttp3_conn_submit_trailers(nghttp3_conn *conn, int64_t stream_id,
- const nghttp3_nv *nva, size_t nvlen) {
- nghttp3_stream *stream;
-
- /* TODO Verify that it is allowed to send trailer now. */
- assert(conn->tx.qenc);
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- if (stream->flags & NGHTTP3_STREAM_FLAG_WRITE_END_STREAM) {
- return NGHTTP3_ERR_INVALID_STATE;
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_WRITE_END_STREAM;
-
- return conn_submit_headers_data(conn, stream, nva, nvlen, NULL);
-}
-
-int nghttp3_conn_submit_push_promise(nghttp3_conn *conn, int64_t *ppush_id,
- int64_t stream_id, const nghttp3_nv *nva,
- size_t nvlen) {
- nghttp3_stream *stream;
- int rv;
- nghttp3_nv *nnva;
- nghttp3_frame_entry frent;
- int64_t push_id;
- nghttp3_push_promise *pp;
-
- assert(conn->server);
- assert(conn->tx.qenc);
- assert(nghttp3_client_stream_bidi(stream_id));
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- if (conn->local.uni.max_pushes <= (uint64_t)conn->local.uni.next_push_id) {
- return NGHTTP3_ERR_PUSH_ID_BLOCKED;
- }
-
- push_id = conn->local.uni.next_push_id;
-
- rv = nghttp3_conn_create_push_promise(conn, &pp, push_id, &stream->node);
- if (rv != 0) {
- return rv;
- }
-
- ++conn->local.uni.next_push_id;
-
- rv = nghttp3_nva_copy(&nnva, nva, nvlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- frent.fr.hd.type = NGHTTP3_FRAME_PUSH_PROMISE;
- frent.fr.push_promise.push_id = push_id;
- frent.fr.push_promise.nva = nnva;
- frent.fr.push_promise.nvlen = nvlen;
-
- rv = nghttp3_stream_frq_add(stream, &frent);
- if (rv != 0) {
- nghttp3_nva_del(nnva, conn->mem);
- return rv;
- }
-
- *ppush_id = push_id;
-
- if (nghttp3_stream_require_schedule(stream)) {
- return nghttp3_conn_schedule_stream(conn, stream);
- }
-
- return 0;
-}
-
-int nghttp3_conn_bind_push_stream(nghttp3_conn *conn, int64_t push_id,
- int64_t stream_id) {
- nghttp3_push_promise *pp;
- nghttp3_stream *stream;
- int rv;
-
- assert(conn->server);
- assert(nghttp3_server_stream_uni(stream_id));
-
- pp = nghttp3_conn_find_push_promise(conn, push_id);
- if (pp == NULL) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- assert(NULL == nghttp3_conn_find_stream(conn, stream_id));
-
- rv = nghttp3_conn_create_stream(conn, &stream, stream_id);
- if (rv != 0) {
- return rv;
- }
-
- stream->type = NGHTTP3_STREAM_TYPE_PUSH;
- stream->pp = pp;
-
- pp->stream = stream;
-
- rv = nghttp3_stream_write_stream_type_push_id(stream);
- if (rv != 0) {
- return rv;
- }
-
- return 0;
-}
-
-int nghttp3_conn_cancel_push(nghttp3_conn *conn, int64_t push_id) {
- if (conn->server) {
- return nghttp3_conn_server_cancel_push(conn, push_id);
- }
- return nghttp3_conn_client_cancel_push(conn, push_id);
-}
-
-int nghttp3_conn_server_cancel_push(nghttp3_conn *conn, int64_t push_id) {
- nghttp3_push_promise *pp;
- nghttp3_frame_entry frent;
- int rv;
-
- assert(conn->tx.ctrl);
-
- pp = nghttp3_conn_find_push_promise(conn, push_id);
- if (pp == NULL) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (!(pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL)) {
- frent.fr.hd.type = NGHTTP3_FRAME_CANCEL_PUSH;
- frent.fr.cancel_push.push_id = push_id;
-
- rv = nghttp3_stream_frq_add(conn->tx.ctrl, &frent);
- if (rv != 0) {
- return rv;
- }
-
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL;
- }
-
- if (pp->stream) {
- /* CANCEL_PUSH will be sent, but it does not affect pushed stream.
- Application should explicitly shutdown the stream. */
- return NGHTTP3_ERR_TOO_LATE;
- }
-
- nghttp3_tnode_unschedule(&pp->node, conn_get_sched_pq(conn, &pp->node));
-
- conn_delete_push_promise(conn, pp);
-
- return 0;
-}
-
-int nghttp3_conn_client_cancel_push(nghttp3_conn *conn, int64_t push_id) {
- nghttp3_push_promise *pp;
- nghttp3_frame_entry frent;
- int rv;
-
- pp = nghttp3_conn_find_push_promise(conn, push_id);
- if (pp == NULL) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (pp->stream) {
- return NGHTTP3_ERR_TOO_LATE;
- }
-
- frent.fr.hd.type = NGHTTP3_FRAME_CANCEL_PUSH;
- frent.fr.cancel_push.push_id = push_id;
-
- rv = nghttp3_stream_frq_add(conn->tx.ctrl, &frent);
- if (rv != 0) {
- return rv;
- }
-
- if (pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECVED) {
- conn_delete_push_promise(conn, pp);
- return 0;
- }
-
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL;
-
- return 0;
-}
-
-int nghttp3_conn_block_stream(nghttp3_conn *conn, int64_t stream_id) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_FC_BLOCKED;
- stream->unscheduled_nwrite = 0;
-
- if (nghttp3_stream_bidi_or_push(stream)) {
- nghttp3_conn_unschedule_stream(conn, stream);
- }
-
- return 0;
-}
-
-int nghttp3_conn_unblock_stream(nghttp3_conn *conn, int64_t stream_id) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- stream->flags &= (uint16_t)~NGHTTP3_STREAM_FLAG_FC_BLOCKED;
-
- if (nghttp3_stream_bidi_or_push(stream) &&
- nghttp3_stream_require_schedule(stream)) {
- return nghttp3_conn_ensure_stream_scheduled(conn, stream);
- }
-
- return 0;
-}
-
-int nghttp3_conn_resume_stream(nghttp3_conn *conn, int64_t stream_id) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- stream->flags &= (uint16_t)~NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED;
-
- if (nghttp3_stream_bidi_or_push(stream) &&
- nghttp3_stream_require_schedule(stream)) {
- return nghttp3_conn_ensure_stream_scheduled(conn, stream);
- }
-
- return 0;
-}
-
-int nghttp3_conn_close_stream(nghttp3_conn *conn, int64_t stream_id,
- uint64_t app_error_code) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- if (nghttp3_stream_uni(stream_id) &&
- stream->type != NGHTTP3_STREAM_TYPE_PUSH &&
- stream->type != NGHTTP3_STREAM_TYPE_UNKNOWN) {
- return NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM;
- }
-
- stream->error_code = app_error_code;
-
- nghttp3_conn_unschedule_stream(conn, stream);
-
- if (stream->qpack_blocked_pe.index == NGHTTP3_PQ_BAD_INDEX &&
- (conn->server || !stream->pp ||
- (stream->pp->flags & NGHTTP3_PUSH_PROMISE_FLAG_RECVED))) {
- return conn_delete_stream(conn, stream);
- }
-
- stream->flags |= NGHTTP3_STREAM_FLAG_CLOSED;
- return 0;
-}
-
-int nghttp3_conn_reset_stream(nghttp3_conn *conn, int64_t stream_id) {
- nghttp3_stream *stream;
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- if (stream) {
- stream->flags |= NGHTTP3_STREAM_FLAG_RESET;
- }
- return nghttp3_qpack_decoder_cancel_stream(&conn->qdec, stream_id);
-}
-
-int nghttp3_conn_qpack_blocked_streams_push(nghttp3_conn *conn,
- nghttp3_stream *stream) {
- assert(stream->qpack_blocked_pe.index == NGHTTP3_PQ_BAD_INDEX);
-
- return nghttp3_pq_push(&conn->qpack_blocked_streams,
- &stream->qpack_blocked_pe);
-}
-
-void nghttp3_conn_qpack_blocked_streams_pop(nghttp3_conn *conn) {
- assert(!nghttp3_pq_empty(&conn->qpack_blocked_streams));
- nghttp3_pq_pop(&conn->qpack_blocked_streams);
-}
-
-void nghttp3_conn_set_max_client_streams_bidi(nghttp3_conn *conn,
- uint64_t max_streams) {
- assert(conn->server);
- assert(conn->remote.bidi.max_client_streams <= max_streams);
-
- conn->remote.bidi.max_client_streams = max_streams;
-}
-
-void nghttp3_conn_set_max_concurrent_streams(nghttp3_conn *conn,
- size_t max_concurrent_streams) {
- nghttp3_qpack_decoder_set_max_concurrent_streams(&conn->qdec,
- max_concurrent_streams);
-}
-
-int nghttp3_conn_submit_max_push_id(nghttp3_conn *conn) {
- nghttp3_frame_entry frent;
- int rv;
-
- assert(conn->tx.ctrl);
- assert(!(conn->flags & NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED));
-
- frent.fr.hd.type = NGHTTP3_FRAME_MAX_PUSH_ID;
- /* The acutal push_id is set when frame is serialized */
-
- rv = nghttp3_stream_frq_add(conn->tx.ctrl, &frent);
- if (rv != 0) {
- return rv;
- }
-
- conn->flags |= NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED;
-
- return 0;
-}
-
-int nghttp3_conn_set_stream_user_data(nghttp3_conn *conn, int64_t stream_id,
- void *stream_user_data) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- stream->user_data = stream_user_data;
-
- return 0;
-}
-
-int64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn,
- int64_t stream_id) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- return stream->rstate.left;
-}
-
-int nghttp3_conn_get_stream_priority(nghttp3_conn *conn, nghttp3_pri *dest,
- int64_t stream_id) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- assert(conn->server);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- dest->urgency = nghttp3_pri_uint8_urgency(stream->rx.http.pri);
- dest->inc = nghttp3_pri_uint8_inc(stream->rx.http.pri);
-
- return 0;
-}
-
-int nghttp3_conn_set_stream_priority(nghttp3_conn *conn, int64_t stream_id,
- const nghttp3_pri *pri) {
- nghttp3_stream *stream = nghttp3_conn_find_stream(conn, stream_id);
-
- assert(conn->server);
- assert(pri->urgency < NGHTTP3_URGENCY_LEVELS);
- assert(pri->inc == 0 || pri->inc == 1);
-
- if (stream == NULL) {
- return NGHTTP3_ERR_STREAM_NOT_FOUND;
- }
-
- stream->rx.http.pri = nghttp3_pri_to_uint8(pri);
-
- return conn_update_stream_priority(conn, stream, stream->rx.http.pri);
-}
-
-int nghttp3_conn_is_remote_qpack_encoder_stream(nghttp3_conn *conn,
- int64_t stream_id) {
- nghttp3_stream *stream;
-
- if (!conn_remote_stream_uni(conn, stream_id)) {
- return 0;
- }
-
- stream = nghttp3_conn_find_stream(conn, stream_id);
- return stream && stream->type == NGHTTP3_STREAM_TYPE_QPACK_ENCODER;
-}
-
-void nghttp3_conn_settings_default(nghttp3_conn_settings *settings) {
- memset(settings, 0, sizeof(nghttp3_conn_settings));
- settings->max_field_section_size = NGHTTP3_VARINT_MAX;
-}
-
-int nghttp3_push_promise_new(nghttp3_push_promise **ppp, int64_t push_id,
- uint64_t seq, nghttp3_tnode *assoc_tnode,
- const nghttp3_mem *mem) {
- nghttp3_push_promise *pp;
- nghttp3_node_id nid;
-
- pp = nghttp3_mem_calloc(mem, 1, sizeof(nghttp3_push_promise));
- if (pp == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- nghttp3_tnode_init(
- &pp->node, nghttp3_node_id_init(&nid, NGHTTP3_NODE_ID_TYPE_PUSH, push_id),
- seq, NGHTTP3_DEFAULT_URGENCY);
-
- pp->me.key = (key_type)push_id;
- pp->node.nid.id = push_id;
- pp->http.status_code = -1;
- pp->http.content_length = -1;
-
- if (assoc_tnode) {
- assert(assoc_tnode->nid.type == NGHTTP3_NODE_ID_TYPE_STREAM);
-
- pp->stream_id = assoc_tnode->nid.id;
- pp->flags |= NGHTTP3_PUSH_PROMISE_FLAG_BOUND;
- } else {
- pp->stream_id = -1;
- }
-
- *ppp = pp;
-
- return 0;
-}
-
-void nghttp3_push_promise_del(nghttp3_push_promise *pp,
- const nghttp3_mem *mem) {
- if (pp == NULL) {
- return;
- }
-
- nghttp3_tnode_free(&pp->node);
-
- nghttp3_mem_free(mem, pp);
-}
diff --git a/deps/nghttp3/lib/nghttp3_conn.h b/deps/nghttp3/lib/nghttp3_conn.h
deleted file mode 100644
index 720b610242..0000000000
--- a/deps/nghttp3/lib/nghttp3_conn.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_CONN_H
-#define NGHTTP3_CONN_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_stream.h"
-#include "nghttp3_map.h"
-#include "nghttp3_qpack.h"
-#include "nghttp3_tnode.h"
-#include "nghttp3_idtr.h"
-#include "nghttp3_gaptr.h"
-
-#define NGHTTP3_VARINT_MAX ((1ull << 62) - 1)
-
-/* NGHTTP3_QPACK_ENCODER_MAX_TABLE_CAPACITY is the maximum dynamic
- table size for QPACK encoder. */
-#define NGHTTP3_QPACK_ENCODER_MAX_TABLE_CAPACITY 16384
-
-/* NGHTTP3_QPACK_ENCODER_MAX_BLOCK_STREAMS is the maximum number of
- blocked streams for QPACK encoder. */
-#define NGHTTP3_QPACK_ENCODER_MAX_BLOCK_STREAMS 100
-
-typedef enum {
- NGHTTP3_PUSH_PROMISE_FLAG_NONE = 0x00,
- /* NGHTTP3_PUSH_PROMISE_FLAG_RECVED is set when PUSH_PROMISE is
- completely received. */
- NGHTTP3_PUSH_PROMISE_FLAG_RECVED = 0x01,
- /* NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL is set when push is
- cancelled by server before receiving PUSH_PROMISE completely.
- This flag should have no effect if push stream has already
- opened. */
- NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL = 0x02,
- /* NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL is set when push is
- canceled by the local endpoint. */
- NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL = 0x04,
- NGHTTP3_PUSH_PROMISE_FLAG_CANCELLED = NGHTTP3_PUSH_PROMISE_FLAG_RECV_CANCEL |
- NGHTTP3_PUSH_PROMISE_FLAG_SENT_CANCEL,
- /* NGHTTP3_PUSH_PROMISE_FLAG_PUSH_ID_RECLAIMED indicates that
- unsent_max_pushes has been updated for this push ID. */
- NGHTTP3_PUSH_PROMISE_FLAG_PUSH_ID_RECLAIMED = 0x08,
- /* NGHTTP3_PUSH_PROMISE_FLAG_BOUND is set if nghttp3_push_promise
- object is bound to a stream where PUSH_PROMISE frame is received
- first. nghttp3_push_promise object might be created before
- receiving any PUSH_PROMISE when pushed stream is received before
- it.*/
- NGHTTP3_PUSH_PROMISE_FLAG_BOUND = 0x10,
-} nghttp3_push_promise_flag;
-
-struct nghttp3_push_promise;
-typedef struct nghttp3_push_promise nghttp3_push_promise;
-
-struct nghttp3_push_promise {
- nghttp3_map_entry me;
- nghttp3_tnode node;
- nghttp3_http_state http;
- /* stream is server initiated unidirectional stream which fulfils
- the push promise. */
- nghttp3_stream *stream;
- /* stream_id is the stream ID where this PUSH_PROMISE is first
- received. PUSH_PROMISE with same push ID is allowed to be sent
- in the multiple streams. We ignore those duplicated PUSH_PROMISE
- entirely because we don't see any value to add extra cost of
- processing for it. Even ignoring those frame is not yet easy
- because we have to decode the header blocks. Server push is
- overly complex and there is no good use case after all. */
- int64_t stream_id;
- /* flags is bitwise OR of zero or more of
- nghttp3_push_promise_flag. */
- uint16_t flags;
-};
-
-typedef enum {
- NGHTTP3_CONN_FLAG_NONE = 0x0000,
- NGHTTP3_CONN_FLAG_SETTINGS_RECVED = 0x0001,
- NGHTTP3_CONN_FLAG_CONTROL_OPENED = 0x0002,
- NGHTTP3_CONN_FLAG_QPACK_ENCODER_OPENED = 0x0004,
- NGHTTP3_CONN_FLAG_QPACK_DECODER_OPENED = 0x0008,
- /* NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED indicates that MAX_PUSH_ID
- has been queued to control stream. */
- NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED = 0x0010,
-} nghttp3_conn_flag;
-
-struct nghttp3_conn {
- nghttp3_conn_callbacks callbacks;
- nghttp3_map streams;
- nghttp3_map pushes;
- nghttp3_qpack_decoder qdec;
- nghttp3_qpack_encoder qenc;
- nghttp3_pq qpack_blocked_streams;
- struct {
- nghttp3_pq spq;
- } sched[NGHTTP3_URGENCY_LEVELS];
- const nghttp3_mem *mem;
- void *user_data;
- int server;
- uint16_t flags;
- uint64_t next_seq;
-
- struct {
- nghttp3_conn_settings settings;
- struct {
- /* max_pushes is the number of push IDs that local endpoint can
- issue. This field is used by server only. */
- uint64_t max_pushes;
- /* next_push_id is the next push ID server uses. This field is
- used by server only. */
- int64_t next_push_id;
- } uni;
- } local;
-
- struct {
- struct {
- nghttp3_idtr idtr;
- /* max_client_streams is the cumulative number of client
- initiated bidirectional stream ID the remote endpoint can
- issue. This field is used on server side only. */
- uint64_t max_client_streams;
- } bidi;
- struct {
- /* push_idtr tracks which push ID has been used by remote
- server. This field is used by client only. */
- nghttp3_gaptr push_idtr;
- /* unsent_max_pushes is the maximum number of push which the local
- endpoint can accept. This limit is not yet notified to the
- remote endpoint. This field is used by client only. */
- uint64_t unsent_max_pushes;
- /* max_push is the maximum number of push which the local
- endpoint can accept. This field is used by client only. */
- uint64_t max_pushes;
- } uni;
- nghttp3_conn_settings settings;
- } remote;
-
- struct {
- struct {
- nghttp3_buf rbuf;
- nghttp3_buf ebuf;
- } qpack;
- nghttp3_stream *ctrl;
- nghttp3_stream *qenc;
- nghttp3_stream *qdec;
- } tx;
-};
-
-nghttp3_stream *nghttp3_conn_find_stream(nghttp3_conn *conn, int64_t stream_id);
-
-nghttp3_push_promise *nghttp3_conn_find_push_promise(nghttp3_conn *conn,
- int64_t push_id);
-
-int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream,
- int64_t stream_id);
-
-int nghttp3_conn_create_push_promise(nghttp3_conn *conn,
- nghttp3_push_promise **ppp,
- int64_t push_id,
- nghttp3_tnode *assoc_tnode);
-
-nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc,
- nghttp3_stream *stream, const uint8_t *src,
- size_t srclen, int fin);
-
-nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream,
- const uint8_t *src, size_t srclen, int fin);
-
-nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
- nghttp3_stream *stream,
- const uint8_t *src, size_t srclen);
-
-nghttp3_ssize nghttp3_conn_read_push(nghttp3_conn *conn, size_t *pnproc,
- nghttp3_stream *stream, const uint8_t *src,
- size_t srclen, int fin);
-
-nghttp3_ssize nghttp3_conn_read_qpack_encoder(nghttp3_conn *conn,
- const uint8_t *src,
- size_t srclen);
-
-nghttp3_ssize nghttp3_conn_read_qpack_decoder(nghttp3_conn *conn,
- const uint8_t *src,
- size_t srclen);
-
-int nghttp3_conn_on_push_promise_push_id(nghttp3_conn *conn, int64_t push_id,
- nghttp3_stream *stream);
-
-int nghttp3_conn_on_client_cancel_push(nghttp3_conn *conn,
- const nghttp3_frame_cancel_push *fr);
-
-int nghttp3_conn_on_server_cancel_push(nghttp3_conn *conn,
- const nghttp3_frame_cancel_push *fr);
-
-int nghttp3_conn_on_stream_push_id(nghttp3_conn *conn, nghttp3_stream *stream,
- int64_t push_id);
-
-int nghttp3_conn_on_data(nghttp3_conn *conn, nghttp3_stream *stream,
- const uint8_t *data, size_t datalen);
-
-nghttp3_ssize nghttp3_conn_on_headers(nghttp3_conn *conn,
- nghttp3_stream *stream,
- nghttp3_push_promise *pp,
- const uint8_t *data, size_t datalen,
- int fin);
-
-int nghttp3_conn_on_settings_entry_received(nghttp3_conn *conn,
- const nghttp3_frame_settings *fr);
-
-int nghttp3_conn_qpack_blocked_streams_push(nghttp3_conn *conn,
- nghttp3_stream *stream);
-
-void nghttp3_conn_qpack_blocked_streams_pop(nghttp3_conn *conn);
-
-int nghttp3_conn_server_cancel_push(nghttp3_conn *conn, int64_t push_id);
-
-int nghttp3_conn_client_cancel_push(nghttp3_conn *conn, int64_t push_id);
-
-int nghttp3_conn_submit_max_push_id(nghttp3_conn *conn);
-
-int nghttp3_conn_schedule_stream(nghttp3_conn *conn, nghttp3_stream *stream);
-
-int nghttp3_conn_ensure_stream_scheduled(nghttp3_conn *conn,
- nghttp3_stream *stream);
-
-void nghttp3_conn_unschedule_stream(nghttp3_conn *conn, nghttp3_stream *stream);
-
-/*
- * nghttp3_conn_get_next_tx_stream returns next stream to send. It
- * returns NULL if there is no such stream.
- */
-nghttp3_stream *nghttp3_conn_get_next_tx_stream(nghttp3_conn *conn);
-
-int nghttp3_push_promise_new(nghttp3_push_promise **ppp, int64_t push_id,
- uint64_t seq, nghttp3_tnode *assoc_tnode,
- const nghttp3_mem *mem);
-
-void nghttp3_push_promise_del(nghttp3_push_promise *pp, const nghttp3_mem *mem);
-
-#endif /* NGHTTP3_CONN_H */
diff --git a/deps/nghttp3/lib/nghttp3_conv.c b/deps/nghttp3/lib/nghttp3_conv.c
deleted file mode 100644
index 04bf6a0f29..0000000000
--- a/deps/nghttp3/lib/nghttp3_conv.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_conv.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "nghttp3_str.h"
-
-int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p) {
- union {
- char b[8];
- uint16_t n16;
- uint32_t n32;
- uint64_t n64;
- } n;
-
- *plen = 1u << (*p >> 6);
-
- switch (*plen) {
- case 1:
- return (int64_t)*p;
- case 2:
- memcpy(&n, p, 2);
- n.b[0] &= 0x3f;
- return (int64_t)ntohs(n.n16);
- case 4:
- memcpy(&n, p, 4);
- n.b[0] &= 0x3f;
- return (int64_t)ntohl(n.n32);
- case 8:
- memcpy(&n, p, 8);
- n.b[0] &= 0x3f;
- return (int64_t)nghttp3_ntohl64(n.n64);
- }
-
- assert(0);
-}
-
-int64_t nghttp3_get_varint_fb(const uint8_t *p) { return *p & 0x3f; }
-
-size_t nghttp3_get_varint_len(const uint8_t *p) { return 1u << (*p >> 6); }
-
-uint8_t *nghttp3_put_uint64be(uint8_t *p, uint64_t n) {
- n = nghttp3_htonl64(n);
- return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n) {
- n = nghttp3_htonl64(n);
- return nghttp3_cpymem(p, ((const uint8_t *)&n) + 2, 6);
-}
-
-uint8_t *nghttp3_put_uint32be(uint8_t *p, uint32_t n) {
- n = htonl(n);
- return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *nghttp3_put_uint24be(uint8_t *p, uint32_t n) {
- n = htonl(n);
- return nghttp3_cpymem(p, ((const uint8_t *)&n) + 1, 3);
-}
-
-uint8_t *nghttp3_put_uint16be(uint8_t *p, uint16_t n) {
- n = htons(n);
- return nghttp3_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *nghttp3_put_varint(uint8_t *p, int64_t n) {
- uint8_t *rv;
- if (n < 64) {
- *p++ = (uint8_t)n;
- return p;
- }
- if (n < 16384) {
- rv = nghttp3_put_uint16be(p, (uint16_t)n);
- *p |= 0x40;
- return rv;
- }
- if (n < 1073741824) {
- rv = nghttp3_put_uint32be(p, (uint32_t)n);
- *p |= 0x80;
- return rv;
- }
- assert(n < 4611686018427387904LL);
- rv = nghttp3_put_uint64be(p, (uint64_t)n);
- *p |= 0xc0;
- return rv;
-}
-
-size_t nghttp3_put_varint_len(int64_t n) {
- if (n < 64) {
- return 1;
- }
- if (n < 16384) {
- return 2;
- }
- if (n < 1073741824) {
- return 4;
- }
- assert(n < 4611686018427387904LL);
- return 8;
-}
-
-uint64_t nghttp3_ord_stream_id(int64_t stream_id) {
- return (uint64_t)(stream_id >> 2) + 1;
-}
-
-uint8_t nghttp3_pri_to_uint8(const nghttp3_pri *pri) {
- return (uint8_t)((uint32_t)pri->inc << 7 | pri->urgency);
-}
diff --git a/deps/nghttp3/lib/nghttp3_conv.h b/deps/nghttp3/lib/nghttp3_conv.h
deleted file mode 100644
index 6fae9fc968..0000000000
--- a/deps/nghttp3/lib/nghttp3_conv.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_CONV_H
-#define NGHTTP3_CONV_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif /* HAVE_ARPA_INET_H */
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif /* HAVE_NETINET_IN_H */
-
-#ifdef HAVE_BYTESWAP_H
-# include <byteswap.h>
-#endif /* HAVE_BYTESWAP_H */
-
-#ifdef HAVE_ENDIAN_H
-# include <endian.h>
-#endif /* HAVE_ENDIAN_H */
-
-#ifdef HAVE_SYS_ENDIAN_H
-# include <sys/endian.h>
-#endif /* HAVE_SYS_ENDIAN_H */
-
-#include <nghttp3/nghttp3.h>
-
-#if defined HAVE_BSWAP_64 || HAVE_DECL_BSWAP_64
-# define nghttp3_bswap64 bswap_64
-#else /* !HAVE_BSWAP_64 */
-# define nghttp3_bswap64(N) \
- ((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32)))
-#endif /* !HAVE_BSWAP_64 */
-
-#if defined HAVE_BE64TOH || HAVE_DECL_BE64TOH
-# define nghttp3_ntohl64(N) be64toh(N)
-# define nghttp3_htonl64(N) htobe64(N)
-#else /* !HAVE_BE64TOH */
-# if defined WORDS_BIGENDIAN
-# define nghttp3_ntohl64(N) (N)
-# define nghttp3_htonl64(N) (N)
-# else /* !WORDS_BIGENDIAN */
-# define nghttp3_ntohl64(N) nghttp3_bswap64(N)
-# define nghttp3_htonl64(N) nghttp3_bswap64(N)
-# endif /* !WORDS_BIGENDIAN */
-#endif /* !HAVE_BE64TOH */
-
-#if defined(WIN32)
-/* Windows requires ws2_32 library for ntonl family of functions. We
- define inline functions for those functions so that we don't have
- dependency on that lib. */
-
-# ifdef _MSC_VER
-# define STIN static __inline
-# else
-# define STIN static inline
-# endif
-
-STIN uint32_t htonl(uint32_t hostlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostlong >> 24;
- *p++ = (hostlong >> 16) & 0xffu;
- *p++ = (hostlong >> 8) & 0xffu;
- *p = hostlong & 0xffu;
- return res;
-}
-
-STIN uint16_t htons(uint16_t hostshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostshort >> 8;
- *p = hostshort & 0xffu;
- return res;
-}
-
-STIN uint32_t ntohl(uint32_t netlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&netlong;
- res = *p++ << 24;
- res += *p++ << 16;
- res += *p++ << 8;
- res += *p;
- return res;
-}
-
-STIN uint16_t ntohs(uint16_t netshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&netshort;
- res = *p++ << 8;
- res += *p;
- return res;
-}
-
-#endif /* WIN32 */
-
-/*
- * nghttp3_get_varint reads variable-length integer from |p|, and
- * returns it in host byte order. The number of bytes read is stored
- * in |*plen|.
- */
-int64_t nghttp3_get_varint(size_t *plen, const uint8_t *p);
-
-/*
- * nghttp3_get_varint_fb reads first byte of encoded variable-length
- * integer from |p|.
- */
-int64_t nghttp3_get_varint_fb(const uint8_t *p);
-
-/*
- * nghttp3_get_varint_len returns the required number of bytes to read
- * variable-length integer starting at |p|.
- */
-size_t nghttp3_get_varint_len(const uint8_t *p);
-
-/*
- * nghttp3_put_uint64be writes |n| in host byte order in |p| in
- * network byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *nghttp3_put_uint64be(uint8_t *p, uint64_t n);
-
-/*
- * nghttp3_put_uint48be writes |n| in host byte order in |p| in
- * network byte order. It writes only least significant 48 bits. It
- * returns the one beyond of the last written position.
- */
-uint8_t *nghttp3_put_uint48be(uint8_t *p, uint64_t n);
-
-/*
- * nghttp3_put_uint32be writes |n| in host byte order in |p| in
- * network byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *nghttp3_put_uint32be(uint8_t *p, uint32_t n);
-
-/*
- * nghttp3_put_uint24be writes |n| in host byte order in |p| in
- * network byte order. It writes only least significant 24 bits. It
- * returns the one beyond of the last written position.
- */
-uint8_t *nghttp3_put_uint24be(uint8_t *p, uint32_t n);
-
-/*
- * nghttp3_put_uint16be writes |n| in host byte order in |p| in
- * network byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *nghttp3_put_uint16be(uint8_t *p, uint16_t n);
-
-/*
- * nghttp3_put_varint writes |n| in |p| using variable-length integer
- * encoding. It returns the one beyond of the last written position.
- */
-uint8_t *nghttp3_put_varint(uint8_t *p, int64_t n);
-
-/*
- * nghttp3_put_varint_len returns the required number of bytes to
- * encode |n|.
- */
-size_t nghttp3_put_varint_len(int64_t n);
-
-/*
- * nghttp3_ord_stream_id returns the ordinal number of |stream_id|.
- */
-uint64_t nghttp3_ord_stream_id(int64_t stream_id);
-
-/*
- * NGHTTP3_PRI_INC_MASK is a bit mask to retrieve incremental bit from
- * a value produced by nghttp3_pri_to_uint8.
- */
-#define NGHTTP3_PRI_INC_MASK (1 << 7)
-
-/*
- * nghttp3_pri_to_uint8 encodes |pri| into uint8_t variable.
- */
-uint8_t nghttp3_pri_to_uint8(const nghttp3_pri *pri);
-
-/*
- * nghttp3_pri_uint8_urgency extracts urgency from |PRI| which is
- * supposed to be constructed by nghttp3_pri_to_uint8.
- */
-#define nghttp3_pri_uint8_urgency(PRI) \
- ((uint32_t)((PRI) & ~NGHTTP3_PRI_INC_MASK))
-
-/*
- * nghttp3_pri_uint8_inc extracts inc from |PRI| which is supposed to
- * be constructed by nghttp3_pri_to_uint8.
- */
-#define nghttp3_pri_uint8_inc(PRI) (((PRI)&NGHTTP3_PRI_INC_MASK) != 0)
-
-#endif /* NGHTTP3_CONV_H */
diff --git a/deps/nghttp3/lib/nghttp3_debug.c b/deps/nghttp3/lib/nghttp3_debug.c
deleted file mode 100644
index 4021b0dc46..0000000000
--- a/deps/nghttp3/lib/nghttp3_debug.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2016 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_debug.h"
-
-#include <stdio.h>
-
-#ifdef DEBUGBUILD
-
-static void nghttp3_default_debug_vfprintf_callback(const char *fmt,
- va_list args) {
- vfprintf(stderr, fmt, args);
-}
-
-static nghttp3_debug_vprintf_callback static_debug_vprintf_callback =
- nghttp3_default_debug_vfprintf_callback;
-
-void nghttp3_debug_vprintf(const char *format, ...) {
- if (static_debug_vprintf_callback) {
- va_list args;
- va_start(args, format);
- static_debug_vprintf_callback(format, args);
- va_end(args);
- }
-}
-
-void nghttp3_set_debug_vprintf_callback(
- nghttp3_debug_vprintf_callback debug_vprintf_callback) {
- static_debug_vprintf_callback = debug_vprintf_callback;
-}
-
-#else /* !DEBUGBUILD */
-
-void nghttp3_set_debug_vprintf_callback(
- nghttp3_debug_vprintf_callback debug_vprintf_callback) {
- (void)debug_vprintf_callback;
-}
-
-#endif /* !DEBUGBUILD */
diff --git a/deps/nghttp3/lib/nghttp3_debug.h b/deps/nghttp3/lib/nghttp3_debug.h
deleted file mode 100644
index 01ed918414..0000000000
--- a/deps/nghttp3/lib/nghttp3_debug.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2016 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_DEBUG_H
-#define NGHTTP3_DEBUG_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#ifdef DEBUGBUILD
-# define DEBUGF(...) nghttp3_debug_vprintf(__VA_ARGS__)
-void nghttp3_debug_vprintf(const char *format, ...);
-#else
-# define DEBUGF(...) \
- do { \
- } while (0)
-#endif
-
-#endif /* NGHTTP3_DEBUG_H */
diff --git a/deps/nghttp3/lib/nghttp3_err.c b/deps/nghttp3/lib/nghttp3_err.c
deleted file mode 100644
index 23033d4640..0000000000
--- a/deps/nghttp3/lib/nghttp3_err.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_err.h"
-
-const char *nghttp3_strerror(int liberr) {
- switch (liberr) {
- case NGHTTP3_ERR_INVALID_ARGUMENT:
- return "ERR_INVALID_ARGUMENT";
- case NGHTTP3_ERR_NOBUF:
- return "ERR_NOBUF";
- case NGHTTP3_ERR_INVALID_STATE:
- return "ERR_INVALID_STATE";
- case NGHTTP3_ERR_WOULDBLOCK:
- return "ERR_WOULDBLOCK";
- case NGHTTP3_ERR_STREAM_IN_USE:
- return "ERR_STREAM_IN_USE";
- case NGHTTP3_ERR_PUSH_ID_BLOCKED:
- return "ERR_PUSH_ID_BLOCKED";
- case NGHTTP3_ERR_MALFORMED_HTTP_HEADER:
- return "ERR_MALFORMED_HTTP_HEADER";
- case NGHTTP3_ERR_REMOVE_HTTP_HEADER:
- return "ERR_REMOVE_HTTP_HEADER";
- case NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING:
- return "ERR_MALFORMED_HTTP_MESSAGING";
- case NGHTTP3_ERR_TOO_LATE:
- return "ERR_TOO_LATE";
- case NGHTTP3_ERR_QPACK_FATAL:
- return "ERR_QPACK_FATAL";
- case NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE:
- return "ERR_QPACK_HEADER_TOO_LARGE";
- case NGHTTP3_ERR_IGNORE_STREAM:
- return "ERR_IGNORE_STREAM";
- case NGHTTP3_ERR_STREAM_NOT_FOUND:
- return "ERR_STREAM_NOT_FOUND";
- case NGHTTP3_ERR_IGNORE_PUSH_PROMISE:
- return "ERR_IGNORE_PUSH_PROMISE";
- case NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED:
- return "ERR_QPACK_DECOMPRESSION_FAILED";
- case NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR:
- return "ERR_QPACK_ENCODER_STREAM_ERROR";
- case NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR:
- return "ERR_QPACK_DECODER_STREAM_ERROR";
- case NGHTTP3_ERR_H3_FRAME_UNEXPECTED:
- return "ERR_H3_FRAME_UNEXPECTED";
- case NGHTTP3_ERR_H3_FRAME_ERROR:
- return "ERR_H3_FRAME_ERROR";
- case NGHTTP3_ERR_H3_MISSING_SETTINGS:
- return "ERR_H3_MISSING_SETTINGS";
- case NGHTTP3_ERR_H3_INTERNAL_ERROR:
- return "ERR_H3_INTERNAL_ERROR";
- case NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM:
- return "ERR_CLOSED_CRITICAL_STREAM";
- case NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR:
- return "ERR_H3_GENERAL_PROTOCOL_ERROR";
- case NGHTTP3_ERR_H3_ID_ERROR:
- return "ERR_H3_ID_ERROR";
- case NGHTTP3_ERR_H3_SETTINGS_ERROR:
- return "ERR_H3_SETTINGS_ERROR";
- case NGHTTP3_ERR_H3_STREAM_CREATION_ERROR:
- return "ERR_H3_STREAM_CREATION_ERROR";
- case NGHTTP3_ERR_NOMEM:
- return "ERR_NOMEM";
- case NGHTTP3_ERR_CALLBACK_FAILURE:
- return "ERR_CALLBACK_FAILURE";
- default:
- return "(unknown)";
- }
-}
-
-uint64_t nghttp3_err_infer_quic_app_error_code(int liberr) {
- switch (liberr) {
- case 0:
- return NGHTTP3_H3_NO_ERROR;
- case NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED:
- return NGHTTP3_QPACK_DECOMPRESSION_FAILED;
- case NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR:
- return NGHTTP3_QPACK_ENCODER_STREAM_ERROR;
- case NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR:
- return NGHTTP3_QPACK_DECODER_STREAM_ERROR;
- case NGHTTP3_ERR_H3_FRAME_UNEXPECTED:
- return NGHTTP3_H3_FRAME_UNEXPECTED;
- case NGHTTP3_ERR_H3_FRAME_ERROR:
- return NGHTTP3_H3_FRAME_ERROR;
- case NGHTTP3_ERR_H3_MISSING_SETTINGS:
- return NGHTTP3_H3_MISSING_SETTINGS;
- case NGHTTP3_ERR_H3_INTERNAL_ERROR:
- return NGHTTP3_H3_INTERNAL_ERROR;
- case NGHTTP3_ERR_H3_CLOSED_CRITICAL_STREAM:
- return NGHTTP3_H3_CLOSED_CRITICAL_STREAM;
- case NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR:
- return NGHTTP3_H3_GENERAL_PROTOCOL_ERROR;
- case NGHTTP3_ERR_H3_ID_ERROR:
- return NGHTTP3_H3_ID_ERROR;
- case NGHTTP3_ERR_H3_SETTINGS_ERROR:
- return NGHTTP3_H3_SETTINGS_ERROR;
- case NGHTTP3_ERR_H3_STREAM_CREATION_ERROR:
- return NGHTTP3_H3_STREAM_CREATION_ERROR;
- default:
- return NGHTTP3_H3_GENERAL_PROTOCOL_ERROR;
- }
-}
diff --git a/deps/nghttp3/lib/nghttp3_err.h b/deps/nghttp3/lib/nghttp3_err.h
deleted file mode 100644
index 2fa914f86b..0000000000
--- a/deps/nghttp3/lib/nghttp3_err.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_ERR_H
-#define NGHTTP3_ERR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#endif /* NGHTTP3_ERR_H */
diff --git a/deps/nghttp3/lib/nghttp3_frame.c b/deps/nghttp3/lib/nghttp3_frame.c
deleted file mode 100644
index 479b794f9a..0000000000
--- a/deps/nghttp3/lib/nghttp3_frame.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_frame.h"
-
-#include <string.h>
-
-#include "nghttp3_conv.h"
-#include "nghttp3_str.h"
-
-uint8_t *nghttp3_frame_write_hd(uint8_t *p, const nghttp3_frame_hd *hd) {
- p = nghttp3_put_varint(p, hd->type);
- p = nghttp3_put_varint(p, hd->length);
- return p;
-}
-
-size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd) {
- return nghttp3_put_varint_len(hd->type) + nghttp3_put_varint_len(hd->length);
-}
-
-uint8_t *nghttp3_frame_write_settings(uint8_t *p,
- const nghttp3_frame_settings *fr) {
- size_t i;
-
- p = nghttp3_frame_write_hd(p, &fr->hd);
-
- for (i = 0; i < fr->niv; ++i) {
- p = nghttp3_put_varint(p, (int64_t)fr->iv[i].id);
- p = nghttp3_put_varint(p, (int64_t)fr->iv[i].value);
- }
-
- return p;
-}
-
-size_t nghttp3_frame_write_settings_len(int64_t *ppayloadlen,
- const nghttp3_frame_settings *fr) {
- size_t payloadlen = 0;
- size_t i;
-
- for (i = 0; i < fr->niv; ++i) {
- payloadlen += nghttp3_put_varint_len((int64_t)fr->iv[i].id) +
- nghttp3_put_varint_len((int64_t)fr->iv[i].value);
- }
-
- *ppayloadlen = (int64_t)payloadlen;
-
- return nghttp3_put_varint_len(NGHTTP3_FRAME_SETTINGS) +
- nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen;
-}
-
-uint8_t *nghttp3_frame_write_cancel_push(uint8_t *p,
- const nghttp3_frame_cancel_push *fr) {
- p = nghttp3_frame_write_hd(p, &fr->hd);
- p = nghttp3_put_varint(p, fr->push_id);
-
- return p;
-}
-
-size_t
-nghttp3_frame_write_cancel_push_len(int64_t *ppayloadlen,
- const nghttp3_frame_cancel_push *fr) {
- size_t payloadlen = nghttp3_put_varint_len(fr->push_id);
-
- *ppayloadlen = (int64_t)payloadlen;
-
- return nghttp3_put_varint_len(NGHTTP3_FRAME_CANCEL_PUSH) +
- nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen;
-}
-
-uint8_t *nghttp3_frame_write_max_push_id(uint8_t *p,
- const nghttp3_frame_max_push_id *fr) {
- p = nghttp3_frame_write_hd(p, &fr->hd);
- p = nghttp3_put_varint(p, fr->push_id);
-
- return p;
-}
-
-size_t
-nghttp3_frame_write_max_push_id_len(int64_t *ppayloadlen,
- const nghttp3_frame_max_push_id *fr) {
- size_t payloadlen = nghttp3_put_varint_len(fr->push_id);
-
- *ppayloadlen = (int64_t)payloadlen;
-
- return nghttp3_put_varint_len(NGHTTP3_FRAME_MAX_PUSH_ID) +
- nghttp3_put_varint_len((int64_t)payloadlen) + payloadlen;
-}
-
-int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_mem *mem) {
- size_t i;
- uint8_t *data = NULL;
- size_t buflen = 0;
- nghttp3_nv *p;
-
- if (nvlen == 0) {
- *pnva = NULL;
-
- return 0;
- }
-
- for (i = 0; i < nvlen; ++i) {
- /* + 1 for null-termination */
- if ((nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_NAME) == 0) {
- buflen += nva[i].namelen + 1;
- }
- if ((nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_VALUE) == 0) {
- buflen += nva[i].valuelen + 1;
- }
- }
-
- buflen += sizeof(nghttp3_nv) * nvlen;
-
- *pnva = nghttp3_mem_malloc(mem, buflen);
-
- if (*pnva == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- p = *pnva;
- data = (uint8_t *)(*pnva) + sizeof(nghttp3_nv) * nvlen;
-
- for (i = 0; i < nvlen; ++i) {
- p->flags = nva[i].flags;
-
- if (nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_NAME) {
- p->name = nva[i].name;
- p->namelen = nva[i].namelen;
- } else {
- if (nva[i].namelen) {
- memcpy(data, nva[i].name, nva[i].namelen);
- }
- p->name = data;
- p->namelen = nva[i].namelen;
- data[p->namelen] = '\0';
- nghttp3_downcase(p->name, p->namelen);
- data += nva[i].namelen + 1;
- }
-
- if (nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_VALUE) {
- p->value = nva[i].value;
- p->valuelen = nva[i].valuelen;
- } else {
- if (nva[i].valuelen) {
- memcpy(data, nva[i].value, nva[i].valuelen);
- }
- p->value = data;
- p->valuelen = nva[i].valuelen;
- data[p->valuelen] = '\0';
- data += nva[i].valuelen + 1;
- }
-
- ++p;
- }
- return 0;
-}
-
-void nghttp3_nva_del(nghttp3_nv *nva, const nghttp3_mem *mem) {
- nghttp3_mem_free(mem, nva);
-}
-
-void nghttp3_frame_headers_free(nghttp3_frame_headers *fr,
- const nghttp3_mem *mem) {
- if (fr == NULL) {
- return;
- }
-
- nghttp3_nva_del(fr->nva, mem);
-}
-
-void nghttp3_frame_push_promise_free(nghttp3_frame_push_promise *fr,
- const nghttp3_mem *mem) {
- if (fr == NULL) {
- return;
- }
-
- nghttp3_nva_del(fr->nva, mem);
-}
diff --git a/deps/nghttp3/lib/nghttp3_frame.h b/deps/nghttp3/lib/nghttp3_frame.h
deleted file mode 100644
index be333e9509..0000000000
--- a/deps/nghttp3/lib/nghttp3_frame.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_FRAME_H
-#define NGHTTP3_FRAME_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_buf.h"
-
-typedef enum {
- NGHTTP3_FRAME_DATA = 0x00,
- NGHTTP3_FRAME_HEADERS = 0x01,
- NGHTTP3_FRAME_CANCEL_PUSH = 0x03,
- NGHTTP3_FRAME_SETTINGS = 0x04,
- NGHTTP3_FRAME_PUSH_PROMISE = 0x05,
- NGHTTP3_FRAME_GOAWAY = 0x07,
- NGHTTP3_FRAME_MAX_PUSH_ID = 0x0d,
-} nghttp3_frame_type;
-
-typedef struct {
- int64_t type;
- int64_t length;
-} nghttp3_frame_hd;
-
-typedef struct {
- nghttp3_frame_hd hd;
-} nghttp3_frame_data;
-
-typedef struct {
- nghttp3_frame_hd hd;
- nghttp3_nv *nva;
- size_t nvlen;
-} nghttp3_frame_headers;
-
-typedef struct {
- nghttp3_frame_hd hd;
- int64_t push_id;
-} nghttp3_frame_cancel_push;
-
-#define NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE 0x06
-#define NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY 0x01
-#define NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS 0x07
-
-typedef struct {
- uint64_t id;
- uint64_t value;
-} nghttp3_settings_entry;
-
-typedef struct {
- nghttp3_frame_hd hd;
- size_t niv;
- nghttp3_settings_entry iv[1];
-} nghttp3_frame_settings;
-
-typedef struct {
- nghttp3_frame_hd hd;
- nghttp3_nv *nva;
- size_t nvlen;
- int64_t push_id;
-} nghttp3_frame_push_promise;
-
-typedef struct {
- nghttp3_frame_hd hd;
- int64_t stream_id;
-} nghttp3_frame_goaway;
-
-typedef struct {
- nghttp3_frame_hd hd;
- int64_t push_id;
-} nghttp3_frame_max_push_id;
-
-typedef union {
- nghttp3_frame_hd hd;
- nghttp3_frame_data data;
- nghttp3_frame_headers headers;
- nghttp3_frame_cancel_push cancel_push;
- nghttp3_frame_settings settings;
- nghttp3_frame_push_promise push_promise;
- nghttp3_frame_goaway goaway;
- nghttp3_frame_max_push_id max_push_id;
-} nghttp3_frame;
-
-/*
- * nghttp3_frame_write_hd writes frame header |hd| to |dest|. This
- * function assumes that |dest| has enough space to write |hd|.
- *
- * This function returns |dest| plus the number of bytes written.
- */
-uint8_t *nghttp3_frame_write_hd(uint8_t *dest, const nghttp3_frame_hd *hd);
-
-/*
- * nghttp3_frame_write_hd_len returns the number of bytes required to
- * write |hd|. hd->length must be set.
- */
-size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd);
-
-/*
- * nghttp3_frame_write_settings writes SETTINGS frame |fr| to |dest|.
- * This function assumes that |dest| has enough space to write |fr|.
- *
- * This function returns |dest| plus the number of bytes written.
- */
-uint8_t *nghttp3_frame_write_settings(uint8_t *dest,
- const nghttp3_frame_settings *fr);
-
-/*
- * nghttp3_frame_write_settings_len returns the number of bytes
- * required to write |fr|. fr->hd.length is ignored. This function
- * stores payload length in |*ppayloadlen|.
- */
-size_t nghttp3_frame_write_settings_len(int64_t *pppayloadlen,
- const nghttp3_frame_settings *fr);
-
-/*
- * nghttp3_frame_write_cancel_push writes CANCEL_PUSH frame |fr| to
- * |dest|. This function assumes that |dest| has enough space to
- * write |fr|.
- *
- * This function returns |dest| plus the number of bytes written.
- */
-uint8_t *nghttp3_frame_write_cancel_push(uint8_t *dest,
- const nghttp3_frame_cancel_push *fr);
-
-/*
- * nghttp3_frame_write_cancel_push_len returns the number of bytes
- * required to write |fr|. fr->hd.length is ignored. This function
- * stores payload length in |*ppayloadlen|.
- */
-size_t nghttp3_frame_write_cancel_push_len(int64_t *ppayloadlen,
- const nghttp3_frame_cancel_push *fr);
-
-/*
- * nghttp3_frame_write_max_push_id writes MAX_PUSH_ID frame |fr| to
- * |dest|. This function assumes that |dest| has enough space to
- * write |fr|.
- *
- * This function returns |dest| plus the number of bytes written.
- */
-uint8_t *nghttp3_frame_write_max_push_id(uint8_t *dest,
- const nghttp3_frame_max_push_id *fr);
-
-/*
- * nghttp3_frame_write_max_push_id_len returns the number of bytes
- * required to write |fr|. fr->hd.length is ignored. This function
- * stores payload length in |*ppayloadlen|.
- */
-size_t nghttp3_frame_write_max_push_id_len(int64_t *ppayloadlen,
- const nghttp3_frame_max_push_id *fr);
-
-/*
- * nghttp3_nva_copy copies name/value pairs from |nva|, which contains
- * |nvlen| pairs, to |*nva_ptr|, which is dynamically allocated so
- * that all items can be stored. The resultant name and value in
- * nghttp2_nv are guaranteed to be NULL-terminated even if the input
- * is not null-terminated.
- *
- * The |*pnva| must be freed using nghttp3_nva_del().
- *
- * This function returns 0 if it succeeds or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_nva_del frees |nva|.
- */
-void nghttp3_nva_del(nghttp3_nv *nva, const nghttp3_mem *mem);
-
-/*
- * nghttp3_frame_headers_free frees memory allocated for |fr|. It
- * assumes that fr->nva is created by nghttp3_nva_copy() or NULL.
- */
-void nghttp3_frame_headers_free(nghttp3_frame_headers *fr,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_frame_push_promise_free frees memory allocated for |fr|.
- * It assumes that fr->nva is created by nghttp3_nva_copy() or NULL.
- */
-void nghttp3_frame_push_promise_free(nghttp3_frame_push_promise *fr,
- const nghttp3_mem *mem);
-
-#endif /* NGHTTP3_FRAME_H */
diff --git a/deps/nghttp3/lib/nghttp3_gaptr.c b/deps/nghttp3/lib/nghttp3_gaptr.c
deleted file mode 100644
index 1faabbf09f..0000000000
--- a/deps/nghttp3/lib/nghttp3_gaptr.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_gaptr.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "nghttp3_macro.h"
-
-int nghttp3_gaptr_init(nghttp3_gaptr *gaptr, const nghttp3_mem *mem) {
- int rv;
- nghttp3_range range = {0, UINT64_MAX};
-
- rv = nghttp3_ksl_init(&gaptr->gap, nghttp3_ksl_range_compar,
- sizeof(nghttp3_range), mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_ksl_insert(&gaptr->gap, NULL, &range, NULL);
- if (rv != 0) {
- nghttp3_ksl_free(&gaptr->gap);
- return rv;
- }
-
- gaptr->mem = mem;
-
- return 0;
-}
-
-void nghttp3_gaptr_free(nghttp3_gaptr *gaptr) {
- if (gaptr == NULL) {
- return;
- }
-
- nghttp3_ksl_free(&gaptr->gap);
-}
-
-int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset, size_t datalen) {
- int rv;
- nghttp3_range k, m, l, r, q = {offset, offset + datalen};
- nghttp3_ksl_it it;
-
- it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
- nghttp3_ksl_range_exclusive_compar);
-
- for (; !nghttp3_ksl_it_end(&it);) {
- k = *(nghttp3_range *)nghttp3_ksl_it_key(&it);
- m = nghttp3_range_intersect(&q, &k);
- if (!nghttp3_range_len(&m)) {
- break;
- }
-
- if (nghttp3_range_eq(&k, &m)) {
- nghttp3_ksl_remove(&gaptr->gap, &it, &k);
- continue;
- }
- nghttp3_range_cut(&l, &r, &k, &m);
- if (nghttp3_range_len(&l)) {
- nghttp3_ksl_update_key(&gaptr->gap, &k, &l);
-
- if (nghttp3_range_len(&r)) {
- rv = nghttp3_ksl_insert(&gaptr->gap, &it, &r, NULL);
- if (rv != 0) {
- return rv;
- }
- }
- } else if (nghttp3_range_len(&r)) {
- nghttp3_ksl_update_key(&gaptr->gap, &k, &r);
- }
- nghttp3_ksl_it_next(&it);
- }
- return 0;
-}
-
-uint64_t nghttp3_gaptr_first_gap_offset(nghttp3_gaptr *gaptr) {
- nghttp3_ksl_it it = nghttp3_ksl_begin(&gaptr->gap);
- return ((nghttp3_range *)nghttp3_ksl_it_key(&it))->begin;
-}
-
-nghttp3_ksl_it nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
- uint64_t offset) {
- nghttp3_range q = {offset, offset + 1};
- return nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
- nghttp3_ksl_range_exclusive_compar);
-}
-
-int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
- size_t datalen) {
- nghttp3_range q = {offset, offset + datalen};
- nghttp3_ksl_it it = nghttp3_ksl_lower_bound_compar(
- &gaptr->gap, &q, nghttp3_ksl_range_exclusive_compar);
- nghttp3_range m =
- nghttp3_range_intersect(&q, (nghttp3_range *)nghttp3_ksl_it_key(&it));
- return nghttp3_range_len(&m) == 0;
-}
diff --git a/deps/nghttp3/lib/nghttp3_gaptr.h b/deps/nghttp3/lib/nghttp3_gaptr.h
deleted file mode 100644
index 6972b40443..0000000000
--- a/deps/nghttp3/lib/nghttp3_gaptr.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_GAPTR_H
-#define NGHTTP3_GAPTR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-#include "nghttp3_range.h"
-#include "nghttp3_ksl.h"
-
-/*
- * nghttp3_gaptr maintains the gap in the range [0, UINT64_MAX).
- */
-typedef struct {
- /* gap maintains the range of offset which is not received
- yet. Initially, its range is [0, UINT64_MAX). */
- nghttp3_ksl gap;
- /* mem is custom memory allocator */
- const nghttp3_mem *mem;
-} nghttp3_gaptr;
-
-/*
- * nghttp3_gaptr_init initializes |gaptr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_gaptr_init(nghttp3_gaptr *gaptr, const nghttp3_mem *mem);
-
-/*
- * nghttp3_gaptr_free frees resources allocated for |gaptr|.
- */
-void nghttp3_gaptr_free(nghttp3_gaptr *gaptr);
-
-/*
- * nghttp3_gaptr_push adds new data of length |datalen| at the stream
- * offset |offset|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory
- */
-int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset, size_t datalen);
-
-/*
- * nghttp3_gaptr_first_gap_offset returns the offset to the first gap.
- * If there is no gap, it returns UINT64_MAX.
- */
-uint64_t nghttp3_gaptr_first_gap_offset(nghttp3_gaptr *gaptr);
-
-/*
- * nghttp3_gaptr_get_first_gap_after returns the iterator pointing to
- * the first gap which overlaps or comes after |offset|.
- */
-nghttp3_ksl_it nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
- uint64_t offset);
-
-/*
- * nghttp3_gaptr_is_pushed returns nonzero if range [offset, offset +
- * datalen) is completely pushed into this object.
- */
-int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
- size_t datalen);
-
-#endif /* NGHTTP3_GAPTR_H */
diff --git a/deps/nghttp3/lib/nghttp3_http.c b/deps/nghttp3/lib/nghttp3_http.c
deleted file mode 100644
index dc84c16b5d..0000000000
--- a/deps/nghttp3/lib/nghttp3_http.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2015 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_http.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "nghttp3_stream.h"
-#include "nghttp3_macro.h"
-#include "nghttp3_conv.h"
-
-static uint8_t downcase(uint8_t c) {
- return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c;
-}
-
-static int memieq(const void *a, const void *b, size_t n) {
- size_t i;
- const uint8_t *aa = a, *bb = b;
-
- for (i = 0; i < n; ++i) {
- if (downcase(aa[i]) != downcase(bb[i])) {
- return 0;
- }
- }
- return 1;
-}
-
-#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
-
-static int64_t parse_uint(const uint8_t *s, size_t len) {
- int64_t n = 0;
- size_t i;
- if (len == 0) {
- return -1;
- }
- for (i = 0; i < len; ++i) {
- if ('0' <= s[i] && s[i] <= '9') {
- if (n > INT64_MAX / 10) {
- return -1;
- }
- n *= 10;
- if (n > INT64_MAX - (s[i] - '0')) {
- return -1;
- }
- n += s[i] - '0';
- continue;
- }
- return -1;
- }
- return n;
-}
-
-static int lws(const uint8_t *s, size_t n) {
- size_t i;
- for (i = 0; i < n; ++i) {
- if (s[i] != ' ' && s[i] != '\t') {
- return 0;
- }
- }
- return 1;
-}
-
-static int check_pseudo_header(nghttp3_http_state *http,
- const nghttp3_qpack_nv *nv, int flag) {
- if (http->flags & flag) {
- return 0;
- }
- if (lws(nv->value->base, nv->value->len)) {
- return 0;
- }
- http->flags = (uint16_t)(http->flags | flag);
- return 1;
-}
-
-static int expect_response_body(nghttp3_http_state *http) {
- return (http->flags & NGHTTP3_HTTP_FLAG_METH_HEAD) == 0 &&
- http->status_code / 100 != 1 && http->status_code != 304 &&
- http->status_code != 204;
-}
-
-/* For "http" or "https" URIs, OPTIONS request may have "*" in :path
- header field to represent system-wide OPTIONS request. Otherwise,
- :path header field value must start with "/". This function must
- be called after ":method" header field was received. This function
- returns nonzero if path is valid.*/
-static int check_path(nghttp3_http_state *http) {
- return (http->flags & NGHTTP3_HTTP_FLAG_SCHEME_HTTP) == 0 ||
- ((http->flags & NGHTTP3_HTTP_FLAG_PATH_REGULAR) ||
- ((http->flags & NGHTTP3_HTTP_FLAG_METH_OPTIONS) &&
- (http->flags & NGHTTP3_HTTP_FLAG_PATH_ASTERISK)));
-}
-
-int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
- size_t len) {
- nghttp3_pri pri = *dest;
- const uint8_t *p = value, *end = value + len;
-
- for (;;) {
- for (; p != end && (*p == ' ' || *p == '\t'); ++p)
- ;
-
- if (p == end) {
- break;
- }
-
- switch (*p) {
- case 'u':
- ++p;
-
- if (p + 2 > end || *p++ != '=') {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (!('0' <= *p && *p <= '7')) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- pri.urgency = (uint32_t)(*p++ - '0');
-
- if (p == end) {
- goto fin;
- }
-
- if (*p++ != ',') {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- break;
- case 'i':
- ++p;
-
- if (p == end) {
- pri.inc = 1;
- goto fin;
- }
-
- if (*p == ',') {
- pri.inc = 1;
- ++p;
- break;
- }
-
- if (p + 3 > end || *p != '=' || *(p + 1) != '?' ||
- (*(p + 2) != '0' && *(p + 2) != '1')) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- pri.inc = *(p + 2) == '1';
-
- p += 3;
-
- if (p == end) {
- goto fin;
- }
-
- if (*p++ != ',') {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- break;
- default:
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (p == end) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
- }
-
-fin:
-
- *dest = pri;
-
- return 0;
-}
-
-static int http_request_on_header(nghttp3_http_state *http, int64_t frame_type,
- nghttp3_qpack_nv *nv, int trailers,
- int connect_protocol) {
- nghttp3_pri pri;
-
- if (nv->name->base[0] == ':') {
- if (trailers ||
- (http->flags & NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
-
- switch (nv->token) {
- case NGHTTP3_QPACK_TOKEN__AUTHORITY:
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__AUTHORITY)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- case NGHTTP3_QPACK_TOKEN__METHOD:
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__METHOD)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- switch (nv->value->len) {
- case 4:
- if (lstreq("HEAD", nv->value->base, nv->value->len)) {
- http->flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
- }
- break;
- case 7:
- switch (nv->value->base[6]) {
- case 'T':
- if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
- if (frame_type == NGHTTP3_FRAME_PUSH_PROMISE) {
- /* we won't allow CONNECT for push */
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
- }
- break;
- case 'S':
- if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
- http->flags |= NGHTTP3_HTTP_FLAG_METH_OPTIONS;
- }
- break;
- }
- break;
- }
- break;
- case NGHTTP3_QPACK_TOKEN__PATH:
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PATH)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if (nv->value->base[0] == '/') {
- http->flags |= NGHTTP3_HTTP_FLAG_PATH_REGULAR;
- } else if (nv->value->len == 1 && nv->value->base[0] == '*') {
- http->flags |= NGHTTP3_HTTP_FLAG_PATH_ASTERISK;
- }
- break;
- case NGHTTP3_QPACK_TOKEN__SCHEME:
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__SCHEME)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) ||
- (nv->value->len == 5 && memieq("https", nv->value->base, 5))) {
- http->flags |= NGHTTP3_HTTP_FLAG_SCHEME_HTTP;
- }
- break;
- case NGHTTP3_QPACK_TOKEN__PROTOCOL:
- if (!connect_protocol) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
-
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PROTOCOL)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- case NGHTTP3_QPACK_TOKEN_HOST:
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG_HOST)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH: {
- /* https://tools.ietf.org/html/rfc7230#section-4.1.2: A sender
- MUST NOT generate a trailer that contains a field necessary for
- message framing (e.g., Transfer-Encoding and Content-Length),
- ... */
- if (trailers) {
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
- if (http->content_length != -1) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->content_length = parse_uint(nv->value->base, nv->value->len);
- if (http->content_length == -1) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- }
- /* disallowed header fields */
- case NGHTTP3_QPACK_TOKEN_CONNECTION:
- case NGHTTP3_QPACK_TOKEN_KEEP_ALIVE:
- case NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION:
- case NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING:
- case NGHTTP3_QPACK_TOKEN_UPGRADE:
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- case NGHTTP3_QPACK_TOKEN_TE:
- if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- case NGHTTP3_QPACK_TOKEN_PRIORITY:
- pri.urgency = nghttp3_pri_uint8_urgency(http->pri);
- pri.inc = nghttp3_pri_uint8_inc(http->pri);
- if (nghttp3_http_parse_priority(&pri, nv->value->base, nv->value->len) ==
- 0) {
- http->pri = nghttp3_pri_to_uint8(&pri);
- }
- break;
- default:
- if (nv->name->base[0] == ':') {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
-
- if (nv->name->base[0] != ':') {
- http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
- }
-
- return 0;
-}
-
-static int http_response_on_header(nghttp3_http_state *http,
- nghttp3_qpack_nv *nv, int trailers) {
- if (nv->name->base[0] == ':') {
- if (trailers ||
- (http->flags & NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
-
- switch (nv->token) {
- case NGHTTP3_QPACK_TOKEN__STATUS: {
- if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__STATUS)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if (nv->value->len != 3) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
- if (http->status_code < 100 || http->status_code == 101) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- }
- case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH: {
- /* https://tools.ietf.org/html/rfc7230#section-4.1.2: A sender
- MUST NOT generate a trailer that contains a field necessary for
- message framing (e.g., Transfer-Encoding and Content-Length),
- ... */
- if (trailers) {
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
- if (http->status_code == 204) {
- /* content-length header field in 204 response is prohibited by
- RFC 7230. But some widely used servers send content-length:
- 0. Until they get fixed, we ignore it. */
- if (http->content_length != -1) {
- /* Found multiple content-length field */
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if (!lstrieq("0", nv->value->base, nv->value->len)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->content_length = 0;
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
- if (http->status_code / 100 == 1) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- /* https://tools.ietf.org/html/rfc7230#section-3.3.3 */
- if (http->status_code / 100 == 2 &&
- (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT)) {
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
- if (http->content_length != -1) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->content_length = parse_uint(nv->value->base, nv->value->len);
- if (http->content_length == -1) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- }
- /* disallowed header fields */
- case NGHTTP3_QPACK_TOKEN_CONNECTION:
- case NGHTTP3_QPACK_TOKEN_KEEP_ALIVE:
- case NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION:
- case NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING:
- case NGHTTP3_QPACK_TOKEN_UPGRADE:
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- case NGHTTP3_QPACK_TOKEN_TE:
- if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- break;
- default:
- if (nv->name->base[0] == ':') {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
-
- if (nv->name->base[0] != ':') {
- http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
- }
-
- return 0;
-}
-
-/* Generated by genauthroitychartbl.py */
-static char VALID_AUTHORITY_CHARS[] = {
- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
- 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
- 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
- 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
- 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
- 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
- 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
- 0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
- 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
- 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
- 1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
- 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
- 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
- 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
- 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
- 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
- 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
- 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
- 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
- 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
- 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
- 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
- 0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
- 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
- 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
- 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
- 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
- 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
- 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
- 0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
- 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
- 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
- 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
- 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
- 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
- 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
- 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
- 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
- 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
- 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
- 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
- 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
- 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
- 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
- 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
- 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
- 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
- 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
- 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
- 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
- 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
- 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
- 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
- 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
- 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
- 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
-};
-
-static int check_authority(const uint8_t *value, size_t len) {
- const uint8_t *last;
- for (last = value + len; value != last; ++value) {
- if (!VALID_AUTHORITY_CHARS[*value]) {
- return 0;
- }
- }
- return 1;
-}
-
-static int check_scheme(const uint8_t *value, size_t len) {
- const uint8_t *last;
- if (len == 0) {
- return 0;
- }
-
- if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) {
- return 0;
- }
-
- last = value + len;
- ++value;
-
- for (; value != last; ++value) {
- if (!(('A' <= *value && *value <= 'Z') ||
- ('a' <= *value && *value <= 'z') ||
- ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' ||
- *value == '.')) {
- return 0;
- }
- }
- return 1;
-}
-
-int nghttp3_http_on_header(nghttp3_http_state *http, int64_t frame_type,
- nghttp3_qpack_nv *nv, int request, int trailers) {
- int rv;
- size_t i;
- uint8_t c;
-
- if (!nghttp3_check_header_name(nv->name->base, nv->name->len)) {
- if (nv->name->len > 0 && nv->name->base[0] == ':') {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- /* header field name must be lower-cased without exception */
- for (i = 0; i < nv->name->len; ++i) {
- c = nv->name->base[i];
- if ('A' <= c && c <= 'Z') {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
- /* When ignoring regular header fields, we set this flag so that
- we still enforce header field ordering rule for pseudo header
- fields. */
- http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
-
- if (nv->token == NGHTTP3_QPACK_TOKEN__AUTHORITY ||
- nv->token == NGHTTP3_QPACK_TOKEN_HOST) {
- rv = check_authority(nv->value->base, nv->value->len);
- } else if (nv->token == NGHTTP3_QPACK_TOKEN__SCHEME) {
- rv = check_scheme(nv->value->base, nv->value->len);
- } else {
- rv = nghttp3_check_header_value(nv->value->base, nv->value->len);
- }
-
- if (rv == 0) {
- assert(nv->name->len > 0);
- if (nv->name->base[0] == ':') {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- /* When ignoring regular header fields, we set this flag so that
- we still enforce header field ordering rule for pseudo header
- fields. */
- http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
- return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
- }
-
- if (request) {
- return http_request_on_header(http, frame_type, nv, trailers,
- /* connect_protocol = */ 0);
- }
-
- return http_response_on_header(http, nv, trailers);
-}
-
-int nghttp3_http_on_request_headers(nghttp3_http_state *http) {
- if (!(http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
- (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT)) {
- if ((http->flags & (NGHTTP3_HTTP_FLAG__SCHEME | NGHTTP3_HTTP_FLAG__PATH)) ||
- (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- http->content_length = -1;
- } else {
- if ((http->flags & NGHTTP3_HTTP_FLAG_REQ_HEADERS) !=
- NGHTTP3_HTTP_FLAG_REQ_HEADERS ||
- (http->flags &
- (NGHTTP3_HTTP_FLAG__AUTHORITY | NGHTTP3_HTTP_FLAG_HOST)) == 0) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if ((http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
- ((http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) == 0 ||
- (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- if (!check_path(http)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
- }
-
- return 0;
-}
-
-int nghttp3_http_on_response_headers(nghttp3_http_state *http) {
- if ((http->flags & NGHTTP3_HTTP_FLAG__STATUS) == 0) {
- return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
- }
-
- if (http->status_code / 100 == 1) {
- /* non-final response */
- http->flags = (uint16_t)((http->flags & NGHTTP3_HTTP_FLAG_METH_ALL) |
- NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
- http->content_length = -1;
- http->status_code = -1;
- return 0;
- }
-
- http->flags =
- (uint16_t)(http->flags & ~NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
-
- if (!expect_response_body(http)) {
- http->content_length = 0;
- } else if (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
- http->content_length = -1;
- }
-
- return 0;
-}
-
-int nghttp3_http_on_remote_end_stream(nghttp3_stream *stream) {
- if (stream->flags & NGHTTP3_STREAM_FLAG_RESET) {
- return 0;
- }
- if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
- (stream->rx.http.content_length != -1 &&
- stream->rx.http.content_length != stream->rx.http.recv_content_length)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
- }
-
- return 0;
-}
-
-int nghttp3_http_on_data_chunk(nghttp3_stream *stream, size_t n) {
- stream->rx.http.recv_content_length += (int64_t)n;
-
- if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
- (stream->rx.http.content_length != -1 &&
- stream->rx.http.recv_content_length > stream->rx.http.content_length)) {
- return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
- }
-
- return 0;
-}
-
-void nghttp3_http_record_request_method(nghttp3_stream *stream,
- const nghttp3_nv *nva, size_t nvlen) {
- size_t i;
- const nghttp3_nv *nv;
-
- /* TODO we should do this strictly. */
- for (i = 0; i < nvlen; ++i) {
- nv = &nva[i];
- if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
- memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
- continue;
- }
- if (lstreq("CONNECT", nv->value, nv->valuelen)) {
- stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
- return;
- }
- if (lstreq("HEAD", nv->value, nv->valuelen)) {
- stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
- return;
- }
- return;
- }
-}
-
-/* Generated by gennmchartbl.py */
-static const int VALID_HD_NAME_CHARS[] = {
- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
- 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
- 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
- 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
- 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
- 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
- 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
- 0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
- 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
- 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
- 0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
- 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
- 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
- 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
- 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
- 0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
- 0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
- 0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
- 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
- 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
- 0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
- 0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
- 0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
- 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
- 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
- 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
- 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
- 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
- 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
- 1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
- 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
- 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
- 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
- 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
- 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
- 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
- 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
- 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
- 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
- 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
- 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
- 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
- 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
- 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
- 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
- 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
- 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
- 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
- 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
- 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
- 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
- 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
- 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
- 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
- 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
- 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
-};
-
-int nghttp3_check_header_name(const uint8_t *name, size_t len) {
- const uint8_t *last;
- if (len == 0) {
- return 0;
- }
- if (*name == ':') {
- if (len == 1) {
- return 0;
- }
- ++name;
- --len;
- }
- for (last = name + len; name != last; ++name) {
- if (!VALID_HD_NAME_CHARS[*name]) {
- return 0;
- }
- }
- return 1;
-}
-
-/* Generated by genvchartbl.py */
-static const int VALID_HD_VALUE_CHARS[] = {
- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
- 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
- 0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
- 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
- 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
- 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
- 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
- 1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
- 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
- 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
- 1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
- 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
- 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
- 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
- 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
- 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
- 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
- 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
- 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
- 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
- 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
- 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
- 1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
- 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
- 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
- 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
- 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
- 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
- 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
- 1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
- 1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
- 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
- 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
- 1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
- 1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
- 1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
- 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
- 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
- 1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
- 1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
- 1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
- 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
- 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
- 1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
- 1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
- 1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
- 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
- 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
- 1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
- 1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
- 1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
- 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
- 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
- 1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
- 1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
- 1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
- 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
- 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
- 1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
- 1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
- 1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
- 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
-};
-
-int nghttp3_check_header_value(const uint8_t *value, size_t len) {
- const uint8_t *last;
- for (last = value + len; value != last; ++value) {
- if (!VALID_HD_VALUE_CHARS[*value]) {
- return 0;
- }
- }
- return 1;
-}
diff --git a/deps/nghttp3/lib/nghttp3_http.h b/deps/nghttp3/lib/nghttp3_http.h
deleted file mode 100644
index 00b74f2a26..0000000000
--- a/deps/nghttp3/lib/nghttp3_http.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2015 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_HTTP_H
-#define NGHTTP3_HTTP_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-struct nghttp3_stream;
-typedef struct nghttp3_stream nghttp3_stream;
-
-struct nghttp3_http_state;
-typedef struct nghttp3_http_state nghttp3_http_state;
-
-/* HTTP related flags to enforce HTTP semantics */
-typedef enum {
- NGHTTP3_HTTP_FLAG_NONE = 0,
- /* header field seen so far */
- NGHTTP3_HTTP_FLAG__AUTHORITY = 1,
- NGHTTP3_HTTP_FLAG__PATH = 1 << 1,
- NGHTTP3_HTTP_FLAG__METHOD = 1 << 2,
- NGHTTP3_HTTP_FLAG__SCHEME = 1 << 3,
- /* host is not pseudo header, but we require either host or
- :authority */
- NGHTTP3_HTTP_FLAG_HOST = 1 << 4,
- NGHTTP3_HTTP_FLAG__STATUS = 1 << 5,
- /* required header fields for HTTP request except for CONNECT
- method. */
- NGHTTP3_HTTP_FLAG_REQ_HEADERS = NGHTTP3_HTTP_FLAG__METHOD |
- NGHTTP3_HTTP_FLAG__PATH |
- NGHTTP3_HTTP_FLAG__SCHEME,
- NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6,
- /* HTTP method flags */
- NGHTTP3_HTTP_FLAG_METH_CONNECT = 1 << 7,
- NGHTTP3_HTTP_FLAG_METH_HEAD = 1 << 8,
- NGHTTP3_HTTP_FLAG_METH_OPTIONS = 1 << 9,
- NGHTTP3_HTTP_FLAG_METH_ALL = NGHTTP3_HTTP_FLAG_METH_CONNECT |
- NGHTTP3_HTTP_FLAG_METH_HEAD |
- NGHTTP3_HTTP_FLAG_METH_OPTIONS,
- /* :path category */
- /* path starts with "/" */
- NGHTTP3_HTTP_FLAG_PATH_REGULAR = 1 << 11,
- /* path "*" */
- NGHTTP3_HTTP_FLAG_PATH_ASTERISK = 1 << 12,
- /* scheme */
- /* "http" or "https" scheme */
- NGHTTP3_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
- /* set if final response is expected */
- NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,
- NGHTTP3_HTTP_FLAG__PROTOCOL = 1 << 15,
-} nghttp3_http_flag;
-
-/*
- * This function is called when HTTP header field |nv| in a frame of type
- * |frame_type| is received for |http|. This function will validate |nv|
- * against the current state of stream. Pass nonzero if this is request
- * headers. Pass nonzero to |trailers| if |nv| is included in trailers.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_MALFORMED_HTTP_HEADER
- * Invalid HTTP header field was received.
- * NGHTTP3_ERR_REMOVE_HTTP_HEADER
- * Invalid HTTP header field was received but it can be treated as
- * if it was not received because of compatibility reasons.
- */
-int nghttp3_http_on_header(nghttp3_http_state *http, int64_t frame_type,
- nghttp3_qpack_nv *nv, int request, int trailers);
-
-/*
- * This function is called when request header is received. This
- * function performs validation and returns 0 if it succeeds, or one
- * of the following negative error codes:
- *
- * NGHTTP3_ERR_MALFORMED_HTTP_HEADER
- * Required HTTP header field was not received; or an invalid
- * header field was received.
- */
-int nghttp3_http_on_request_headers(nghttp3_http_state *http);
-
-/*
- * This function is called when response header is received. This
- * function performs validation and returns 0 if it succeeds, or one
- * of the following negative error codes:
- *
- * NGHTTP3_ERR_MALFORMED_HTTP_HEADER
- * Required HTTP header field was not received; or an invalid
- * header field was received.
- */
-int nghttp3_http_on_response_headers(nghttp3_http_state *http);
-
-/*
- * This function is called when read side stream is closed. This
- * function performs validation and returns 0 if it succeeds, or one
- * of the following negative error codes:
- *
- * NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING
- * HTTP messaging is violated.
- */
-int nghttp3_http_on_remote_end_stream(nghttp3_stream *stream);
-
-/*
- * This function is called when chunk of data is received. This
- * function performs validation and returns 0 if it succeeds, or one
- * of the following negative error codes:
- *
- * NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING
- * HTTP messaging is violated.
- */
-int nghttp3_http_on_data_chunk(nghttp3_stream *stream, size_t n);
-
-/*
- * This function inspects header fields in |nva| of length |nvlen| and
- * records its method in stream->http_flags.
- */
-void nghttp3_http_record_request_method(nghttp3_stream *stream,
- const nghttp3_nv *nva, size_t nvlen);
-
-#endif /* NGHTTP3_HTTP_H */
diff --git a/deps/nghttp3/lib/nghttp3_idtr.c b/deps/nghttp3/lib/nghttp3_idtr.c
deleted file mode 100644
index cd8fd82e6b..0000000000
--- a/deps/nghttp3/lib/nghttp3_idtr.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_idtr.h"
-
-#include <assert.h>
-
-int nghttp3_idtr_init(nghttp3_idtr *idtr, int server, const nghttp3_mem *mem) {
- int rv;
-
- rv = nghttp3_gaptr_init(&idtr->gap, mem);
- if (rv != 0) {
- return rv;
- }
-
- idtr->server = server;
- idtr->mem = mem;
-
- return 0;
-}
-
-void nghttp3_idtr_free(nghttp3_idtr *idtr) {
- if (idtr == NULL) {
- return;
- }
-
- nghttp3_gaptr_free(&idtr->gap);
-}
-
-/*
- * id_from_stream_id translates |stream_id| to id space used by
- * nghttp3_idtr.
- */
-static uint64_t id_from_stream_id(int64_t stream_id) {
- return (uint64_t)(stream_id >> 2);
-}
-
-int nghttp3_idtr_open(nghttp3_idtr *idtr, int64_t stream_id) {
- uint64_t q;
-
- assert((idtr->server && (stream_id % 2)) ||
- (!idtr->server && (stream_id % 2)) == 0);
-
- q = id_from_stream_id(stream_id);
-
- if (nghttp3_gaptr_is_pushed(&idtr->gap, q, 1)) {
- return NGHTTP3_ERR_STREAM_IN_USE;
- }
-
- return nghttp3_gaptr_push(&idtr->gap, q, 1);
-}
-
-int nghttp3_idtr_is_open(nghttp3_idtr *idtr, int64_t stream_id) {
- uint64_t q;
-
- assert((idtr->server && (stream_id % 2)) ||
- (!idtr->server && (stream_id % 2)) == 0);
-
- q = id_from_stream_id(stream_id);
-
- return nghttp3_gaptr_is_pushed(&idtr->gap, q, 1);
-}
-
-uint64_t nghttp3_idtr_first_gap(nghttp3_idtr *idtr) {
- return nghttp3_gaptr_first_gap_offset(&idtr->gap);
-}
diff --git a/deps/nghttp3/lib/nghttp3_idtr.h b/deps/nghttp3/lib/nghttp3_idtr.h
deleted file mode 100644
index ba2808a11f..0000000000
--- a/deps/nghttp3/lib/nghttp3_idtr.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_IDTR_H
-#define NGHTTP3_IDTR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-#include "nghttp3_gaptr.h"
-
-/*
- * nghttp3_idtr tracks the usage of stream ID.
- */
-typedef struct {
- /* gap maintains the range of ID which is not used yet. Initially,
- its range is [0, UINT64_MAX). */
- nghttp3_gaptr gap;
- /* server is nonzero if this object records server initiated stream
- ID. */
- int server;
- /* mem is custom memory allocator */
- const nghttp3_mem *mem;
-} nghttp3_idtr;
-
-/*
- * nghttp3_idtr_init initializes |idtr|. |chunk| is the size of buffer
- * per chunk.
- *
- * If this object records server initiated ID (even number), set
- * |server| to nonzero.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_idtr_init(nghttp3_idtr *idtr, int server, const nghttp3_mem *mem);
-
-/*
- * nghttp3_idtr_free frees resources allocated for |idtr|.
- */
-void nghttp3_idtr_free(nghttp3_idtr *idtr);
-
-/*
- * nghttp3_idtr_open claims that |stream_id| is in used.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGHTTP3_ERR_STREAM_IN_USE
- * ID has already been used.
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_idtr_open(nghttp3_idtr *idtr, int64_t stream_id);
-
-/*
- * nghttp3_idtr_open tells whether ID |stream_id| is in used or not.
- *
- * It returns nonzero if |stream_id| is used.
- */
-int nghttp3_idtr_is_open(nghttp3_idtr *idtr, int64_t stream_id);
-
-/*
- * nghttp3_idtr_first_gap returns the first id of first gap. If there
- * is no gap, it returns UINT64_MAX. The returned id is an id space
- * used in this object internally, and not stream ID.
- */
-uint64_t nghttp3_idtr_first_gap(nghttp3_idtr *idtr);
-
-#endif /* NGHTTP3_IDTR_H */
diff --git a/deps/nghttp3/lib/nghttp3_ksl.c b/deps/nghttp3/lib/nghttp3_ksl.c
deleted file mode 100644
index 6a0f7c1de5..0000000000
--- a/deps/nghttp3/lib/nghttp3_ksl.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_ksl.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "nghttp3_macro.h"
-#include "nghttp3_mem.h"
-#include "nghttp3_range.h"
-
-static size_t ksl_nodelen(size_t keylen) {
- return (sizeof(nghttp3_ksl_node) + keylen - sizeof(uint64_t) + 0xf) &
- (size_t)~0xf;
-}
-
-static size_t ksl_blklen(size_t nodelen) {
- return sizeof(nghttp3_ksl_blk) + nodelen * NGHTTP3_KSL_MAX_NBLK -
- sizeof(uint64_t);
-}
-
-/*
- * ksl_node_set_key sets |key| to |node|.
- */
-static void ksl_node_set_key(nghttp3_ksl *ksl, nghttp3_ksl_node *node,
- const void *key) {
- memcpy(node->key, key, ksl->keylen);
-}
-
-int nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar, size_t keylen,
- const nghttp3_mem *mem) {
- size_t nodelen = ksl_nodelen(keylen);
- size_t blklen = ksl_blklen(nodelen);
- nghttp3_ksl_blk *head;
-
- ksl->head = nghttp3_mem_malloc(mem, blklen);
- if (!ksl->head) {
- return NGHTTP3_ERR_NOMEM;
- }
- ksl->front = ksl->back = ksl->head;
- ksl->compar = compar;
- ksl->keylen = keylen;
- ksl->nodelen = nodelen;
- ksl->n = 0;
- ksl->mem = mem;
-
- head = ksl->head;
- head->next = head->prev = NULL;
- head->n = 0;
- head->leaf = 1;
-
- return 0;
-}
-
-/*
- * ksl_free_blk frees |blk| recursively.
- */
-static void ksl_free_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) {
- size_t i;
-
- if (!blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- ksl_free_blk(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk);
- }
- }
-
- nghttp3_mem_free(ksl->mem, blk);
-}
-
-void nghttp3_ksl_free(nghttp3_ksl *ksl) {
- if (!ksl) {
- return;
- }
-
- ksl_free_blk(ksl, ksl->head);
-}
-
-/*
- * ksl_split_blk splits |blk| into 2 nghttp3_ksl_blk objects. The new
- * nghttp3_ksl_blk is always the "right" block.
- *
- * It returns the pointer to the nghttp3_ksl_blk created which is the
- * located at the right of |blk|, or NULL which indicates out of
- * memory error.
- */
-static nghttp3_ksl_blk *ksl_split_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) {
- nghttp3_ksl_blk *rblk;
-
- rblk = nghttp3_mem_malloc(ksl->mem, ksl_blklen(ksl->nodelen));
- if (rblk == NULL) {
- return NULL;
- }
-
- rblk->next = blk->next;
- blk->next = rblk;
- if (rblk->next) {
- rblk->next->prev = rblk;
- } else if (ksl->back == blk) {
- ksl->back = rblk;
- }
- rblk->prev = blk;
- rblk->leaf = blk->leaf;
-
- rblk->n = blk->n / 2;
-
- memcpy(rblk->nodes, blk->nodes + ksl->nodelen * (blk->n - rblk->n),
- ksl->nodelen * rblk->n);
-
- blk->n -= rblk->n;
-
- assert(blk->n >= NGHTTP3_KSL_MIN_NBLK);
- assert(rblk->n >= NGHTTP3_KSL_MIN_NBLK);
-
- return rblk;
-}
-
-/*
- * ksl_split_node splits a node included in |blk| at the position |i|
- * into 2 adjacent nodes. The new node is always inserted at the
- * position |i+1|.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int ksl_split_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
- nghttp3_ksl_node *node;
- nghttp3_ksl_blk *lblk = nghttp3_ksl_nth_node(ksl, blk, i)->blk, *rblk;
-
- rblk = ksl_split_blk(ksl, lblk);
- if (rblk == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- memmove(blk->nodes + (i + 2) * ksl->nodelen,
- blk->nodes + (i + 1) * ksl->nodelen,
- ksl->nodelen * (blk->n - (i + 1)));
-
- node = nghttp3_ksl_nth_node(ksl, blk, i + 1);
- node->blk = rblk;
- ++blk->n;
- ksl_node_set_key(ksl, node,
- nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
-
- node = nghttp3_ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node,
- nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
-
- return 0;
-}
-
-/*
- * ksl_split_head splits a head (root) block. It increases the height
- * of skip list by 1.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int ksl_split_head(nghttp3_ksl *ksl) {
- nghttp3_ksl_blk *rblk = NULL, *lblk, *nhead = NULL;
- nghttp3_ksl_node *node;
-
- rblk = ksl_split_blk(ksl, ksl->head);
- if (rblk == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- lblk = ksl->head;
-
- nhead = nghttp3_mem_malloc(ksl->mem, ksl_blklen(ksl->nodelen));
- if (nhead == NULL) {
- nghttp3_mem_free(ksl->mem, rblk);
- return NGHTTP3_ERR_NOMEM;
- }
- nhead->next = nhead->prev = NULL;
- nhead->n = 2;
- nhead->leaf = 0;
-
- node = nghttp3_ksl_nth_node(ksl, nhead, 0);
- ksl_node_set_key(ksl, node,
- nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
- node->blk = lblk;
-
- node = nghttp3_ksl_nth_node(ksl, nhead, 1);
- ksl_node_set_key(ksl, node,
- nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
- node->blk = rblk;
-
- ksl->head = nhead;
-
- return 0;
-}
-
-/*
- * insert_node inserts a node whose key is |key| with the associated
- * |data| at the index of |i|. This function assumes that the number
- * of nodes contained by |blk| is strictly less than
- * NGHTTP3_KSL_MAX_NBLK.
- */
-static void ksl_insert_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i,
- const nghttp3_ksl_key *key, void *data) {
- nghttp3_ksl_node *node;
-
- assert(blk->n < NGHTTP3_KSL_MAX_NBLK);
-
- memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
- ksl->nodelen * (blk->n - i));
-
- node = nghttp3_ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node, key);
- node->data = data;
-
- ++blk->n;
-}
-
-static size_t ksl_bsearch(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
- const nghttp3_ksl_key *key,
- nghttp3_ksl_compar compar) {
- nghttp3_ssize left = -1, right = (nghttp3_ssize)blk->n, mid;
- nghttp3_ksl_node *node;
-
- while (right - left > 1) {
- mid = (left + right) / 2;
- node = nghttp3_ksl_nth_node(ksl, blk, (size_t)mid);
- if (compar((nghttp3_ksl_key *)node->key, key)) {
- left = mid;
- } else {
- right = mid;
- }
- }
-
- return (size_t)right;
-}
-
-int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
- const nghttp3_ksl_key *key, void *data) {
- nghttp3_ksl_blk *blk = ksl->head;
- nghttp3_ksl_node *node;
- size_t i;
- int rv;
-
- if (blk->n == NGHTTP3_KSL_MAX_NBLK) {
- rv = ksl_split_head(ksl);
- if (rv != 0) {
- return rv;
- }
- blk = ksl->head;
- }
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (blk->leaf) {
- if (i < blk->n &&
- !ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) {
- if (it) {
- *it = nghttp3_ksl_end(ksl);
- }
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
- ksl_insert_node(ksl, blk, i, key, data);
- ++ksl->n;
- if (it) {
- nghttp3_ksl_it_init(it, ksl, blk, i);
- }
- return 0;
- }
-
- if (i == blk->n) {
- /* This insertion extends the largest key in this subtree. */
- for (; !blk->leaf;) {
- node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1);
- if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) {
- rv = ksl_split_node(ksl, blk, blk->n - 1);
- if (rv != 0) {
- return rv;
- }
- node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1);
- }
- ksl_node_set_key(ksl, node, key);
- blk = node->blk;
- }
- ksl_insert_node(ksl, blk, blk->n, key, data);
- ++ksl->n;
- if (it) {
- nghttp3_ksl_it_init(it, ksl, blk, blk->n - 1);
- }
- return 0;
- }
-
- node = nghttp3_ksl_nth_node(ksl, blk, i);
-
- if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) {
- rv = ksl_split_node(ksl, blk, i);
- if (rv != 0) {
- return rv;
- }
- if (ksl->compar((nghttp3_ksl_key *)node->key, key)) {
- node = nghttp3_ksl_nth_node(ksl, blk, i + 1);
- if (ksl->compar((nghttp3_ksl_key *)node->key, key)) {
- ksl_node_set_key(ksl, node, key);
- }
- }
- }
-
- blk = node->blk;
- }
-}
-
-/*
- * ksl_remove_node removes the node included in |blk| at the index of
- * |i|.
- */
-static void ksl_remove_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
- memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen,
- ksl->nodelen * (blk->n - (i + 1)));
-
- --blk->n;
-}
-
-/*
- * ksl_merge_node merges 2 nodes which are the nodes at the index of
- * |i| and |i + 1|.
- *
- * If |blk| is the direct descendant of head (root) block and the head
- * block contains just 2 nodes, the merged block becomes head block,
- * which decreases the height of |ksl| by 1.
- *
- * This function returns the pointer to the merged block.
- */
-static nghttp3_ksl_blk *ksl_merge_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
- size_t i) {
- nghttp3_ksl_blk *lblk, *rblk;
-
- assert(i + 1 < blk->n);
-
- lblk = nghttp3_ksl_nth_node(ksl, blk, i)->blk;
- rblk = nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk;
-
- assert(lblk->n + rblk->n < NGHTTP3_KSL_MAX_NBLK);
-
- memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes,
- ksl->nodelen * rblk->n);
-
- lblk->n += rblk->n;
- lblk->next = rblk->next;
- if (lblk->next) {
- lblk->next->prev = lblk;
- } else if (ksl->back == rblk) {
- ksl->back = lblk;
- }
-
- nghttp3_mem_free(ksl->mem, rblk);
-
- if (ksl->head == blk && blk->n == 2) {
- nghttp3_mem_free(ksl->mem, ksl->head);
- ksl->head = lblk;
- } else {
- ksl_remove_node(ksl, blk, i + 1);
- ksl_node_set_key(ksl, nghttp3_ksl_nth_node(ksl, blk, i),
- nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
- }
-
- return lblk;
-}
-
-/*
- * ksl_shift_left moves the first node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i - 1]->blk->nodes.
- */
-static void ksl_shift_left(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
- nghttp3_ksl_node *lnode, *rnode, *dest, *src;
-
- assert(i > 0);
-
- lnode = nghttp3_ksl_nth_node(ksl, blk, i - 1);
- rnode = nghttp3_ksl_nth_node(ksl, blk, i);
-
- assert(lnode->blk->n < NGHTTP3_KSL_MAX_NBLK);
- assert(rnode->blk->n > NGHTTP3_KSL_MIN_NBLK);
-
- dest = nghttp3_ksl_nth_node(ksl, lnode->blk, lnode->blk->n);
- src = nghttp3_ksl_nth_node(ksl, rnode->blk, 0);
-
- memcpy(dest, src, ksl->nodelen);
- ksl_node_set_key(ksl, lnode, dest->key);
- ++lnode->blk->n;
-
- --rnode->blk->n;
- memmove(rnode->blk->nodes, rnode->blk->nodes + ksl->nodelen,
- ksl->nodelen * rnode->blk->n);
-}
-
-/*
- * ksl_shift_right moves the last node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i + 1]->blk->nodes.
- */
-static void ksl_shift_right(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
- nghttp3_ksl_node *lnode, *rnode, *dest, *src;
-
- assert(i < blk->n - 1);
-
- lnode = nghttp3_ksl_nth_node(ksl, blk, i);
- rnode = nghttp3_ksl_nth_node(ksl, blk, i + 1);
-
- assert(lnode->blk->n > NGHTTP3_KSL_MIN_NBLK);
- assert(rnode->blk->n < NGHTTP3_KSL_MAX_NBLK);
-
- memmove(rnode->blk->nodes + ksl->nodelen, rnode->blk->nodes,
- ksl->nodelen * rnode->blk->n);
- ++rnode->blk->n;
-
- dest = nghttp3_ksl_nth_node(ksl, rnode->blk, 0);
- src = nghttp3_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1);
-
- memcpy(dest, src, ksl->nodelen);
-
- --lnode->blk->n;
- ksl_node_set_key(
- ksl, lnode,
- nghttp3_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
-}
-
-/*
- * key_equal returns nonzero if |lhs| and |rhs| are equal using the
- * function |compar|.
- */
-static int key_equal(nghttp3_ksl_compar compar, const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs) {
- return !compar(lhs, rhs) && !compar(rhs, lhs);
-}
-
-int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
- const nghttp3_ksl_key *key) {
- nghttp3_ksl_blk *blk = ksl->head;
- nghttp3_ksl_node *node;
- size_t i;
-
- if (!blk->leaf && blk->n == 2 &&
- nghttp3_ksl_nth_node(ksl, blk, 0)->blk->n == NGHTTP3_KSL_MIN_NBLK &&
- nghttp3_ksl_nth_node(ksl, blk, 1)->blk->n == NGHTTP3_KSL_MIN_NBLK) {
- blk = ksl_merge_node(ksl, ksl->head, 0);
- }
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (i == blk->n) {
- if (it) {
- *it = nghttp3_ksl_end(ksl);
- }
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (blk->leaf) {
- if (ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) {
- if (it) {
- *it = nghttp3_ksl_end(ksl);
- }
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
- ksl_remove_node(ksl, blk, i);
- --ksl->n;
- if (it) {
- if (blk->n == i && blk->next) {
- nghttp3_ksl_it_init(it, ksl, blk->next, 0);
- } else {
- nghttp3_ksl_it_init(it, ksl, blk, i);
- }
- }
- return 0;
- }
-
- node = nghttp3_ksl_nth_node(ksl, blk, i);
-
- if (node->blk->n == NGHTTP3_KSL_MIN_NBLK) {
- if (i > 0 && nghttp3_ksl_nth_node(ksl, blk, i - 1)->blk->n >
- NGHTTP3_KSL_MIN_NBLK) {
- ksl_shift_right(ksl, blk, i - 1);
- blk = node->blk;
- } else if (i + 1 < blk->n &&
- nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk->n >
- NGHTTP3_KSL_MIN_NBLK) {
- ksl_shift_left(ksl, blk, i + 1);
- blk = node->blk;
- } else if (i > 0) {
- blk = ksl_merge_node(ksl, blk, i - 1);
- } else {
- assert(i + 1 < blk->n);
- blk = ksl_merge_node(ksl, blk, i);
- }
- } else {
- blk = node->blk;
- }
- }
-}
-
-nghttp3_ksl_it nghttp3_ksl_lower_bound(nghttp3_ksl *ksl,
- const nghttp3_ksl_key *key) {
- nghttp3_ksl_blk *blk = ksl->head;
- nghttp3_ksl_it it;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (blk->leaf) {
- if (i == blk->n && blk->next) {
- blk = blk->next;
- i = 0;
- }
- nghttp3_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
-
- if (i == blk->n) {
- /* This happens if descendant has smaller key. Fast forward to
- find last node in this subtree. */
- for (; !blk->leaf; blk = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
- ;
- if (blk->next) {
- blk = blk->next;
- i = 0;
- } else {
- i = blk->n;
- }
- nghttp3_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
- blk = nghttp3_ksl_nth_node(ksl, blk, i)->blk;
- }
-}
-
-nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(nghttp3_ksl *ksl,
- const nghttp3_ksl_key *key,
- nghttp3_ksl_compar compar) {
- nghttp3_ksl_blk *blk = ksl->head;
- nghttp3_ksl_it it;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, compar);
-
- if (blk->leaf) {
- if (i == blk->n && blk->next) {
- blk = blk->next;
- i = 0;
- }
- nghttp3_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
-
- if (i == blk->n) {
- /* This happens if descendant has smaller key. Fast forward to
- find last node in this subtree. */
- for (; !blk->leaf; blk = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
- ;
- if (blk->next) {
- blk = blk->next;
- i = 0;
- } else {
- i = blk->n;
- }
- nghttp3_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
- blk = nghttp3_ksl_nth_node(ksl, blk, i)->blk;
- }
-}
-
-void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key,
- const nghttp3_ksl_key *new_key) {
- nghttp3_ksl_blk *blk = ksl->head;
- nghttp3_ksl_node *node;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, old_key, ksl->compar);
-
- assert(i < blk->n);
- node = nghttp3_ksl_nth_node(ksl, blk, i);
-
- if (blk->leaf) {
- assert(key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key));
- ksl_node_set_key(ksl, node, new_key);
- return;
- }
-
- if (key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key) ||
- ksl->compar((nghttp3_ksl_key *)node->key, new_key)) {
- ksl_node_set_key(ksl, node, new_key);
- }
-
- blk = node->blk;
- }
-}
-
-static void ksl_print(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t level) {
- size_t i;
- nghttp3_ksl_node *node;
-
- fprintf(stderr, "LV=%zu n=%zu\n", level, blk->n);
-
- if (blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- node = nghttp3_ksl_nth_node(ksl, blk, i);
- fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
- }
- fprintf(stderr, "\n");
- return;
- }
-
- for (i = 0; i < blk->n; ++i) {
- ksl_print(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk, level + 1);
- }
-}
-
-size_t nghttp3_ksl_len(nghttp3_ksl *ksl) { return ksl->n; }
-
-void nghttp3_ksl_clear(nghttp3_ksl *ksl) {
- size_t i;
- nghttp3_ksl_blk *head;
-
- if (!ksl->head->leaf) {
- for (i = 0; i < ksl->head->n; ++i) {
- ksl_free_blk(ksl, nghttp3_ksl_nth_node(ksl, ksl->head, i)->blk);
- }
- }
-
- ksl->front = ksl->back = ksl->head;
- ksl->n = 0;
-
- head = ksl->head;
-
- head->next = head->prev = NULL;
- head->n = 0;
- head->leaf = 1;
-}
-
-void nghttp3_ksl_print(nghttp3_ksl *ksl) { ksl_print(ksl, ksl->head, 0); }
-
-nghttp3_ksl_it nghttp3_ksl_begin(const nghttp3_ksl *ksl) {
- nghttp3_ksl_it it;
- nghttp3_ksl_it_init(&it, ksl, ksl->front, 0);
- return it;
-}
-
-nghttp3_ksl_it nghttp3_ksl_end(const nghttp3_ksl *ksl) {
- nghttp3_ksl_it it;
- nghttp3_ksl_it_init(&it, ksl, ksl->back, ksl->back->n);
- return it;
-}
-
-void nghttp3_ksl_it_init(nghttp3_ksl_it *it, const nghttp3_ksl *ksl,
- nghttp3_ksl_blk *blk, size_t i) {
- it->ksl = ksl;
- it->blk = blk;
- it->i = i;
-}
-
-void *nghttp3_ksl_it_get(const nghttp3_ksl_it *it) {
- assert(it->i < it->blk->n);
- return nghttp3_ksl_nth_node(it->ksl, it->blk, it->i)->data;
-}
-
-void nghttp3_ksl_it_prev(nghttp3_ksl_it *it) {
- assert(!nghttp3_ksl_it_begin(it));
-
- if (it->i == 0) {
- it->blk = it->blk->prev;
- it->i = it->blk->n - 1;
- } else {
- --it->i;
- }
-}
-
-int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it) {
- return it->i == 0 && it->blk->prev == NULL;
-}
-
-int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs) {
- const nghttp3_range *a = lhs, *b = rhs;
- return a->begin < b->begin;
-}
-
-int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs) {
- const nghttp3_range *a = lhs, *b = rhs;
- return a->begin < b->begin &&
- !(nghttp3_max(a->begin, b->begin) < nghttp3_min(a->end, b->end));
-}
diff --git a/deps/nghttp3/lib/nghttp3_ksl.h b/deps/nghttp3/lib/nghttp3_ksl.h
deleted file mode 100644
index aeb77eea57..0000000000
--- a/deps/nghttp3/lib/nghttp3_ksl.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_KSL_H
-#define NGHTTP3_KSL_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-
-#include <nghttp3/nghttp3.h>
-
-/*
- * Skip List using single key instead of range.
- */
-
-#define NGHTTP3_KSL_DEGR 16
-/* NGHTTP3_KSL_MAX_NBLK is the maximum number of nodes which a single
- block can contain. */
-#define NGHTTP3_KSL_MAX_NBLK (2 * NGHTTP3_KSL_DEGR - 1)
-/* NGHTTP3_KSL_MIN_NBLK is the minimum number of nodes which a single
- block other than root must contains. */
-#define NGHTTP3_KSL_MIN_NBLK (NGHTTP3_KSL_DEGR - 1)
-
-/*
- * nghttp3_ksl_key represents key in nghttp3_ksl.
- */
-typedef void nghttp3_ksl_key;
-
-struct nghttp3_ksl_node;
-typedef struct nghttp3_ksl_node nghttp3_ksl_node;
-
-struct nghttp3_ksl_blk;
-typedef struct nghttp3_ksl_blk nghttp3_ksl_blk;
-
-/*
- * nghttp3_ksl_node is a node which contains either nghttp3_ksl_blk or
- * opaque data. If a node is an internal node, it contains
- * nghttp3_ksl_blk. Otherwise, it has data. The key is stored at the
- * location starting at key.
- */
-struct nghttp3_ksl_node {
- union {
- nghttp3_ksl_blk *blk;
- void *data;
- };
- union {
- uint64_t align;
- /* key is a buffer to include key associated to this node.
- Because the length of key is unknown until nghttp3_ksl_init is
- called, the actual buffer will be allocated after this
- field. */
- uint8_t key[1];
- };
-};
-
-/*
- * nghttp3_ksl_blk contains nghttp3_ksl_node objects.
- */
-struct nghttp3_ksl_blk {
- /* next points to the next block if leaf field is nonzero. */
- nghttp3_ksl_blk *next;
- /* prev points to the previous block if leaf field is nonzero. */
- nghttp3_ksl_blk *prev;
- /* n is the number of nodes this object contains in nodes. */
- size_t n;
- /* leaf is nonzero if this block contains leaf nodes. */
- int leaf;
- union {
- uint64_t align;
- /* nodes is a buffer to contain NGHTTP3_KSL_MAX_NBLK
- nghttp3_ksl_node objects. Because nghttp3_ksl_node object is
- allocated along with the additional variable length key
- storage, the size of buffer is unknown until nghttp3_ksl_init
- is called. */
- uint8_t nodes[1];
- };
-};
-
-/*
- * nghttp3_ksl_compar is a function type which returns nonzero if key
- * |lhs| should be placed before |rhs|. It returns 0 otherwise.
- */
-typedef int (*nghttp3_ksl_compar)(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs);
-
-struct nghttp3_ksl;
-typedef struct nghttp3_ksl nghttp3_ksl;
-
-struct nghttp3_ksl_it;
-typedef struct nghttp3_ksl_it nghttp3_ksl_it;
-
-/*
- * nghttp3_ksl_it is a forward iterator to iterate nodes.
- */
-struct nghttp3_ksl_it {
- const nghttp3_ksl *ksl;
- nghttp3_ksl_blk *blk;
- size_t i;
-};
-
-/*
- * nghttp3_ksl is a deterministic paged skip list.
- */
-struct nghttp3_ksl {
- /* head points to the root block. */
- nghttp3_ksl_blk *head;
- /* front points to the first leaf block. */
- nghttp3_ksl_blk *front;
- /* back points to the last leaf block. */
- nghttp3_ksl_blk *back;
- nghttp3_ksl_compar compar;
- size_t n;
- /* keylen is the size of key */
- size_t keylen;
- /* nodelen is the actual size of nghttp3_ksl_node including key
- storage. */
- size_t nodelen;
- const nghttp3_mem *mem;
-};
-
-/*
- * nghttp3_ksl_init initializes |ksl|. |compar| specifies compare
- * function. |keylen| is the length of key.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar, size_t keylen,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_ksl_free frees resources allocated for |ksl|. If |ksl| is
- * NULL, this function does nothing. It does not free the memory
- * region pointed by |ksl| itself.
- */
-void nghttp3_ksl_free(nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_insert inserts |key| with its associated |data|. On
- * successful insertion, the iterator points to the inserted node is
- * stored in |*it|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_INVALID_ARGUMENT
- * |key| already exists.
- */
-int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
- const nghttp3_ksl_key *key, void *data);
-
-/*
- * nghttp3_ksl_remove removes the |key| from |ksl|.
- *
- * This function assigns the iterator to |*it|, which points to the
- * node which is located at the right next of the removed node if |it|
- * is not NULL. If |key| is not found, no deletion takes place and
- * the return value of nghttp3_ksl_end(ksl) is assigned to |*it|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_INVALID_ARGUMENT
- * |key| does not exist.
- */
-int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
- const nghttp3_ksl_key *key);
-
-/*
- * nghttp3_ksl_lower_bound returns the iterator which points to the
- * first node which has the key which is equal to |key| or the last
- * node which satisfies !compar(&node->key, key). If there is no such
- * node, it returns the iterator which satisfies nghttp3_ksl_it_end(it)
- * != 0.
- */
-nghttp3_ksl_it nghttp3_ksl_lower_bound(nghttp3_ksl *ksl,
- const nghttp3_ksl_key *key);
-
-/*
- * nghttp3_ksl_lower_bound_compar works like nghttp3_ksl_lower_bound,
- * but it takes custom function |compar| to do lower bound search.
- */
-nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(nghttp3_ksl *ksl,
- const nghttp3_ksl_key *key,
- nghttp3_ksl_compar compar);
-
-/*
- * nghttp3_ksl_update_key replaces the key of nodes which has |old_key|
- * with |new_key|. |new_key| must be strictly greater than the
- * previous node and strictly smaller than the next node.
- */
-void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key,
- const nghttp3_ksl_key *new_key);
-
-/*
- * nghttp3_ksl_begin returns the iterator which points to the first
- * node. If there is no node in |ksl|, it returns the iterator which
- * satisfies nghttp3_ksl_it_end(it) != 0.
- */
-nghttp3_ksl_it nghttp3_ksl_begin(const nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_end returns the iterator which points to the node
- * following the last node. The returned object satisfies
- * nghttp3_ksl_it_end(). If there is no node in |ksl|, it returns the
- * iterator which satisfies nghttp3_ksl_it_begin(it) != 0.
- */
-nghttp3_ksl_it nghttp3_ksl_end(const nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_len returns the number of elements stored in |ksl|.
- */
-size_t nghttp3_ksl_len(nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_clear removes all elements stored in |ksl|.
- */
-void nghttp3_ksl_clear(nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_nth_node returns the |n|th node under |blk|.
- */
-#define nghttp3_ksl_nth_node(KSL, BLK, N) \
- ((nghttp3_ksl_node *)(void *)((BLK)->nodes + (KSL)->nodelen * (N)))
-
-/*
- * nghttp3_ksl_print prints its internal state in stderr. It assumes
- * that the key is of type int64_t. This function should be used for
- * the debugging purpose only.
- */
-void nghttp3_ksl_print(nghttp3_ksl *ksl);
-
-/*
- * nghttp3_ksl_it_init initializes |it|.
- */
-void nghttp3_ksl_it_init(nghttp3_ksl_it *it, const nghttp3_ksl *ksl,
- nghttp3_ksl_blk *blk, size_t i);
-
-/*
- * nghttp3_ksl_it_get returns the data associated to the node which
- * |it| points to. It is undefined to call this function when
- * nghttp3_ksl_it_end(it) returns nonzero.
- */
-void *nghttp3_ksl_it_get(const nghttp3_ksl_it *it);
-
-/*
- * nghttp3_ksl_it_next advances the iterator by one. It is undefined
- * if this function is called when nghttp3_ksl_it_end(it) returns
- * nonzero.
- */
-#define nghttp3_ksl_it_next(IT) \
- (++(IT)->i == (IT)->blk->n && (IT)->blk->next \
- ? ((IT)->blk = (IT)->blk->next, (IT)->i = 0) \
- : 0)
-
-/*
- * nghttp3_ksl_it_prev moves backward the iterator by one. It is
- * undefined if this function is called when nghttp3_ksl_it_begin(it)
- * returns nonzero.
- */
-void nghttp3_ksl_it_prev(nghttp3_ksl_it *it);
-
-/*
- * nghttp3_ksl_it_end returns nonzero if |it| points to the beyond the
- * last node.
- */
-#define nghttp3_ksl_it_end(IT) \
- ((IT)->blk->n == (IT)->i && (IT)->blk->next == NULL)
-
-/*
- * nghttp3_ksl_it_begin returns nonzero if |it| points to the first
- * node. |it| might satisfy both nghttp3_ksl_it_begin(&it) and
- * nghttp3_ksl_it_end(&it) if the skip list has no node.
- */
-int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it);
-
-/*
- * nghttp3_ksl_key returns the key of the node which |it| points to.
- * It is undefined to call this function when nghttp3_ksl_it_end(it)
- * returns nonzero.
- */
-#define nghttp3_ksl_it_key(IT) \
- ((nghttp3_ksl_key *)nghttp3_ksl_nth_node((IT)->ksl, (IT)->blk, (IT)->i)->key)
-
-/*
- * nghttp3_ksl_range_compar is an implementation of
- * nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
- * nghttp3_range object and the function returns nonzero if (const
- * nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
- * *)(rhs->ptr)->begin.
- */
-int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs);
-
-/*
- * nghttp3_ksl_range_exclusive_compar is an implementation of
- * nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
- * nghttp3_range object and the function returns nonzero if (const
- * nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
- * *)(rhs->ptr)->begin and the 2 ranges do not intersect.
- */
-int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs);
-
-#endif /* NGHTTP3_KSL_H */
diff --git a/deps/nghttp3/lib/nghttp3_macro.h b/deps/nghttp3/lib/nghttp3_macro.h
deleted file mode 100644
index 6ee704cc47..0000000000
--- a/deps/nghttp3/lib/nghttp3_macro.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_MACRO_H
-#define NGHTTP3_MACRO_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stddef.h>
-
-#include <nghttp3/nghttp3.h>
-
-#define nghttp3_min(A, B) ((A) < (B) ? (A) : (B))
-#define nghttp3_max(A, B) ((A) > (B) ? (A) : (B))
-
-#define nghttp3_struct_of(ptr, type, member) \
- ((type *)(void *)((char *)(ptr)-offsetof(type, member)))
-
-#define nghttp3_arraylen(A) (sizeof(A) / sizeof(*(A)))
-
-#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
-
-#endif /* NGHTTP3_MACRO_H */
diff --git a/deps/nghttp3/lib/nghttp3_map.c b/deps/nghttp3/lib/nghttp3_map.c
deleted file mode 100644
index e8eb811566..0000000000
--- a/deps/nghttp3/lib/nghttp3_map.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_map.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "nghttp3_conv.h"
-
-#define INITIAL_TABLE_LENGTH 256
-
-int nghttp3_map_init(nghttp3_map *map, const nghttp3_mem *mem) {
- map->mem = mem;
- map->tablelen = INITIAL_TABLE_LENGTH;
- map->table =
- nghttp3_mem_calloc(mem, map->tablelen, sizeof(nghttp3_map_bucket));
- if (map->table == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- map->size = 0;
-
- return 0;
-}
-
-void nghttp3_map_free(nghttp3_map *map) {
- size_t i;
- nghttp3_map_bucket *bkt;
-
- if (!map) {
- return;
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- if (bkt->ksl) {
- nghttp3_ksl_free(bkt->ksl);
- nghttp3_mem_free(map->mem, bkt->ksl);
- }
- }
-
- nghttp3_mem_free(map->mem, map->table);
-}
-
-void nghttp3_map_each_free(nghttp3_map *map,
- int (*func)(nghttp3_map_entry *entry, void *ptr),
- void *ptr) {
- uint32_t i;
- nghttp3_map_bucket *bkt;
- nghttp3_ksl_it it;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- func(bkt->ptr, ptr);
- bkt->ptr = NULL;
- assert(bkt->ksl == NULL || nghttp3_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = nghttp3_ksl_begin(bkt->ksl); !nghttp3_ksl_it_end(&it);
- nghttp3_ksl_it_next(&it)) {
- func(nghttp3_ksl_it_get(&it), ptr);
- }
-
- nghttp3_ksl_free(bkt->ksl);
- nghttp3_mem_free(map->mem, bkt->ksl);
- bkt->ksl = NULL;
- }
- }
-}
-
-int nghttp3_map_each(nghttp3_map *map,
- int (*func)(nghttp3_map_entry *entry, void *ptr),
- void *ptr) {
- int rv;
- uint32_t i;
- nghttp3_map_bucket *bkt;
- nghttp3_ksl_it it;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- rv = func(bkt->ptr, ptr);
- if (rv != 0) {
- return rv;
- }
- assert(bkt->ksl == NULL || nghttp3_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = nghttp3_ksl_begin(bkt->ksl); !nghttp3_ksl_it_end(&it);
- nghttp3_ksl_it_next(&it)) {
- rv = func(nghttp3_ksl_it_get(&it), ptr);
- if (rv != 0) {
- return rv;
- }
- }
- }
- }
- return 0;
-}
-
-void nghttp3_map_entry_init(nghttp3_map_entry *entry, key_type key) {
- entry->key = key;
- entry->next = NULL;
-}
-
-/* FNV1a hash */
-static uint32_t hash(key_type key, uint32_t mod) {
- uint8_t *p, *end;
- uint32_t h = 0x811C9DC5u;
-
- key = nghttp3_htonl64(key);
- p = (uint8_t *)&key;
- end = p + sizeof(key_type);
-
- for (; p != end;) {
- h ^= *p++;
- h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
- }
-
- return h & (mod - 1);
-}
-
-static int less(const nghttp3_ksl_key *lhs, const nghttp3_ksl_key *rhs) {
- return *(key_type *)lhs < *(key_type *)rhs;
-}
-
-static int map_insert(nghttp3_map *map, nghttp3_map_bucket *table,
- uint32_t tablelen, nghttp3_map_entry *entry) {
- uint32_t h = hash(entry->key, tablelen);
- nghttp3_map_bucket *bkt = &table[h];
- const nghttp3_mem *mem = map->mem;
- int rv;
-
- if (bkt->ptr == NULL &&
- (bkt->ksl == NULL || nghttp3_ksl_len(bkt->ksl) == 0)) {
- bkt->ptr = entry;
- return 0;
- }
-
- if (!bkt->ksl) {
- bkt->ksl = nghttp3_mem_malloc(mem, sizeof(*bkt->ksl));
- if (bkt->ksl == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
- nghttp3_ksl_init(bkt->ksl, less, sizeof(key_type), mem);
- }
-
- if (bkt->ptr) {
- rv = nghttp3_ksl_insert(bkt->ksl, NULL, &bkt->ptr->key, bkt->ptr);
- if (rv != 0) {
- return rv;
- }
-
- bkt->ptr = NULL;
- }
-
- return nghttp3_ksl_insert(bkt->ksl, NULL, &entry->key, entry);
-}
-
-/* new_tablelen must be power of 2 */
-static int map_resize(nghttp3_map *map, uint32_t new_tablelen) {
- uint32_t i;
- nghttp3_map_bucket *new_table;
- nghttp3_map_bucket *bkt;
- nghttp3_ksl_it it;
- int rv;
-
- new_table =
- nghttp3_mem_calloc(map->mem, new_tablelen, sizeof(nghttp3_map_bucket));
- if (new_table == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- rv = map_insert(map, new_table, new_tablelen, bkt->ptr);
- if (rv != 0) {
- goto fail;
- }
- assert(bkt->ksl == NULL || nghttp3_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = nghttp3_ksl_begin(bkt->ksl); !nghttp3_ksl_it_end(&it);
- nghttp3_ksl_it_next(&it)) {
- rv = map_insert(map, new_table, new_tablelen, nghttp3_ksl_it_get(&it));
- if (rv != 0) {
- goto fail;
- }
- }
- }
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- if (bkt->ksl) {
- nghttp3_ksl_free(bkt->ksl);
- nghttp3_mem_free(map->mem, bkt->ksl);
- }
- }
-
- nghttp3_mem_free(map->mem, map->table);
- map->tablelen = new_tablelen;
- map->table = new_table;
-
- return 0;
-
-fail:
- for (i = 0; i < new_tablelen; ++i) {
- bkt = &new_table[i];
- if (bkt->ksl) {
- nghttp3_ksl_free(bkt->ksl);
- nghttp3_mem_free(map->mem, bkt->ksl);
- }
- }
-
- return rv;
-}
-
-int nghttp3_map_insert(nghttp3_map *map, nghttp3_map_entry *new_entry) {
- int rv;
-
- /* Load factor is 0.75 */
- if ((map->size + 1) * 4 > map->tablelen * 3) {
- rv = map_resize(map, map->tablelen * 2);
- if (rv != 0) {
- return rv;
- }
- }
- rv = map_insert(map, map->table, map->tablelen, new_entry);
- if (rv != 0) {
- return rv;
- }
- ++map->size;
- return 0;
-}
-
-nghttp3_map_entry *nghttp3_map_find(nghttp3_map *map, key_type key) {
- nghttp3_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
- nghttp3_ksl_it it;
-
- if (bkt->ptr) {
- if (bkt->ptr->key == key) {
- return bkt->ptr;
- }
- return NULL;
- }
-
- if (bkt->ksl) {
- it = nghttp3_ksl_lower_bound(bkt->ksl, &key);
- if (nghttp3_ksl_it_end(&it) ||
- *(key_type *)nghttp3_ksl_it_key(&it) != key) {
- return NULL;
- }
- return nghttp3_ksl_it_get(&it);
- }
-
- return NULL;
-}
-
-int nghttp3_map_remove(nghttp3_map *map, key_type key) {
- nghttp3_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
- int rv;
-
- if (bkt->ptr) {
- if (bkt->ptr->key == key) {
- bkt->ptr = NULL;
- --map->size;
- return 0;
- }
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (bkt->ksl) {
- rv = nghttp3_ksl_remove(bkt->ksl, NULL, &key);
- if (rv != 0) {
- return rv;
- }
- --map->size;
- return 0;
- }
-
- return NGHTTP3_ERR_INVALID_ARGUMENT;
-}
-
-void nghttp3_map_clear(nghttp3_map *map) {
- uint32_t i;
- nghttp3_map_bucket *bkt;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- bkt->ptr = NULL;
- if (bkt->ksl) {
- nghttp3_ksl_free(bkt->ksl);
- nghttp3_mem_free(map->mem, bkt->ksl);
- bkt->ksl = NULL;
- }
- }
-
- map->size = 0;
-}
-
-size_t nghttp3_map_size(nghttp3_map *map) { return map->size; }
diff --git a/deps/nghttp3/lib/nghttp3_map.h b/deps/nghttp3/lib/nghttp3_map.h
deleted file mode 100644
index 8a00711970..0000000000
--- a/deps/nghttp3/lib/nghttp3_map.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_MAP_H
-#define NGHTTP3_MAP_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-#include "nghttp3_ksl.h"
-
-/* Implementation of unordered map */
-
-typedef uint64_t key_type;
-
-typedef struct nghttp3_map_entry {
- struct nghttp3_map_entry *next;
- key_type key;
-} nghttp3_map_entry;
-
-typedef struct nghttp3_map_bucket {
- nghttp3_map_entry *ptr;
- nghttp3_ksl *ksl;
-} nghttp3_map_bucket;
-
-typedef struct {
- nghttp3_map_bucket *table;
- const nghttp3_mem *mem;
- size_t size;
- uint32_t tablelen;
-} nghttp3_map;
-
-/*
- * Initializes the map |map|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory
- */
-int nghttp3_map_init(nghttp3_map *map, const nghttp3_mem *mem);
-
-/*
- * Deallocates any resources allocated for |map|. The stored entries
- * are not freed by this function. Use nghttp3_map_each_free() to free
- * each entries.
- */
-void nghttp3_map_free(nghttp3_map *map);
-
-/*
- * Deallocates each entries using |func| function and any resources
- * allocated for |map|. The |func| function is responsible for freeing
- * given the |entry| object. The |ptr| will be passed to the |func| as
- * send argument. The return value of the |func| will be ignored.
- */
-void nghttp3_map_each_free(nghttp3_map *map,
- int (*func)(nghttp3_map_entry *entry, void *ptr),
- void *ptr);
-
-/*
- * Initializes the |entry| with the |key|. All entries to be inserted
- * to the map must be initialized with this function.
- */
-void nghttp3_map_entry_init(nghttp3_map_entry *entry, key_type key);
-
-/*
- * Inserts the new |entry| with the key |entry->key| to the map |map|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_INVALID_ARGUMENT
- * The item associated by |key| already exists.
- * NGHTTP3_ERR_NOMEM
- * Out of memory
- */
-int nghttp3_map_insert(nghttp3_map *map, nghttp3_map_entry *entry);
-
-/*
- * Returns the entry associated by the key |key|. If there is no such
- * entry, this function returns NULL.
- */
-nghttp3_map_entry *nghttp3_map_find(nghttp3_map *map, key_type key);
-
-/*
- * Removes the entry associated by the key |key| from the |map|. The
- * removed entry is not freed by this function.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_INVALID_ARGUMENT
- * The entry associated by |key| does not exist.
- */
-int nghttp3_map_remove(nghttp3_map *map, key_type key);
-
-/*
- * Removes all entries from |map|.
- */
-void nghttp3_map_clear(nghttp3_map *map);
-
-/*
- * Returns the number of items stored in the map |map|.
- */
-size_t nghttp3_map_size(nghttp3_map *map);
-
-/*
- * Applies the function |func| to each entry in the |map| with the
- * optional user supplied pointer |ptr|.
- *
- * If the |func| returns 0, this function calls the |func| with the
- * next entry. If the |func| returns nonzero, it will not call the
- * |func| for further entries and return the return value of the
- * |func| immediately. Thus, this function returns 0 if all the
- * invocations of the |func| return 0, or nonzero value which the last
- * invocation of |func| returns.
- *
- * Don't use this function to free each entry. Use
- * nghttp3_map_each_free() instead.
- */
-int nghttp3_map_each(nghttp3_map *map,
- int (*func)(nghttp3_map_entry *entry, void *ptr),
- void *ptr);
-
-#endif /* NGHTTP3_MAP_H */
diff --git a/deps/nghttp3/lib/nghttp3_mem.c b/deps/nghttp3/lib/nghttp3_mem.c
deleted file mode 100644
index e5f93f10bd..0000000000
--- a/deps/nghttp3/lib/nghttp3_mem.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2014 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_mem.h"
-
-static void *default_malloc(size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return malloc(size);
-}
-
-static void default_free(void *ptr, void *mem_user_data) {
- (void)mem_user_data;
-
- free(ptr);
-}
-
-static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return calloc(nmemb, size);
-}
-
-static void *default_realloc(void *ptr, size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return realloc(ptr, size);
-}
-
-static nghttp3_mem mem_default = {NULL, default_malloc, default_free,
- default_calloc, default_realloc};
-
-const nghttp3_mem *nghttp3_mem_default(void) { return &mem_default; }
-
-void *nghttp3_mem_malloc(const nghttp3_mem *mem, size_t size) {
- return mem->malloc(size, mem->mem_user_data);
-}
-
-void nghttp3_mem_free(const nghttp3_mem *mem, void *ptr) {
- mem->free(ptr, mem->mem_user_data);
-}
-
-void nghttp3_mem_free2(const nghttp3_free free_func, void *ptr,
- void *mem_user_data) {
- free_func(ptr, mem_user_data);
-}
-
-void *nghttp3_mem_calloc(const nghttp3_mem *mem, size_t nmemb, size_t size) {
- return mem->calloc(nmemb, size, mem->mem_user_data);
-}
-
-void *nghttp3_mem_realloc(const nghttp3_mem *mem, void *ptr, size_t size) {
- return mem->realloc(ptr, size, mem->mem_user_data);
-}
diff --git a/deps/nghttp3/lib/nghttp3_mem.h b/deps/nghttp3/lib/nghttp3_mem.h
deleted file mode 100644
index 55ef86b4f9..0000000000
--- a/deps/nghttp3/lib/nghttp3_mem.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2014 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_MEM_H
-#define NGHTTP3_MEM_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-/* Convenient wrapper functions to call allocator function in
- |mem|. */
-void *nghttp3_mem_malloc(const nghttp3_mem *mem, size_t size);
-void nghttp3_mem_free(const nghttp3_mem *mem, void *ptr);
-void nghttp3_mem_free2(const nghttp3_free free_func, void *ptr,
- void *mem_user_data);
-void *nghttp3_mem_calloc(const nghttp3_mem *mem, size_t nmemb, size_t size);
-void *nghttp3_mem_realloc(const nghttp3_mem *mem, void *ptr, size_t size);
-
-#endif /* NGHTTP3_MEM_H */
diff --git a/deps/nghttp3/lib/nghttp3_pq.c b/deps/nghttp3/lib/nghttp3_pq.c
deleted file mode 100644
index 5d09050ae6..0000000000
--- a/deps/nghttp3/lib/nghttp3_pq.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_pq.h"
-
-#include <assert.h>
-
-#include "nghttp3_macro.h"
-
-void nghttp3_pq_init(nghttp3_pq *pq, nghttp3_less less,
- const nghttp3_mem *mem) {
- pq->mem = mem;
- pq->capacity = 0;
- pq->q = NULL;
- pq->length = 0;
- pq->less = less;
-}
-
-void nghttp3_pq_free(nghttp3_pq *pq) {
- nghttp3_mem_free(pq->mem, pq->q);
- pq->q = NULL;
-}
-
-static void swap(nghttp3_pq *pq, size_t i, size_t j) {
- nghttp3_pq_entry *a = pq->q[i];
- nghttp3_pq_entry *b = pq->q[j];
-
- pq->q[i] = b;
- b->index = i;
- pq->q[j] = a;
- a->index = j;
-}
-
-static void bubble_up(nghttp3_pq *pq, size_t index) {
- size_t parent;
- while (index != 0) {
- parent = (index - 1) / 2;
- if (!pq->less(pq->q[index], pq->q[parent])) {
- return;
- }
- swap(pq, parent, index);
- index = parent;
- }
-}
-
-int nghttp3_pq_push(nghttp3_pq *pq, nghttp3_pq_entry *item) {
- if (pq->capacity <= pq->length) {
- void *nq;
- size_t ncapacity;
-
- ncapacity = nghttp3_max(4, (pq->capacity * 2));
-
- nq = nghttp3_mem_realloc(pq->mem, pq->q,
- ncapacity * sizeof(nghttp3_pq_entry *));
- if (nq == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
- pq->capacity = ncapacity;
- pq->q = nq;
- }
- pq->q[pq->length] = item;
- item->index = pq->length;
- ++pq->length;
- bubble_up(pq, pq->length - 1);
- return 0;
-}
-
-nghttp3_pq_entry *nghttp3_pq_top(const nghttp3_pq *pq) {
- assert(pq->length);
- return pq->q[0];
-}
-
-static void bubble_down(nghttp3_pq *pq, size_t index) {
- size_t i, j, minindex;
- for (;;) {
- j = index * 2 + 1;
- minindex = index;
- for (i = 0; i < 2; ++i, ++j) {
- if (j >= pq->length) {
- break;
- }
- if (pq->less(pq->q[j], pq->q[minindex])) {
- minindex = j;
- }
- }
- if (minindex == index) {
- return;
- }
- swap(pq, index, minindex);
- index = minindex;
- }
-}
-
-void nghttp3_pq_pop(nghttp3_pq *pq) {
- if (pq->length > 0) {
- pq->q[0] = pq->q[pq->length - 1];
- pq->q[0]->index = 0;
- --pq->length;
- bubble_down(pq, 0);
- }
-}
-
-void nghttp3_pq_remove(nghttp3_pq *pq, nghttp3_pq_entry *item) {
- assert(pq->q[item->index] == item);
-
- if (item->index == 0) {
- nghttp3_pq_pop(pq);
- return;
- }
-
- if (item->index == pq->length - 1) {
- --pq->length;
- return;
- }
-
- pq->q[item->index] = pq->q[pq->length - 1];
- pq->q[item->index]->index = item->index;
- --pq->length;
-
- if (pq->less(item, pq->q[item->index])) {
- bubble_down(pq, item->index);
- } else {
- bubble_up(pq, item->index);
- }
-}
-
-int nghttp3_pq_empty(const nghttp3_pq *pq) { return pq->length == 0; }
-
-size_t nghttp3_pq_size(const nghttp3_pq *pq) { return pq->length; }
-
-int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg) {
- size_t i;
-
- if (pq->length == 0) {
- return 0;
- }
- for (i = 0; i < pq->length; ++i) {
- if ((*fun)(pq->q[i], arg)) {
- return 1;
- }
- }
- return 0;
-}
-
-void nghttp3_pq_clear(nghttp3_pq *pq) { pq->length = 0; }
diff --git a/deps/nghttp3/lib/nghttp3_pq.h b/deps/nghttp3/lib/nghttp3_pq.h
deleted file mode 100644
index e80b1bc43b..0000000000
--- a/deps/nghttp3/lib/nghttp3_pq.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_PQ_H
-#define NGHTTP3_PQ_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-
-/* Implementation of priority queue */
-
-/* NGHTTP3_PQ_BAD_INDEX is the priority queue index which indicates
- that an entry is not queued. Assigning this value to
- nghttp3_pq_entry.index can check that the entry is queued or not. */
-#define NGHTTP3_PQ_BAD_INDEX SIZE_MAX
-
-typedef struct {
- size_t index;
-} nghttp3_pq_entry;
-
-/* "less" function, return nonzero if |lhs| is less than |rhs|. */
-typedef int (*nghttp3_less)(const nghttp3_pq_entry *lhs,
- const nghttp3_pq_entry *rhs);
-
-typedef struct {
- /* The pointer to the pointer to the item stored */
- nghttp3_pq_entry **q;
- /* Memory allocator */
- const nghttp3_mem *mem;
- /* The number of items stored */
- size_t length;
- /* The maximum number of items this pq can store. This is
- automatically extended when length is reached to this value. */
- size_t capacity;
- /* The less function between items */
- nghttp3_less less;
-} nghttp3_pq;
-
-/*
- * Initializes priority queue |pq| with compare function |cmp|.
- */
-void nghttp3_pq_init(nghttp3_pq *pq, nghttp3_less less, const nghttp3_mem *mem);
-
-/*
- * Deallocates any resources allocated for |pq|. The stored items are
- * not freed by this function.
- */
-void nghttp3_pq_free(nghttp3_pq *pq);
-
-/*
- * Adds |item| to the priority queue |pq|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_pq_push(nghttp3_pq *pq, nghttp3_pq_entry *item);
-
-/*
- * Returns item at the top of the queue |pq|. It is undefined if the
- * queue is empty.
- */
-nghttp3_pq_entry *nghttp3_pq_top(const nghttp3_pq *pq);
-
-/*
- * Pops item at the top of the queue |pq|. The popped item is not
- * freed by this function.
- */
-void nghttp3_pq_pop(nghttp3_pq *pq);
-
-/*
- * Returns nonzero if the queue |pq| is empty.
- */
-int nghttp3_pq_empty(const nghttp3_pq *pq);
-
-/*
- * Returns the number of items in the queue |pq|.
- */
-size_t nghttp3_pq_size(const nghttp3_pq *pq);
-
-typedef int (*nghttp3_pq_item_cb)(nghttp3_pq_entry *item, void *arg);
-
-/*
- * Applys |fun| to each item in |pq|. The |arg| is passed as arg
- * parameter to callback function. This function must not change the
- * ordering key. If the return value from callback is nonzero, this
- * function returns 1 immediately without iterating remaining items.
- * Otherwise this function returns 0.
- */
-int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg);
-
-/*
- * Removes |item| from priority queue.
- */
-void nghttp3_pq_remove(nghttp3_pq *pq, nghttp3_pq_entry *item);
-
-void nghttp3_pq_clear(nghttp3_pq *pq);
-
-#endif /* NGHTTP3_PQ_H */
diff --git a/deps/nghttp3/lib/nghttp3_qpack.c b/deps/nghttp3/lib/nghttp3_qpack.c
deleted file mode 100644
index d74e29f6fe..0000000000
--- a/deps/nghttp3/lib/nghttp3_qpack.c
+++ /dev/null
@@ -1,4096 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_qpack.h"
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "nghttp3_str.h"
-#include "nghttp3_macro.h"
-#include "nghttp3_debug.h"
-
-/* NGHTTP3_QPACK_MAX_QPACK_STREAMS is the maximum number of concurrent
- nghttp3_qpack_stream object to handle a client which never cancel
- or acknowledge header block. After this limit, encoder stops using
- dynamic table. */
-#define NGHTTP3_QPACK_MAX_QPACK_STREAMS 2000
-
-/* Make scalar initialization form of nghttp3_qpack_static_entry */
-#define MAKE_STATIC_ENT(I, T, H) \
- { I, T, H }
-
-/* Generated by mkstatichdtbl.py */
-static nghttp3_qpack_static_entry token_stable[] = {
- MAKE_STATIC_ENT(0, NGHTTP3_QPACK_TOKEN__AUTHORITY, 3153725150u),
- MAKE_STATIC_ENT(15, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(16, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(17, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(18, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(19, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(20, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(21, NGHTTP3_QPACK_TOKEN__METHOD, 695666056u),
- MAKE_STATIC_ENT(1, NGHTTP3_QPACK_TOKEN__PATH, 3292848686u),
- MAKE_STATIC_ENT(22, NGHTTP3_QPACK_TOKEN__SCHEME, 2510477674u),
- MAKE_STATIC_ENT(23, NGHTTP3_QPACK_TOKEN__SCHEME, 2510477674u),
- MAKE_STATIC_ENT(24, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(25, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(26, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(27, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(28, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(63, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(64, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(65, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(66, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(67, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(68, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(69, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(70, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(71, NGHTTP3_QPACK_TOKEN__STATUS, 4000288983u),
- MAKE_STATIC_ENT(29, NGHTTP3_QPACK_TOKEN_ACCEPT, 136609321u),
- MAKE_STATIC_ENT(30, NGHTTP3_QPACK_TOKEN_ACCEPT, 136609321u),
- MAKE_STATIC_ENT(31, NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING, 3379649177u),
- MAKE_STATIC_ENT(72, NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE, 1979086614u),
- MAKE_STATIC_ENT(32, NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES, 1713753958u),
- MAKE_STATIC_ENT(73, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS,
- 901040780u),
- MAKE_STATIC_ENT(74, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS,
- 901040780u),
- MAKE_STATIC_ENT(33, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
- 1524311232u),
- MAKE_STATIC_ENT(34, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
- 1524311232u),
- MAKE_STATIC_ENT(75, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
- 1524311232u),
- MAKE_STATIC_ENT(76, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
- 2175229868u),
- MAKE_STATIC_ENT(77, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
- 2175229868u),
- MAKE_STATIC_ENT(78, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
- 2175229868u),
- MAKE_STATIC_ENT(35, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN,
- 2710797292u),
- MAKE_STATIC_ENT(79, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS,
- 2449824425u),
- MAKE_STATIC_ENT(80, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS,
- 3599549072u),
- MAKE_STATIC_ENT(81, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD,
- 2417078055u),
- MAKE_STATIC_ENT(82, NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD,
- 2417078055u),
- MAKE_STATIC_ENT(2, NGHTTP3_QPACK_TOKEN_AGE, 742476188u),
- MAKE_STATIC_ENT(83, NGHTTP3_QPACK_TOKEN_ALT_SVC, 2148877059u),
- MAKE_STATIC_ENT(84, NGHTTP3_QPACK_TOKEN_AUTHORIZATION, 2436257726u),
- MAKE_STATIC_ENT(36, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(37, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(38, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(39, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(40, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(41, NGHTTP3_QPACK_TOKEN_CACHE_CONTROL, 1355326669u),
- MAKE_STATIC_ENT(3, NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION, 3889184348u),
- MAKE_STATIC_ENT(42, NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING, 65203592u),
- MAKE_STATIC_ENT(43, NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING, 65203592u),
- MAKE_STATIC_ENT(4, NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH, 1308181789u),
- MAKE_STATIC_ENT(85, NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY,
- 1569039836u),
- MAKE_STATIC_ENT(44, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(45, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(46, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(47, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(48, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(49, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(50, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(51, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(52, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(53, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(54, NGHTTP3_QPACK_TOKEN_CONTENT_TYPE, 4244048277u),
- MAKE_STATIC_ENT(5, NGHTTP3_QPACK_TOKEN_COOKIE, 2007449791u),
- MAKE_STATIC_ENT(6, NGHTTP3_QPACK_TOKEN_DATE, 3564297305u),
- MAKE_STATIC_ENT(86, NGHTTP3_QPACK_TOKEN_EARLY_DATA, 4080895051u),
- MAKE_STATIC_ENT(7, NGHTTP3_QPACK_TOKEN_ETAG, 113792960u),
- MAKE_STATIC_ENT(87, NGHTTP3_QPACK_TOKEN_EXPECT_CT, 1183214960u),
- MAKE_STATIC_ENT(88, NGHTTP3_QPACK_TOKEN_FORWARDED, 1485178027u),
- MAKE_STATIC_ENT(8, NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE, 2213050793u),
- MAKE_STATIC_ENT(9, NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH, 2536202615u),
- MAKE_STATIC_ENT(89, NGHTTP3_QPACK_TOKEN_IF_RANGE, 2340978238u),
- MAKE_STATIC_ENT(10, NGHTTP3_QPACK_TOKEN_LAST_MODIFIED, 3226950251u),
- MAKE_STATIC_ENT(11, NGHTTP3_QPACK_TOKEN_LINK, 232457833u),
- MAKE_STATIC_ENT(12, NGHTTP3_QPACK_TOKEN_LOCATION, 200649126u),
- MAKE_STATIC_ENT(90, NGHTTP3_QPACK_TOKEN_ORIGIN, 3649018447u),
- MAKE_STATIC_ENT(91, NGHTTP3_QPACK_TOKEN_PURPOSE, 4212263681u),
- MAKE_STATIC_ENT(55, NGHTTP3_QPACK_TOKEN_RANGE, 4208725202u),
- MAKE_STATIC_ENT(13, NGHTTP3_QPACK_TOKEN_REFERER, 3969579366u),
- MAKE_STATIC_ENT(92, NGHTTP3_QPACK_TOKEN_SERVER, 1085029842u),
- MAKE_STATIC_ENT(14, NGHTTP3_QPACK_TOKEN_SET_COOKIE, 1848371000u),
- MAKE_STATIC_ENT(56, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
- 4138147361u),
- MAKE_STATIC_ENT(57, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
- 4138147361u),
- MAKE_STATIC_ENT(58, NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY,
- 4138147361u),
- MAKE_STATIC_ENT(93, NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN, 2432297564u),
- MAKE_STATIC_ENT(94, NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS,
- 2479169413u),
- MAKE_STATIC_ENT(95, NGHTTP3_QPACK_TOKEN_USER_AGENT, 606444526u),
- MAKE_STATIC_ENT(59, NGHTTP3_QPACK_TOKEN_VARY, 1085005381u),
- MAKE_STATIC_ENT(60, NGHTTP3_QPACK_TOKEN_VARY, 1085005381u),
- MAKE_STATIC_ENT(61, NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS,
- 3644557769u),
- MAKE_STATIC_ENT(96, NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR, 2914187656u),
- MAKE_STATIC_ENT(97, NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS, 3993834824u),
- MAKE_STATIC_ENT(98, NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS, 3993834824u),
- MAKE_STATIC_ENT(62, NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION, 2501058888u),
-};
-
-/* Make scalar initialization form of nghttp3_qpack_static_entry */
-#define MAKE_STATIC_HD(N, V, T) \
- { \
- {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
- {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, T \
- }
-
-static nghttp3_qpack_static_header stable[] = {
- MAKE_STATIC_HD(":authority", "", NGHTTP3_QPACK_TOKEN__AUTHORITY),
- MAKE_STATIC_HD(":path", "/", NGHTTP3_QPACK_TOKEN__PATH),
- MAKE_STATIC_HD("age", "0", NGHTTP3_QPACK_TOKEN_AGE),
- MAKE_STATIC_HD("content-disposition", "",
- NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION),
- MAKE_STATIC_HD("content-length", "0", NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH),
- MAKE_STATIC_HD("cookie", "", NGHTTP3_QPACK_TOKEN_COOKIE),
- MAKE_STATIC_HD("date", "", NGHTTP3_QPACK_TOKEN_DATE),
- MAKE_STATIC_HD("etag", "", NGHTTP3_QPACK_TOKEN_ETAG),
- MAKE_STATIC_HD("if-modified-since", "",
- NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE),
- MAKE_STATIC_HD("if-none-match", "", NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH),
- MAKE_STATIC_HD("last-modified", "", NGHTTP3_QPACK_TOKEN_LAST_MODIFIED),
- MAKE_STATIC_HD("link", "", NGHTTP3_QPACK_TOKEN_LINK),
- MAKE_STATIC_HD("location", "", NGHTTP3_QPACK_TOKEN_LOCATION),
- MAKE_STATIC_HD("referer", "", NGHTTP3_QPACK_TOKEN_REFERER),
- MAKE_STATIC_HD("set-cookie", "", NGHTTP3_QPACK_TOKEN_SET_COOKIE),
- MAKE_STATIC_HD(":method", "CONNECT", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "DELETE", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "GET", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "HEAD", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "OPTIONS", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "POST", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":method", "PUT", NGHTTP3_QPACK_TOKEN__METHOD),
- MAKE_STATIC_HD(":scheme", "http", NGHTTP3_QPACK_TOKEN__SCHEME),
- MAKE_STATIC_HD(":scheme", "https", NGHTTP3_QPACK_TOKEN__SCHEME),
- MAKE_STATIC_HD(":status", "103", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "200", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "304", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "404", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "503", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD("accept", "*/*", NGHTTP3_QPACK_TOKEN_ACCEPT),
- MAKE_STATIC_HD("accept", "application/dns-message",
- NGHTTP3_QPACK_TOKEN_ACCEPT),
- MAKE_STATIC_HD("accept-encoding", "gzip, deflate, br",
- NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING),
- MAKE_STATIC_HD("accept-ranges", "bytes", NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES),
- MAKE_STATIC_HD("access-control-allow-headers", "cache-control",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
- MAKE_STATIC_HD("access-control-allow-headers", "content-type",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
- MAKE_STATIC_HD("access-control-allow-origin", "*",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN),
- MAKE_STATIC_HD("cache-control", "max-age=0",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("cache-control", "max-age=2592000",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("cache-control", "max-age=604800",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("cache-control", "no-cache",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("cache-control", "no-store",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("cache-control", "public, max-age=31536000",
- NGHTTP3_QPACK_TOKEN_CACHE_CONTROL),
- MAKE_STATIC_HD("content-encoding", "br",
- NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING),
- MAKE_STATIC_HD("content-encoding", "gzip",
- NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING),
- MAKE_STATIC_HD("content-type", "application/dns-message",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "application/javascript",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "application/json",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "application/x-www-form-urlencoded",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "image/gif",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "image/jpeg",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "image/png",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "text/css",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "text/html; charset=utf-8",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "text/plain",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("content-type", "text/plain;charset=utf-8",
- NGHTTP3_QPACK_TOKEN_CONTENT_TYPE),
- MAKE_STATIC_HD("range", "bytes=0-", NGHTTP3_QPACK_TOKEN_RANGE),
- MAKE_STATIC_HD("strict-transport-security", "max-age=31536000",
- NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
- MAKE_STATIC_HD("strict-transport-security",
- "max-age=31536000; includesubdomains",
- NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
- MAKE_STATIC_HD("strict-transport-security",
- "max-age=31536000; includesubdomains; preload",
- NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY),
- MAKE_STATIC_HD("vary", "accept-encoding", NGHTTP3_QPACK_TOKEN_VARY),
- MAKE_STATIC_HD("vary", "origin", NGHTTP3_QPACK_TOKEN_VARY),
- MAKE_STATIC_HD("x-content-type-options", "nosniff",
- NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS),
- MAKE_STATIC_HD("x-xss-protection", "1; mode=block",
- NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION),
- MAKE_STATIC_HD(":status", "100", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "204", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "206", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "302", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "400", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "403", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "421", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "425", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD(":status", "500", NGHTTP3_QPACK_TOKEN__STATUS),
- MAKE_STATIC_HD("accept-language", "", NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE),
- MAKE_STATIC_HD("access-control-allow-credentials", "FALSE",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS),
- MAKE_STATIC_HD("access-control-allow-credentials", "TRUE",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS),
- MAKE_STATIC_HD("access-control-allow-headers", "*",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS),
- MAKE_STATIC_HD("access-control-allow-methods", "get",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
- MAKE_STATIC_HD("access-control-allow-methods", "get, post, options",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
- MAKE_STATIC_HD("access-control-allow-methods", "options",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS),
- MAKE_STATIC_HD("access-control-expose-headers", "content-length",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS),
- MAKE_STATIC_HD("access-control-request-headers", "content-type",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS),
- MAKE_STATIC_HD("access-control-request-method", "get",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD),
- MAKE_STATIC_HD("access-control-request-method", "post",
- NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD),
- MAKE_STATIC_HD("alt-svc", "clear", NGHTTP3_QPACK_TOKEN_ALT_SVC),
- MAKE_STATIC_HD("authorization", "", NGHTTP3_QPACK_TOKEN_AUTHORIZATION),
- MAKE_STATIC_HD("content-security-policy",
- "script-src 'none'; object-src 'none'; base-uri 'none'",
- NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY),
- MAKE_STATIC_HD("early-data", "1", NGHTTP3_QPACK_TOKEN_EARLY_DATA),
- MAKE_STATIC_HD("expect-ct", "", NGHTTP3_QPACK_TOKEN_EXPECT_CT),
- MAKE_STATIC_HD("forwarded", "", NGHTTP3_QPACK_TOKEN_FORWARDED),
- MAKE_STATIC_HD("if-range", "", NGHTTP3_QPACK_TOKEN_IF_RANGE),
- MAKE_STATIC_HD("origin", "", NGHTTP3_QPACK_TOKEN_ORIGIN),
- MAKE_STATIC_HD("purpose", "prefetch", NGHTTP3_QPACK_TOKEN_PURPOSE),
- MAKE_STATIC_HD("server", "", NGHTTP3_QPACK_TOKEN_SERVER),
- MAKE_STATIC_HD("timing-allow-origin", "*",
- NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN),
- MAKE_STATIC_HD("upgrade-insecure-requests", "1",
- NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS),
- MAKE_STATIC_HD("user-agent", "", NGHTTP3_QPACK_TOKEN_USER_AGENT),
- MAKE_STATIC_HD("x-forwarded-for", "", NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR),
- MAKE_STATIC_HD("x-frame-options", "deny",
- NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS),
- MAKE_STATIC_HD("x-frame-options", "sameorigin",
- NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS),
-};
-
-static int memeq(const void *s1, const void *s2, size_t n) {
- return n == 0 || memcmp(s1, s2, n) == 0;
-}
-
-/* Generated by genlibtokenlookup.py */
-static int32_t qpack_lookup_token(const uint8_t *name, size_t namelen) {
- switch (namelen) {
- case 2:
- switch (name[1]) {
- case 'e':
- if (memeq("t", name, 1)) {
- return NGHTTP3_QPACK_TOKEN_TE;
- }
- break;
- }
- break;
- case 3:
- switch (name[2]) {
- case 'e':
- if (memeq("ag", name, 2)) {
- return NGHTTP3_QPACK_TOKEN_AGE;
- }
- break;
- }
- break;
- case 4:
- switch (name[3]) {
- case 'e':
- if (memeq("dat", name, 3)) {
- return NGHTTP3_QPACK_TOKEN_DATE;
- }
- break;
- case 'g':
- if (memeq("eta", name, 3)) {
- return NGHTTP3_QPACK_TOKEN_ETAG;
- }
- break;
- case 'k':
- if (memeq("lin", name, 3)) {
- return NGHTTP3_QPACK_TOKEN_LINK;
- }
- break;
- case 't':
- if (memeq("hos", name, 3)) {
- return NGHTTP3_QPACK_TOKEN_HOST;
- }
- break;
- case 'y':
- if (memeq("var", name, 3)) {
- return NGHTTP3_QPACK_TOKEN_VARY;
- }
- break;
- }
- break;
- case 5:
- switch (name[4]) {
- case 'e':
- if (memeq("rang", name, 4)) {
- return NGHTTP3_QPACK_TOKEN_RANGE;
- }
- break;
- case 'h':
- if (memeq(":pat", name, 4)) {
- return NGHTTP3_QPACK_TOKEN__PATH;
- }
- break;
- }
- break;
- case 6:
- switch (name[5]) {
- case 'e':
- if (memeq("cooki", name, 5)) {
- return NGHTTP3_QPACK_TOKEN_COOKIE;
- }
- break;
- case 'n':
- if (memeq("origi", name, 5)) {
- return NGHTTP3_QPACK_TOKEN_ORIGIN;
- }
- break;
- case 'r':
- if (memeq("serve", name, 5)) {
- return NGHTTP3_QPACK_TOKEN_SERVER;
- }
- break;
- case 't':
- if (memeq("accep", name, 5)) {
- return NGHTTP3_QPACK_TOKEN_ACCEPT;
- }
- break;
- }
- break;
- case 7:
- switch (name[6]) {
- case 'c':
- if (memeq("alt-sv", name, 6)) {
- return NGHTTP3_QPACK_TOKEN_ALT_SVC;
- }
- break;
- case 'd':
- if (memeq(":metho", name, 6)) {
- return NGHTTP3_QPACK_TOKEN__METHOD;
- }
- break;
- case 'e':
- if (memeq(":schem", name, 6)) {
- return NGHTTP3_QPACK_TOKEN__SCHEME;
- }
- if (memeq("purpos", name, 6)) {
- return NGHTTP3_QPACK_TOKEN_PURPOSE;
- }
- if (memeq("upgrad", name, 6)) {
- return NGHTTP3_QPACK_TOKEN_UPGRADE;
- }
- break;
- case 'r':
- if (memeq("refere", name, 6)) {
- return NGHTTP3_QPACK_TOKEN_REFERER;
- }
- break;
- case 's':
- if (memeq(":statu", name, 6)) {
- return NGHTTP3_QPACK_TOKEN__STATUS;
- }
- break;
- }
- break;
- case 8:
- switch (name[7]) {
- case 'e':
- if (memeq("if-rang", name, 7)) {
- return NGHTTP3_QPACK_TOKEN_IF_RANGE;
- }
- break;
- case 'n':
- if (memeq("locatio", name, 7)) {
- return NGHTTP3_QPACK_TOKEN_LOCATION;
- }
- break;
- case 'y':
- if (memeq("priorit", name, 7)) {
- return NGHTTP3_QPACK_TOKEN_PRIORITY;
- }
- break;
- }
- break;
- case 9:
- switch (name[8]) {
- case 'd':
- if (memeq("forwarde", name, 8)) {
- return NGHTTP3_QPACK_TOKEN_FORWARDED;
- }
- break;
- case 'l':
- if (memeq(":protoco", name, 8)) {
- return NGHTTP3_QPACK_TOKEN__PROTOCOL;
- }
- break;
- case 't':
- if (memeq("expect-c", name, 8)) {
- return NGHTTP3_QPACK_TOKEN_EXPECT_CT;
- }
- break;
- }
- break;
- case 10:
- switch (name[9]) {
- case 'a':
- if (memeq("early-dat", name, 9)) {
- return NGHTTP3_QPACK_TOKEN_EARLY_DATA;
- }
- break;
- case 'e':
- if (memeq("keep-aliv", name, 9)) {
- return NGHTTP3_QPACK_TOKEN_KEEP_ALIVE;
- }
- if (memeq("set-cooki", name, 9)) {
- return NGHTTP3_QPACK_TOKEN_SET_COOKIE;
- }
- break;
- case 'n':
- if (memeq("connectio", name, 9)) {
- return NGHTTP3_QPACK_TOKEN_CONNECTION;
- }
- break;
- case 't':
- if (memeq("user-agen", name, 9)) {
- return NGHTTP3_QPACK_TOKEN_USER_AGENT;
- }
- break;
- case 'y':
- if (memeq(":authorit", name, 9)) {
- return NGHTTP3_QPACK_TOKEN__AUTHORITY;
- }
- break;
- }
- break;
- case 12:
- switch (name[11]) {
- case 'e':
- if (memeq("content-typ", name, 11)) {
- return NGHTTP3_QPACK_TOKEN_CONTENT_TYPE;
- }
- break;
- }
- break;
- case 13:
- switch (name[12]) {
- case 'd':
- if (memeq("last-modifie", name, 12)) {
- return NGHTTP3_QPACK_TOKEN_LAST_MODIFIED;
- }
- break;
- case 'h':
- if (memeq("if-none-matc", name, 12)) {
- return NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH;
- }
- break;
- case 'l':
- if (memeq("cache-contro", name, 12)) {
- return NGHTTP3_QPACK_TOKEN_CACHE_CONTROL;
- }
- break;
- case 'n':
- if (memeq("authorizatio", name, 12)) {
- return NGHTTP3_QPACK_TOKEN_AUTHORIZATION;
- }
- break;
- case 's':
- if (memeq("accept-range", name, 12)) {
- return NGHTTP3_QPACK_TOKEN_ACCEPT_RANGES;
- }
- break;
- }
- break;
- case 14:
- switch (name[13]) {
- case 'h':
- if (memeq("content-lengt", name, 13)) {
- return NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH;
- }
- break;
- }
- break;
- case 15:
- switch (name[14]) {
- case 'e':
- if (memeq("accept-languag", name, 14)) {
- return NGHTTP3_QPACK_TOKEN_ACCEPT_LANGUAGE;
- }
- break;
- case 'g':
- if (memeq("accept-encodin", name, 14)) {
- return NGHTTP3_QPACK_TOKEN_ACCEPT_ENCODING;
- }
- break;
- case 'r':
- if (memeq("x-forwarded-fo", name, 14)) {
- return NGHTTP3_QPACK_TOKEN_X_FORWARDED_FOR;
- }
- break;
- case 's':
- if (memeq("x-frame-option", name, 14)) {
- return NGHTTP3_QPACK_TOKEN_X_FRAME_OPTIONS;
- }
- break;
- }
- break;
- case 16:
- switch (name[15]) {
- case 'g':
- if (memeq("content-encodin", name, 15)) {
- return NGHTTP3_QPACK_TOKEN_CONTENT_ENCODING;
- }
- break;
- case 'n':
- if (memeq("proxy-connectio", name, 15)) {
- return NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION;
- }
- if (memeq("x-xss-protectio", name, 15)) {
- return NGHTTP3_QPACK_TOKEN_X_XSS_PROTECTION;
- }
- break;
- }
- break;
- case 17:
- switch (name[16]) {
- case 'e':
- if (memeq("if-modified-sinc", name, 16)) {
- return NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE;
- }
- break;
- case 'g':
- if (memeq("transfer-encodin", name, 16)) {
- return NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING;
- }
- break;
- }
- break;
- case 19:
- switch (name[18]) {
- case 'n':
- if (memeq("content-dispositio", name, 18)) {
- return NGHTTP3_QPACK_TOKEN_CONTENT_DISPOSITION;
- }
- if (memeq("timing-allow-origi", name, 18)) {
- return NGHTTP3_QPACK_TOKEN_TIMING_ALLOW_ORIGIN;
- }
- break;
- }
- break;
- case 22:
- switch (name[21]) {
- case 's':
- if (memeq("x-content-type-option", name, 21)) {
- return NGHTTP3_QPACK_TOKEN_X_CONTENT_TYPE_OPTIONS;
- }
- break;
- }
- break;
- case 23:
- switch (name[22]) {
- case 'y':
- if (memeq("content-security-polic", name, 22)) {
- return NGHTTP3_QPACK_TOKEN_CONTENT_SECURITY_POLICY;
- }
- break;
- }
- break;
- case 25:
- switch (name[24]) {
- case 's':
- if (memeq("upgrade-insecure-request", name, 24)) {
- return NGHTTP3_QPACK_TOKEN_UPGRADE_INSECURE_REQUESTS;
- }
- break;
- case 'y':
- if (memeq("strict-transport-securit", name, 24)) {
- return NGHTTP3_QPACK_TOKEN_STRICT_TRANSPORT_SECURITY;
- }
- break;
- }
- break;
- case 27:
- switch (name[26]) {
- case 'n':
- if (memeq("access-control-allow-origi", name, 26)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
- }
- break;
- }
- break;
- case 28:
- switch (name[27]) {
- case 's':
- if (memeq("access-control-allow-header", name, 27)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS;
- }
- if (memeq("access-control-allow-method", name, 27)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_METHODS;
- }
- break;
- }
- break;
- case 29:
- switch (name[28]) {
- case 'd':
- if (memeq("access-control-request-metho", name, 28)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_METHOD;
- }
- break;
- case 's':
- if (memeq("access-control-expose-header", name, 28)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS;
- }
- break;
- }
- break;
- case 30:
- switch (name[29]) {
- case 's':
- if (memeq("access-control-request-header", name, 29)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS;
- }
- break;
- }
- break;
- case 32:
- switch (name[31]) {
- case 's':
- if (memeq("access-control-allow-credential", name, 31)) {
- return NGHTTP3_QPACK_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS;
- }
- break;
- }
- break;
- }
- return -1;
-}
-
-static size_t table_space(size_t namelen, size_t valuelen) {
- return NGHTTP3_QPACK_ENTRY_OVERHEAD + namelen + valuelen;
-}
-
-static int qpack_nv_name_eq(const nghttp3_qpack_nv *a, const nghttp3_nv *b) {
- return a->name->len == b->namelen &&
- memeq(a->name->base, b->name, b->namelen);
-}
-
-static int qpack_nv_value_eq(const nghttp3_qpack_nv *a, const nghttp3_nv *b) {
- return a->value->len == b->valuelen &&
- memeq(a->value->base, b->value, b->valuelen);
-}
-
-static void qpack_map_init(nghttp3_qpack_map *map) {
- memset(map, 0, sizeof(nghttp3_qpack_map));
-}
-
-static void qpack_map_insert(nghttp3_qpack_map *map, nghttp3_qpack_entry *ent) {
- nghttp3_qpack_entry **bucket;
-
- bucket = &map->table[ent->hash & (NGHTTP3_QPACK_MAP_SIZE - 1)];
-
- if (*bucket == NULL) {
- *bucket = ent;
- return;
- }
-
- /* larger absidx is linked near the root */
- ent->map_next = *bucket;
- *bucket = ent;
-}
-
-static void qpack_map_remove(nghttp3_qpack_map *map, nghttp3_qpack_entry *ent) {
- nghttp3_qpack_entry **dst;
-
- dst = &map->table[ent->hash & (NGHTTP3_QPACK_MAP_SIZE - 1)];
-
- for (; *dst; dst = &(*dst)->map_next) {
- if (*dst != ent) {
- continue;
- }
-
- *dst = ent->map_next;
- ent->map_next = NULL;
- return;
- }
-}
-
-/*
- * qpack_context_can_reference returns nonzero if dynamic table entry
- * at |absidx| can be referenced. In other words, it is within
- * ctx->max_dtable_size.
- */
-static int qpack_context_can_reference(nghttp3_qpack_context *ctx,
- uint64_t absidx) {
- nghttp3_qpack_entry *ent = nghttp3_qpack_context_dtable_get(ctx, absidx);
- return ctx->dtable_sum - ent->sum <= ctx->max_dtable_size;
-}
-
-/* |*ppb_match| (post-base match), if it is not NULL, is always exact
- match. */
-static void encoder_qpack_map_find(nghttp3_qpack_encoder *encoder,
- int *exact_match,
- nghttp3_qpack_entry **pmatch,
- nghttp3_qpack_entry **ppb_match,
- const nghttp3_nv *nv, int32_t token,
- uint32_t hash, uint64_t krcnt,
- int allow_blocking, int name_only) {
- nghttp3_qpack_entry *p;
-
- *exact_match = 0;
- *pmatch = NULL;
- *ppb_match = NULL;
-
- for (p = encoder->dtable_map.table[hash & (NGHTTP3_QPACK_MAP_SIZE - 1)]; p;
- p = p->map_next) {
- if (token != p->nv.token ||
- (token == -1 && (hash != p->hash || !qpack_nv_name_eq(&p->nv, nv))) ||
- !qpack_context_can_reference(&encoder->ctx, p->absidx)) {
- continue;
- }
- if (allow_blocking || p->absidx + 1 <= krcnt) {
- if (!*pmatch) {
- *pmatch = p;
- if (name_only) {
- return;
- }
- }
- if (qpack_nv_value_eq(&p->nv, nv)) {
- *pmatch = p;
- *exact_match = 1;
- return;
- }
- } else if (!*ppb_match && qpack_nv_value_eq(&p->nv, nv)) {
- *ppb_match = p;
- }
- }
-}
-
-/*
- * qpack_context_init initializes |ctx|. |max_dtable_size| is the
- * maximum size of dynamic table. |mem| is a memory allocator.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int qpack_context_init(nghttp3_qpack_context *ctx,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem) {
- int rv;
- size_t len = 4096 / NGHTTP3_QPACK_ENTRY_OVERHEAD;
- size_t len2;
-
- for (len2 = 1; len2 < len; len2 <<= 1)
- ;
-
- rv = nghttp3_ringbuf_init(&ctx->dtable, len2, sizeof(nghttp3_qpack_entry *),
- mem);
- if (rv != 0) {
- return rv;
- }
-
- ctx->mem = mem;
- ctx->dtable_size = 0;
- ctx->dtable_sum = 0;
- ctx->hard_max_dtable_size = max_dtable_size;
- ctx->max_dtable_size = 0;
- ctx->max_blocked = max_blocked;
- ctx->next_absidx = 0;
- ctx->bad = 0;
-
- return 0;
-}
-
-static void qpack_context_free(nghttp3_qpack_context *ctx) {
- nghttp3_qpack_entry *ent;
- size_t i, len = nghttp3_ringbuf_len(&ctx->dtable);
-
- for (i = 0; i < len; ++i) {
- ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i);
- nghttp3_qpack_entry_free(ent);
- nghttp3_mem_free(ctx->mem, ent);
- }
- nghttp3_ringbuf_free(&ctx->dtable);
-}
-
-static int ref_min_cnt_less(const nghttp3_pq_entry *lhsx,
- const nghttp3_pq_entry *rhsx) {
- nghttp3_qpack_header_block_ref *lhs =
- nghttp3_struct_of(lhsx, nghttp3_qpack_header_block_ref, min_cnts_pe);
- nghttp3_qpack_header_block_ref *rhs =
- nghttp3_struct_of(rhsx, nghttp3_qpack_header_block_ref, min_cnts_pe);
-
- return lhs->min_cnt < rhs->min_cnt;
-}
-
-typedef struct {
- uint64_t max_cnt;
- uint64_t id;
-} nghttp3_blocked_streams_key;
-
-static int max_cnt_greater(const nghttp3_ksl_key *lhs,
- const nghttp3_ksl_key *rhs) {
- const nghttp3_blocked_streams_key *a = lhs;
- const nghttp3_blocked_streams_key *b = rhs;
- return a->max_cnt > b->max_cnt || (a->max_cnt == b->max_cnt && a->id < b->id);
-}
-
-int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem) {
- int rv;
-
- rv = qpack_context_init(&encoder->ctx, max_dtable_size, max_blocked, mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_map_init(&encoder->streams, mem);
- if (rv != 0) {
- goto streams_init_fail;
- }
-
- rv = nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater,
- sizeof(nghttp3_blocked_streams_key), mem);
- if (rv != 0) {
- goto blocked_streams_init_fail;
- }
-
- qpack_map_init(&encoder->dtable_map);
- nghttp3_pq_init(&encoder->min_cnts, ref_min_cnt_less, mem);
-
- encoder->krcnt = 0;
- encoder->state = NGHTTP3_QPACK_DS_STATE_OPCODE;
- encoder->opcode = 0;
- encoder->min_dtable_update = SIZE_MAX;
- encoder->last_max_dtable_update = 0;
- encoder->flags = NGHTTP3_QPACK_ENCODER_FLAG_NONE;
-
- nghttp3_qpack_read_state_reset(&encoder->rstate);
-
- return 0;
-
-blocked_streams_init_fail:
- nghttp3_map_free(&encoder->streams);
-streams_init_fail:
- qpack_context_free(&encoder->ctx);
-
- return rv;
-}
-
-static int map_stream_free(nghttp3_map_entry *entry, void *ptr) {
- const nghttp3_mem *mem = ptr;
- nghttp3_qpack_stream *stream =
- nghttp3_struct_of(entry, nghttp3_qpack_stream, me);
- nghttp3_qpack_stream_del(stream, mem);
- return 0;
-}
-
-void nghttp3_qpack_encoder_free(nghttp3_qpack_encoder *encoder) {
- nghttp3_pq_free(&encoder->min_cnts);
- nghttp3_ksl_free(&encoder->blocked_streams);
- nghttp3_map_each_free(&encoder->streams, map_stream_free,
- (void *)encoder->ctx.mem);
- nghttp3_map_free(&encoder->streams);
- qpack_context_free(&encoder->ctx);
-}
-
-int nghttp3_qpack_encoder_set_max_dtable_size(nghttp3_qpack_encoder *encoder,
- size_t max_dtable_size) {
- if (encoder->ctx.hard_max_dtable_size < max_dtable_size) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- if (encoder->ctx.max_dtable_size == max_dtable_size) {
- return 0;
- }
-
- encoder->flags |= NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP;
-
- if (encoder->min_dtable_update > max_dtable_size) {
- encoder->min_dtable_update = max_dtable_size;
- encoder->ctx.max_dtable_size = max_dtable_size;
- }
- encoder->last_max_dtable_update = max_dtable_size;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_set_hard_max_dtable_size(
- nghttp3_qpack_encoder *encoder, size_t hard_max_dtable_size) {
- /* TODO This is not ideal. */
- if (encoder->ctx.hard_max_dtable_size) {
- return NGHTTP3_ERR_INVALID_STATE;
- }
-
- encoder->ctx.hard_max_dtable_size = hard_max_dtable_size;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_set_max_blocked(nghttp3_qpack_encoder *encoder,
- size_t max_blocked) {
- /* TODO This is not ideal. */
- if (encoder->ctx.max_blocked) {
- return NGHTTP3_ERR_INVALID_STATE;
- }
-
- encoder->ctx.max_blocked = max_blocked;
-
- return 0;
-}
-
-uint64_t nghttp3_qpack_encoder_get_min_cnt(nghttp3_qpack_encoder *encoder) {
- assert(!nghttp3_pq_empty(&encoder->min_cnts));
-
- return nghttp3_struct_of(nghttp3_pq_top(&encoder->min_cnts),
- nghttp3_qpack_header_block_ref, min_cnts_pe)
- ->min_cnt;
-}
-
-void nghttp3_qpack_encoder_shrink_dtable(nghttp3_qpack_encoder *encoder) {
- nghttp3_ringbuf *dtable = &encoder->ctx.dtable;
- const nghttp3_mem *mem = encoder->ctx.mem;
- uint64_t min_cnt = UINT64_MAX;
- size_t len;
- nghttp3_qpack_entry *ent;
-
- if (encoder->ctx.dtable_size <= encoder->ctx.max_dtable_size) {
- return;
- }
-
- if (!nghttp3_pq_empty(&encoder->min_cnts)) {
- min_cnt = nghttp3_qpack_encoder_get_min_cnt(encoder);
- }
-
- for (; encoder->ctx.dtable_size > encoder->ctx.max_dtable_size;) {
- len = nghttp3_ringbuf_len(dtable);
- ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(dtable, len - 1);
- if (ent->absidx + 1 == min_cnt) {
- return;
- }
-
- encoder->ctx.dtable_size -=
- table_space(ent->nv.name->len, ent->nv.value->len);
-
- nghttp3_ringbuf_pop_back(dtable);
- qpack_map_remove(&encoder->dtable_map, ent);
-
- nghttp3_qpack_entry_free(ent);
- nghttp3_mem_free(mem, ent);
- }
-}
-
-/*
- * qpack_encoder_add_stream_ref adds another dynamic table reference
- * to a stream denoted by |stream_id|. |stream| must be NULL if no
- * stream object is not found for the given stream ID. |max_cnt| and
- * |min_cnt| is the maximum and minimum insert count it references
- * respectively.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int qpack_encoder_add_stream_ref(nghttp3_qpack_encoder *encoder,
- int64_t stream_id,
- nghttp3_qpack_stream *stream,
- uint64_t max_cnt, uint64_t min_cnt) {
- nghttp3_qpack_header_block_ref *ref;
- const nghttp3_mem *mem = encoder->ctx.mem;
- uint64_t prev_max_cnt = 0;
- int rv;
-
- if (stream == NULL) {
- rv = nghttp3_qpack_stream_new(&stream, stream_id, mem);
- if (rv != 0) {
- assert(rv == NGHTTP3_ERR_NOMEM);
- return rv;
- }
- rv = nghttp3_map_insert(&encoder->streams, &stream->me);
- if (rv != 0) {
- assert(rv == NGHTTP3_ERR_NOMEM);
- nghttp3_qpack_stream_del(stream, mem);
- return rv;
- }
- } else {
- prev_max_cnt = nghttp3_qpack_stream_get_max_cnt(stream);
- if (nghttp3_qpack_encoder_stream_is_blocked(encoder, stream) &&
- max_cnt > prev_max_cnt) {
- nghttp3_qpack_encoder_unblock_stream(encoder, stream);
- }
- }
-
- rv = nghttp3_qpack_header_block_ref_new(&ref, max_cnt, min_cnt, mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_qpack_stream_add_ref(stream, ref);
- if (rv != 0) {
- nghttp3_qpack_header_block_ref_del(ref, mem);
- return rv;
- }
-
- if (max_cnt > prev_max_cnt &&
- nghttp3_qpack_encoder_stream_is_blocked(encoder, stream)) {
- rv = nghttp3_qpack_encoder_block_stream(encoder, stream);
- if (rv != 0) {
- return rv;
- }
- }
-
- return nghttp3_pq_push(&encoder->min_cnts, &ref->min_cnts_pe);
-}
-
-static void qpack_encoder_remove_stream(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream) {
- size_t i, len;
- nghttp3_qpack_header_block_ref *ref;
-
- nghttp3_map_remove(&encoder->streams, stream->me.key);
-
- len = nghttp3_ringbuf_len(&stream->refs);
- for (i = 0; i < len; ++i) {
- ref = *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs,
- i);
-
- assert(ref->min_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
-
- nghttp3_pq_remove(&encoder->min_cnts, &ref->min_cnts_pe);
- }
-}
-
-/*
- * reserve_buf_internal ensures that |buf| contains at least
- * |extra_size| of free space. In other words, if this function
- * succeeds, nghttp2_buf_left(buf) >= extra_size holds. |min_size| is
- * the minimum size of buffer. The allocated buffer has at least
- * |min_size| bytes.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int reserve_buf_internal(nghttp3_buf *buf, size_t extra_size,
- size_t min_size, const nghttp3_mem *mem) {
- size_t left = nghttp3_buf_left(buf);
- size_t n = min_size, need;
-
- if (left >= extra_size) {
- return 0;
- }
-
- need = nghttp3_buf_cap(buf) + extra_size - left;
-
- for (; n < need; n *= 2)
- ;
-
- return nghttp3_buf_reserve(buf, n, mem);
-}
-
-static int reserve_buf_small(nghttp3_buf *buf, size_t extra_size,
- const nghttp3_mem *mem) {
- return reserve_buf_internal(buf, extra_size, 32, mem);
-}
-
-static int reserve_buf(nghttp3_buf *buf, size_t extra_size,
- const nghttp3_mem *mem) {
- return reserve_buf_internal(buf, extra_size, 32, mem);
-}
-
-int nghttp3_qpack_encoder_encode(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *pbuf, nghttp3_buf *rbuf,
- nghttp3_buf *ebuf, int64_t stream_id,
- const nghttp3_nv *nva, size_t nvlen) {
- size_t i;
- uint64_t max_cnt = 0, min_cnt = UINT64_MAX;
- uint64_t base;
- int rv = 0;
- int allow_blocking;
- int blocked_stream;
- nghttp3_qpack_stream *stream;
-
- if (encoder->ctx.bad) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- rv = nghttp3_qpack_encoder_process_dtable_update(encoder, ebuf);
- if (rv != 0) {
- goto fail;
- }
-
- base = encoder->ctx.next_absidx;
-
- stream = nghttp3_qpack_encoder_find_stream(encoder, stream_id);
- blocked_stream =
- stream && nghttp3_qpack_encoder_stream_is_blocked(encoder, stream);
- allow_blocking =
- blocked_stream ||
- encoder->ctx.max_blocked > nghttp3_ksl_len(&encoder->blocked_streams);
-
- DEBUGF("qpack::encode: stream %ld blocked=%d allow_blocking=%d\n", stream_id,
- blocked_stream, allow_blocking);
-
- for (i = 0; i < nvlen; ++i) {
- rv = nghttp3_qpack_encoder_encode_nv(encoder, &max_cnt, &min_cnt, rbuf,
- ebuf, &nva[i], base, allow_blocking);
- if (rv != 0) {
- goto fail;
- }
- }
-
- nghttp3_qpack_encoder_write_field_section_prefix(encoder, pbuf, max_cnt,
- base);
-
- /* TODO If max_cnt == 0, no reference is made to dtable. */
- if (!max_cnt) {
- return 0;
- }
-
- rv = qpack_encoder_add_stream_ref(encoder, stream_id, stream, max_cnt,
- min_cnt);
- if (rv != 0) {
- goto fail;
- }
-
- return 0;
-
-fail:
- encoder->ctx.bad = 1;
- return rv;
-}
-
-/*
- * qpack_write_number writes variable integer to |rbuf|. |num| is an
- * integer to write. |prefix| is a prefix of variable integer
- * encoding.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int qpack_write_number(nghttp3_buf *rbuf, uint8_t fb, uint64_t num,
- size_t prefix, const nghttp3_mem *mem) {
- int rv;
- size_t len = nghttp3_qpack_put_varint_len(num, prefix);
- uint8_t *p;
-
- rv = reserve_buf(rbuf, len, mem);
- if (rv != 0) {
- return rv;
- }
-
- p = rbuf->last;
-
- *p = fb;
- p = nghttp3_qpack_put_varint(p, num, prefix);
-
- assert((size_t)(p - rbuf->last) == len);
-
- rbuf->last = p;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_process_dtable_update(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf) {
- int rv;
-
- nghttp3_qpack_encoder_shrink_dtable(encoder);
-
- if (encoder->ctx.max_dtable_size < encoder->ctx.dtable_size ||
- !(encoder->flags & NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP)) {
- return 0;
- }
-
- if (encoder->min_dtable_update < encoder->last_max_dtable_update) {
- rv = nghttp3_qpack_encoder_write_set_dtable_cap(encoder, ebuf,
- encoder->min_dtable_update);
- if (rv != 0) {
- return rv;
- }
- }
-
- rv = nghttp3_qpack_encoder_write_set_dtable_cap(
- encoder, ebuf, encoder->last_max_dtable_update);
- if (rv != 0) {
- return rv;
- }
-
- encoder->flags &= (uint8_t)~NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP;
- encoder->min_dtable_update = SIZE_MAX;
- encoder->ctx.max_dtable_size = encoder->last_max_dtable_update;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_write_set_dtable_cap(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf, size_t cap) {
- DEBUGF("qpack::encode: Set Dynamic Table Capacity capacity=%zu\n", cap);
- return qpack_write_number(ebuf, 0x20, cap, 5, encoder->ctx.mem);
-}
-
-nghttp3_qpack_stream *
-nghttp3_qpack_encoder_find_stream(nghttp3_qpack_encoder *encoder,
- int64_t stream_id) {
- nghttp3_map_entry *me =
- nghttp3_map_find(&encoder->streams, (uint64_t)stream_id);
- return me == NULL ? NULL : nghttp3_struct_of(me, nghttp3_qpack_stream, me);
-}
-
-int nghttp3_qpack_encoder_stream_is_blocked(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream) {
- return stream && encoder->krcnt < nghttp3_qpack_stream_get_max_cnt(stream);
-}
-
-/*
- * qpack_encoder_decide_indexing_mode determines and returns indexing
- * mode for header field |nv|. |token| is a token of header field
- * name.
- */
-static nghttp3_qpack_indexing_mode
-qpack_encoder_decide_indexing_mode(nghttp3_qpack_encoder *encoder,
- const nghttp3_nv *nv, int32_t token) {
- if (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) {
- return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
- }
-
- switch (token) {
- case NGHTTP3_QPACK_TOKEN_AUTHORIZATION:
- return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
- case NGHTTP3_QPACK_TOKEN_COOKIE:
- if (nv->valuelen < 20) {
- return NGHTTP3_QPACK_INDEXING_MODE_NEVER;
- }
- break;
- case -1:
- case NGHTTP3_QPACK_TOKEN__PATH:
- case NGHTTP3_QPACK_TOKEN_AGE:
- case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH:
- case NGHTTP3_QPACK_TOKEN_ETAG:
- case NGHTTP3_QPACK_TOKEN_IF_MODIFIED_SINCE:
- case NGHTTP3_QPACK_TOKEN_IF_NONE_MATCH:
- case NGHTTP3_QPACK_TOKEN_LOCATION:
- case NGHTTP3_QPACK_TOKEN_SET_COOKIE:
- return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
- case NGHTTP3_QPACK_TOKEN_HOST:
- case NGHTTP3_QPACK_TOKEN_TE:
- case NGHTTP3_QPACK_TOKEN__PROTOCOL:
- case NGHTTP3_QPACK_TOKEN_PRIORITY:
- break;
- default:
- if (token >= 1000) {
- return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
- }
- }
-
- if (table_space(nv->namelen, nv->valuelen) >
- encoder->ctx.max_dtable_size * 3 / 4) {
- return NGHTTP3_QPACK_INDEXING_MODE_LITERAL;
- }
-
- return NGHTTP3_QPACK_INDEXING_MODE_STORE;
-}
-
-/*
- * qpack_encoder_can_index returns nonzero if an entry which occupies
- * |need| bytes can be inserted into dynamic table. |min_cnt| is the
- * minimum insert count which blocked stream requires.
- */
-static int qpack_encoder_can_index(nghttp3_qpack_encoder *encoder, size_t need,
- uint64_t min_cnt) {
- size_t avail = 0;
- size_t len;
- uint64_t gmin_cnt;
- nghttp3_qpack_entry *min_ent, *last_ent;
- nghttp3_ringbuf *dtable = &encoder->ctx.dtable;
-
- if (encoder->ctx.max_dtable_size > encoder->ctx.dtable_size) {
- avail = encoder->ctx.max_dtable_size - encoder->ctx.dtable_size;
- if (need <= avail) {
- return 1;
- }
- }
-
- if (!nghttp3_pq_empty(&encoder->min_cnts)) {
- gmin_cnt = nghttp3_qpack_encoder_get_min_cnt(encoder);
- min_cnt = nghttp3_min(min_cnt, gmin_cnt);
- }
-
- if (min_cnt == UINT64_MAX) {
- return encoder->ctx.max_dtable_size >= need;
- }
-
- min_ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, min_cnt - 1);
-
- len = nghttp3_ringbuf_len(&encoder->ctx.dtable);
- assert(len);
- last_ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(dtable, len - 1);
-
- if (min_ent == last_ent) {
- return 0;
- }
-
- return avail + min_ent->sum - last_ent->sum >= need;
-}
-
-/*
- * qpack_encoder_can_index_nv returns nonzero if header field |nv| can
- * be inserted into dynamic table. |min_cnt| is the minimum insert
- * count which blocked stream requires.
- */
-static int qpack_encoder_can_index_nv(nghttp3_qpack_encoder *encoder,
- const nghttp3_nv *nv, uint64_t min_cnt) {
- return qpack_encoder_can_index(
- encoder, table_space(nv->namelen, nv->valuelen), min_cnt);
-}
-
-/*
- * qpack_encoder_can_index_duplicate returns nonzero if an entry at
- * |absidx| in dynamic table can be inserted to dynamic table as
- * duplicate. |min_cnt| is the minimum insert count which blocked
- * stream requires.
- */
-static int qpack_encoder_can_index_duplicate(nghttp3_qpack_encoder *encoder,
- uint64_t absidx,
- uint64_t min_cnt) {
- nghttp3_qpack_entry *ent =
- nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
-
- return qpack_encoder_can_index(
- encoder, table_space(ent->nv.name->len, ent->nv.value->len), min_cnt);
-}
-
-/*
- * qpack_context_check_draining returns nonzero if an entry at
- * |absidx| in dynamic table is one of draining entries.
- */
-static int qpack_context_check_draining(nghttp3_qpack_context *ctx,
- uint64_t absidx) {
- const size_t safe =
- ctx->max_dtable_size - nghttp3_min(512, ctx->max_dtable_size * 1 / 8);
- nghttp3_qpack_entry *ent = nghttp3_qpack_context_dtable_get(ctx, absidx);
-
- return ctx->dtable_sum - ent->sum > safe;
-}
-
-int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
- uint64_t *pmax_cnt, uint64_t *pmin_cnt,
- nghttp3_buf *rbuf, nghttp3_buf *ebuf,
- const nghttp3_nv *nv, uint64_t base,
- int allow_blocking) {
- uint32_t hash = 0;
- int32_t token;
- nghttp3_qpack_indexing_mode indexing_mode;
- nghttp3_qpack_lookup_result sres = {-1, 0, -1}, dres = {-1, 0, -1};
- nghttp3_qpack_entry *new_ent = NULL;
- int static_entry;
- int just_index = 0;
- int rv;
-
- token = qpack_lookup_token(nv->name, nv->namelen);
- static_entry = token != -1 && (size_t)token < nghttp3_arraylen(token_stable);
- if (static_entry) {
- hash = token_stable[token].hash;
- } else {
- switch (token) {
- case NGHTTP3_QPACK_TOKEN_HOST:
- hash = 2952701295u;
- break;
- case NGHTTP3_QPACK_TOKEN_TE:
- hash = 1011170994u;
- break;
- case NGHTTP3_QPACK_TOKEN__PROTOCOL:
- hash = 1128642621u;
- break;
- case NGHTTP3_QPACK_TOKEN_PRIORITY:
- hash = 2498028297u;
- break;
- }
- }
-
- indexing_mode = qpack_encoder_decide_indexing_mode(encoder, nv, token);
-
- if (static_entry) {
- sres = nghttp3_qpack_lookup_stable(nv, token, indexing_mode);
- if (sres.index != -1 && sres.name_value_match) {
- return nghttp3_qpack_encoder_write_static_indexed(encoder, rbuf,
- (size_t)sres.index);
- }
- }
-
- if (hash &&
- nghttp3_map_size(&encoder->streams) < NGHTTP3_QPACK_MAX_QPACK_STREAMS) {
- dres = nghttp3_qpack_encoder_lookup_dtable(encoder, nv, token, hash,
- indexing_mode, encoder->krcnt,
- allow_blocking);
- just_index = indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_STORE &&
- dres.pb_index == -1;
- }
-
- if (dres.index != -1 && dres.name_value_match) {
- if (allow_blocking &&
- qpack_context_check_draining(&encoder->ctx, (size_t)dres.index) &&
- qpack_encoder_can_index_duplicate(encoder, (size_t)dres.index,
- *pmin_cnt)) {
- rv = nghttp3_qpack_encoder_write_duplicate_insert(encoder, ebuf,
- (size_t)dres.index);
- if (rv != 0) {
- return rv;
- }
- rv = nghttp3_qpack_encoder_dtable_duplicate_add(encoder,
- (size_t)dres.index);
- if (rv != 0) {
- return rv;
- }
-
- new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
- dres.index = (nghttp3_ssize)new_ent->absidx;
- }
- *pmax_cnt = nghttp3_max(*pmax_cnt, (size_t)(dres.index + 1));
- *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)(dres.index + 1));
-
- return nghttp3_qpack_encoder_write_dynamic_indexed(
- encoder, rbuf, (size_t)dres.index, base);
- }
-
- if (sres.index != -1) {
- if (just_index && qpack_encoder_can_index_nv(encoder, nv, *pmin_cnt)) {
- rv = nghttp3_qpack_encoder_write_static_insert(encoder, ebuf,
- (size_t)sres.index, nv);
- if (rv != 0) {
- return rv;
- }
- rv = nghttp3_qpack_encoder_dtable_static_add(encoder, (size_t)sres.index,
- nv, hash);
- if (rv != 0) {
- return rv;
- }
- if (allow_blocking) {
- new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
- *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
- *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
-
- return nghttp3_qpack_encoder_write_dynamic_indexed(
- encoder, rbuf, new_ent->absidx, base);
- }
- }
-
- return nghttp3_qpack_encoder_write_static_indexed_name(
- encoder, rbuf, (size_t)sres.index, nv);
- }
-
- if (dres.index != -1) {
- if (just_index &&
- qpack_encoder_can_index_nv(
- encoder, nv,
- allow_blocking ? *pmin_cnt
- : nghttp3_min((size_t)dres.index + 1, *pmin_cnt))) {
- rv = nghttp3_qpack_encoder_write_dynamic_insert(encoder, ebuf,
- (size_t)dres.index, nv);
- if (rv != 0) {
- return rv;
- }
-
- if (!allow_blocking) {
- *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)dres.index + 1);
- }
-
- rv = nghttp3_qpack_encoder_dtable_dynamic_add(encoder, (size_t)dres.index,
- nv, hash);
- if (rv != 0) {
- return rv;
- }
-
- if (allow_blocking) {
- new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
- *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
- *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
-
- return nghttp3_qpack_encoder_write_dynamic_indexed(
- encoder, rbuf, new_ent->absidx, base);
- }
- }
-
- *pmax_cnt = nghttp3_max(*pmax_cnt, (size_t)(dres.index + 1));
- *pmin_cnt = nghttp3_min(*pmin_cnt, (size_t)(dres.index + 1));
-
- return nghttp3_qpack_encoder_write_dynamic_indexed_name(
- encoder, rbuf, (size_t)dres.index, base, nv);
- }
-
- if (just_index && qpack_encoder_can_index_nv(encoder, nv, *pmin_cnt)) {
- rv = nghttp3_qpack_encoder_dtable_literal_add(encoder, nv, token, hash);
- if (rv != 0) {
- return rv;
- }
- rv = nghttp3_qpack_encoder_write_literal_insert(encoder, ebuf, nv);
- if (rv != 0) {
- return rv;
- }
- if (allow_blocking) {
- new_ent = nghttp3_qpack_context_dtable_top(&encoder->ctx);
- *pmax_cnt = nghttp3_max(*pmax_cnt, new_ent->absidx + 1);
- *pmin_cnt = nghttp3_min(*pmin_cnt, new_ent->absidx + 1);
-
- return nghttp3_qpack_encoder_write_dynamic_indexed(encoder, rbuf,
- new_ent->absidx, base);
- }
- }
-
- return nghttp3_qpack_encoder_write_literal(encoder, rbuf, nv);
-}
-
-nghttp3_qpack_lookup_result
-nghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
- nghttp3_qpack_indexing_mode indexing_mode) {
- nghttp3_qpack_lookup_result res = {(nghttp3_ssize)token_stable[token].absidx,
- 0, -1};
- nghttp3_qpack_static_entry *ent;
- nghttp3_qpack_static_header *hdr;
- size_t i;
-
- assert(token >= 0);
-
- if (indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_NEVER) {
- return res;
- }
-
- for (i = (size_t)token;
- i < nghttp3_arraylen(token_stable) && token_stable[i].token == token;
- ++i) {
- ent = &token_stable[i];
- hdr = &stable[ent->absidx];
- if (hdr->value.len == nv->valuelen &&
- memeq(hdr->value.base, nv->value, nv->valuelen)) {
- res.index = (nghttp3_ssize)ent->absidx;
- res.name_value_match = 1;
- return res;
- }
- }
- return res;
-}
-
-nghttp3_qpack_lookup_result nghttp3_qpack_encoder_lookup_dtable(
- nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
- uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
- int allow_blocking) {
- nghttp3_qpack_lookup_result res = {-1, 0, -1};
- int exact_match = 0;
- nghttp3_qpack_entry *match, *pb_match;
-
- encoder_qpack_map_find(encoder, &exact_match, &match, &pb_match, nv, token,
- hash, krcnt, allow_blocking,
- indexing_mode == NGHTTP3_QPACK_INDEXING_MODE_NEVER);
- if (match) {
- res.index = (nghttp3_ssize)match->absidx;
- res.name_value_match = exact_match;
- }
- if (pb_match) {
- res.pb_index = (nghttp3_ssize)pb_match->absidx;
- }
-
- return res;
-}
-
-int nghttp3_qpack_header_block_ref_new(nghttp3_qpack_header_block_ref **pref,
- uint64_t max_cnt, uint64_t min_cnt,
- const nghttp3_mem *mem) {
- nghttp3_qpack_header_block_ref *ref =
- nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_header_block_ref));
-
- if (ref == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- ref->max_cnts_pe.index = NGHTTP3_PQ_BAD_INDEX;
- ref->min_cnts_pe.index = NGHTTP3_PQ_BAD_INDEX;
- ref->max_cnt = max_cnt;
- ref->min_cnt = min_cnt;
-
- *pref = ref;
-
- return 0;
-}
-
-void nghttp3_qpack_header_block_ref_del(nghttp3_qpack_header_block_ref *ref,
- const nghttp3_mem *mem) {
- nghttp3_mem_free(mem, ref);
-}
-
-static int ref_max_cnt_greater(const nghttp3_pq_entry *lhsx,
- const nghttp3_pq_entry *rhsx) {
- const nghttp3_qpack_header_block_ref *lhs =
- nghttp3_struct_of(lhsx, nghttp3_qpack_header_block_ref, max_cnts_pe);
- const nghttp3_qpack_header_block_ref *rhs =
- nghttp3_struct_of(rhsx, nghttp3_qpack_header_block_ref, max_cnts_pe);
-
- return lhs->max_cnt > rhs->max_cnt;
-}
-
-int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
- const nghttp3_mem *mem) {
- int rv;
- nghttp3_qpack_stream *stream;
-
- stream = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream));
- if (stream == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- rv = nghttp3_ringbuf_init(&stream->refs, 4,
- sizeof(nghttp3_qpack_header_block_ref *), mem);
- if (rv != 0) {
- nghttp3_mem_free(mem, stream);
- return rv;
- }
-
- nghttp3_pq_init(&stream->max_cnts, ref_max_cnt_greater, mem);
-
- stream->me.next = NULL;
- stream->me.key = (uint64_t)stream_id;
-
- *pstream = stream;
-
- return 0;
-}
-
-void nghttp3_qpack_stream_del(nghttp3_qpack_stream *stream,
- const nghttp3_mem *mem) {
- nghttp3_qpack_header_block_ref *ref;
- size_t i, len;
-
- if (stream == NULL) {
- return;
- }
-
- nghttp3_pq_free(&stream->max_cnts);
-
- len = nghttp3_ringbuf_len(&stream->refs);
- for (i = 0; i < len; ++i) {
- ref = *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs,
- i);
- nghttp3_qpack_header_block_ref_del(ref, mem);
- }
-
- nghttp3_ringbuf_free(&stream->refs);
-
- nghttp3_mem_free(mem, stream);
-}
-
-uint64_t nghttp3_qpack_stream_get_max_cnt(const nghttp3_qpack_stream *stream) {
- nghttp3_qpack_header_block_ref *ref;
-
- if (nghttp3_pq_empty(&stream->max_cnts)) {
- return 0;
- }
-
- ref = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
- nghttp3_qpack_header_block_ref, max_cnts_pe);
- return ref->max_cnt;
-}
-
-int nghttp3_qpack_stream_add_ref(nghttp3_qpack_stream *stream,
- nghttp3_qpack_header_block_ref *ref) {
- nghttp3_qpack_header_block_ref **dest;
- int rv;
-
- if (nghttp3_ringbuf_full(&stream->refs)) {
- rv = nghttp3_ringbuf_reserve(&stream->refs,
- nghttp3_ringbuf_len(&stream->refs) * 2);
- if (rv != 0) {
- return rv;
- }
- }
-
- dest = nghttp3_ringbuf_push_back(&stream->refs);
- *dest = ref;
-
- return nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
-}
-
-void nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream) {
- nghttp3_qpack_header_block_ref *ref;
-
- assert(nghttp3_ringbuf_len(&stream->refs));
-
- ref =
- *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs, 0);
-
- assert(ref->max_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
-
- nghttp3_pq_remove(&stream->max_cnts, &ref->max_cnts_pe);
-
- nghttp3_ringbuf_pop_front(&stream->refs);
-}
-
-int nghttp3_qpack_encoder_write_static_indexed(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- uint64_t absidx) {
- DEBUGF("qpack::encode: Indexed Field Line (static) absidx=%" PRIu64 "\n",
- absidx);
- return qpack_write_number(rbuf, 0xc0, absidx, 6, encoder->ctx.mem);
-}
-
-int nghttp3_qpack_encoder_write_dynamic_indexed(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- uint64_t absidx,
- uint64_t base) {
- DEBUGF("qpack::encode: Indexed Field Line (dynamic) absidx=%" PRIu64
- " base=%" PRIu64 "\n",
- absidx, base);
-
- if (absidx < base) {
- return qpack_write_number(rbuf, 0x80, base - absidx - 1, 6,
- encoder->ctx.mem);
- }
-
- return qpack_write_number(rbuf, 0x10, absidx - base, 4, encoder->ctx.mem);
-}
-
-/*
- * qpack_encoder_write_indexed_name writes generic indexed name. |fb|
- * is the first byte. |nameidx| is an index of referenced name.
- * |prefix| is a prefix of variable integer encoding. |nv| is a
- * header field to encode.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int qpack_encoder_write_indexed_name(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *buf, uint8_t fb,
- uint64_t nameidx, size_t prefix,
- const nghttp3_nv *nv) {
- int rv;
- size_t len = nghttp3_qpack_put_varint_len(nameidx, prefix);
- uint8_t *p;
- size_t hlen;
- int h = 0;
-
- hlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
- if (hlen < nv->valuelen) {
- h = 1;
- len += nghttp3_qpack_put_varint_len(hlen, 7) + hlen;
- } else {
- len += nghttp3_qpack_put_varint_len(nv->valuelen, 7) + nv->valuelen;
- }
-
- rv = reserve_buf(buf, len, encoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = buf->last;
-
- *p = fb;
- p = nghttp3_qpack_put_varint(p, nameidx, prefix);
-
- if (h) {
- *p = 0x80;
- p = nghttp3_qpack_put_varint(p, hlen, 7);
- p = nghttp3_qpack_huffman_encode(p, nv->value, nv->valuelen);
- } else {
- *p = 0;
- p = nghttp3_qpack_put_varint(p, nv->valuelen, 7);
- if (nv->valuelen) {
- p = nghttp3_cpymem(p, nv->value, nv->valuelen);
- }
- }
-
- assert((size_t)(p - buf->last) == len);
-
- buf->last = p;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_write_static_indexed_name(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
- const nghttp3_nv *nv) {
- uint8_t fb =
- (uint8_t)(0x50 | ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x20 : 0));
-
- DEBUGF("qpack::encode: Literal Field Line With Name Reference (static) "
- "absidx=%" PRIu64 " never=%d\n",
- absidx, (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) != 0);
- return qpack_encoder_write_indexed_name(encoder, rbuf, fb, absidx, 4, nv);
-}
-
-int nghttp3_qpack_encoder_write_dynamic_indexed_name(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
- uint64_t base, const nghttp3_nv *nv) {
- uint8_t fb;
-
- DEBUGF("qpack::encode: Literal Field Line With Name Reference (dynamic) "
- "absidx=%" PRIu64 " base=%" PRIu64 " never=%d\n",
- absidx, base, (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) != 0);
-
- if (absidx < base) {
- fb = (uint8_t)(0x40 |
- ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x20 : 0));
- return qpack_encoder_write_indexed_name(encoder, rbuf, fb,
- base - absidx - 1, 4, nv);
- }
-
- fb = (nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x08 : 0;
- return qpack_encoder_write_indexed_name(encoder, rbuf, fb, absidx - base, 3,
- nv);
-}
-
-/*
- * qpack_encoder_write_literal writes generic literal header field
- * representation. |fb| is a first byte. |prefix| is a prefix of
- * variable integer encoding for name length. |nv| is a header field
- * to encode.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-static int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *buf, uint8_t fb,
- size_t prefix, const nghttp3_nv *nv) {
- int rv;
- size_t len;
- uint8_t *p;
- size_t nhlen, vhlen;
- int nh = 0, vh = 0;
-
- nhlen = nghttp3_qpack_huffman_encode_count(nv->name, nv->namelen);
- if (nhlen < nv->namelen) {
- nh = 1;
- len = nghttp3_qpack_put_varint_len(nhlen, prefix) + nhlen;
- } else {
- len = nghttp3_qpack_put_varint_len(nv->namelen, prefix) + nv->namelen;
- }
-
- vhlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
- if (vhlen < nv->valuelen) {
- vh = 1;
- len += nghttp3_qpack_put_varint_len(vhlen, 7) + vhlen;
- } else {
- len += nghttp3_qpack_put_varint_len(nv->valuelen, 7) + nv->valuelen;
- }
-
- rv = reserve_buf(buf, len, encoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = buf->last;
-
- *p = fb;
- if (nh) {
- *p |= (uint8_t)(1 << prefix);
- p = nghttp3_qpack_put_varint(p, nhlen, prefix);
- p = nghttp3_qpack_huffman_encode(p, nv->name, nv->namelen);
- } else {
- p = nghttp3_qpack_put_varint(p, nv->namelen, prefix);
- if (nv->namelen) {
- p = nghttp3_cpymem(p, nv->name, nv->namelen);
- }
- }
-
- *p = 0;
-
- if (vh) {
- *p |= 0x80;
- p = nghttp3_qpack_put_varint(p, vhlen, 7);
- p = nghttp3_qpack_huffman_encode(p, nv->value, nv->valuelen);
- } else {
- p = nghttp3_qpack_put_varint(p, nv->valuelen, 7);
- if (nv->valuelen) {
- p = nghttp3_cpymem(p, nv->value, nv->valuelen);
- }
- }
-
- assert((size_t)(p - buf->last) == len);
-
- buf->last = p;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- const nghttp3_nv *nv) {
- uint8_t fb =
- (uint8_t)(0x20 | ((nv->flags & NGHTTP3_NV_FLAG_NEVER_INDEX) ? 0x10 : 0));
-
- DEBUGF("qpack::encode: Literal Field Line Without Name Reference\n");
- return qpack_encoder_write_literal(encoder, rbuf, fb, 3, nv);
-}
-
-int nghttp3_qpack_encoder_write_static_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx,
- const nghttp3_nv *nv) {
- DEBUGF("qpack::encode: Insert With Name Reference (static) absidx=%" PRIu64
- "\n",
- absidx);
- return qpack_encoder_write_indexed_name(encoder, ebuf, 0xc0, absidx, 6, nv);
-}
-
-int nghttp3_qpack_encoder_write_dynamic_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx,
- const nghttp3_nv *nv) {
- DEBUGF("qpack::encode: Insert With Name Reference (dynamic) absidx=%" PRIu64
- "\n",
- absidx);
- return qpack_encoder_write_indexed_name(
- encoder, ebuf, 0x80, encoder->ctx.next_absidx - absidx - 1, 6, nv);
-}
-
-int nghttp3_qpack_encoder_write_duplicate_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx) {
- uint64_t idx = encoder->ctx.next_absidx - absidx - 1;
- size_t len = nghttp3_qpack_put_varint_len(idx, 5);
- uint8_t *p;
- int rv;
-
- DEBUGF("qpack::encode: Insert duplicate absidx=%" PRIu64 "\n", absidx);
-
- rv = reserve_buf(ebuf, len, encoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = ebuf->last;
-
- *p = 0;
- p = nghttp3_qpack_put_varint(p, idx, 5);
-
- assert((size_t)(p - ebuf->last) == len);
-
- ebuf->last = p;
-
- return 0;
-}
-
-int nghttp3_qpack_encoder_write_literal_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- const nghttp3_nv *nv) {
- DEBUGF("qpack::encode: Insert Without Name Reference\n");
- return qpack_encoder_write_literal(encoder, ebuf, 0x40, 5, nv);
-}
-
-int nghttp3_qpack_context_dtable_add(nghttp3_qpack_context *ctx,
- nghttp3_qpack_nv *qnv,
- nghttp3_qpack_map *dtable_map,
- uint32_t hash) {
- nghttp3_qpack_entry *new_ent, **p, *ent;
- const nghttp3_mem *mem = ctx->mem;
- size_t space;
- size_t i;
- int rv;
-
- space = table_space(qnv->name->len, qnv->value->len);
-
- assert(space <= ctx->max_dtable_size);
-
- while (ctx->dtable_size + space > ctx->max_dtable_size) {
- i = nghttp3_ringbuf_len(&ctx->dtable);
- assert(i);
- ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i - 1);
-
- ctx->dtable_size -= table_space(ent->nv.name->len, ent->nv.value->len);
-
- nghttp3_ringbuf_pop_back(&ctx->dtable);
- if (dtable_map) {
- qpack_map_remove(dtable_map, ent);
- }
-
- nghttp3_qpack_entry_free(ent);
- nghttp3_mem_free(mem, ent);
- }
-
- new_ent = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_entry));
- if (new_ent == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- nghttp3_qpack_entry_init(new_ent, qnv, ctx->dtable_sum, ctx->next_absidx++,
- hash);
-
- if (nghttp3_ringbuf_full(&ctx->dtable)) {
- rv = nghttp3_ringbuf_reserve(&ctx->dtable,
- nghttp3_ringbuf_len(&ctx->dtable) * 2);
- if (rv != 0) {
- goto fail;
- }
- }
-
- p = nghttp3_ringbuf_push_front(&ctx->dtable);
- *p = new_ent;
-
- if (dtable_map) {
- qpack_map_insert(dtable_map, new_ent);
- }
-
- ctx->dtable_size += space;
- ctx->dtable_sum += space;
-
- return 0;
-
-fail:
- nghttp3_qpack_entry_free(new_ent);
- nghttp3_mem_free(mem, new_ent);
-
- return rv;
-}
-
-int nghttp3_qpack_encoder_dtable_static_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx,
- const nghttp3_nv *nv,
- uint32_t hash) {
- const nghttp3_qpack_static_header *shd;
- nghttp3_qpack_nv qnv;
- const nghttp3_mem *mem = encoder->ctx.mem;
- int rv;
-
- rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
- if (rv != 0) {
- return rv;
- }
-
- assert(nghttp3_arraylen(stable) > absidx);
-
- shd = &stable[absidx];
-
- qnv.name = (nghttp3_rcbuf *)&shd->name;
- qnv.token = shd->token;
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
- &encoder->dtable_map, hash);
-
- nghttp3_rcbuf_decref(qnv.value);
-
- return rv;
-}
-
-int nghttp3_qpack_encoder_dtable_dynamic_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx,
- const nghttp3_nv *nv,
- uint32_t hash) {
- nghttp3_qpack_nv qnv;
- nghttp3_qpack_entry *ent;
- const nghttp3_mem *mem = encoder->ctx.mem;
- int rv;
-
- rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
- if (rv != 0) {
- return rv;
- }
-
- ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
-
- qnv.name = ent->nv.name;
- qnv.token = ent->nv.token;
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- nghttp3_rcbuf_incref(qnv.name);
-
- rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
- &encoder->dtable_map, hash);
-
- nghttp3_rcbuf_decref(qnv.value);
- nghttp3_rcbuf_decref(qnv.name);
-
- return rv;
-}
-
-int nghttp3_qpack_encoder_dtable_duplicate_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx) {
- nghttp3_qpack_nv qnv;
- nghttp3_qpack_entry *ent;
- int rv;
-
- ent = nghttp3_qpack_context_dtable_get(&encoder->ctx, absidx);
-
- qnv = ent->nv;
- nghttp3_rcbuf_incref(qnv.name);
- nghttp3_rcbuf_incref(qnv.value);
-
- rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
- &encoder->dtable_map, ent->hash);
-
- nghttp3_rcbuf_decref(qnv.name);
- nghttp3_rcbuf_decref(qnv.value);
-
- return rv;
-}
-
-int nghttp3_qpack_encoder_dtable_literal_add(nghttp3_qpack_encoder *encoder,
- const nghttp3_nv *nv,
- int32_t token, uint32_t hash) {
- nghttp3_qpack_nv qnv;
- const nghttp3_mem *mem = encoder->ctx.mem;
- int rv;
-
- rv = nghttp3_rcbuf_new2(&qnv.name, nv->name, nv->namelen, mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = nghttp3_rcbuf_new2(&qnv.value, nv->value, nv->valuelen, mem);
- if (rv != 0) {
- nghttp3_rcbuf_decref(qnv.name);
- return rv;
- }
-
- qnv.token = token;
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- rv = nghttp3_qpack_context_dtable_add(&encoder->ctx, &qnv,
- &encoder->dtable_map, hash);
-
- nghttp3_rcbuf_decref(qnv.value);
- nghttp3_rcbuf_decref(qnv.name);
-
- return rv;
-}
-
-nghttp3_qpack_entry *
-nghttp3_qpack_context_dtable_get(nghttp3_qpack_context *ctx, uint64_t absidx) {
- size_t relidx;
-
- assert(ctx->next_absidx > absidx);
- assert(ctx->next_absidx - absidx - 1 < nghttp3_ringbuf_len(&ctx->dtable));
-
- relidx = (size_t)(ctx->next_absidx - absidx - 1);
-
- return *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, relidx);
-}
-
-nghttp3_qpack_entry *
-nghttp3_qpack_context_dtable_top(nghttp3_qpack_context *ctx) {
- assert(nghttp3_ringbuf_len(&ctx->dtable));
- return *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, 0);
-}
-
-void nghttp3_qpack_entry_init(nghttp3_qpack_entry *ent, nghttp3_qpack_nv *qnv,
- size_t sum, uint64_t absidx, uint32_t hash) {
- ent->nv = *qnv;
- ent->map_next = NULL;
- ent->sum = sum;
- ent->absidx = absidx;
- ent->hash = hash;
-
- nghttp3_rcbuf_incref(ent->nv.name);
- nghttp3_rcbuf_incref(ent->nv.value);
-}
-
-void nghttp3_qpack_entry_free(nghttp3_qpack_entry *ent) {
- nghttp3_rcbuf_decref(ent->nv.value);
- nghttp3_rcbuf_decref(ent->nv.name);
-}
-
-int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream) {
- nghttp3_blocked_streams_key bsk = {
- nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
- nghttp3_qpack_header_block_ref, max_cnts_pe)
- ->max_cnt,
- stream->me.key};
-
- return nghttp3_ksl_insert(&encoder->blocked_streams, NULL, &bsk, stream);
-}
-
-void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream) {
- nghttp3_blocked_streams_key bsk = {
- nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
- nghttp3_qpack_header_block_ref, max_cnts_pe)
- ->max_cnt,
- stream->me.key};
- nghttp3_ksl_it it;
-
- /* This is purely debugging purpose only */
- it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
-
- assert(!nghttp3_ksl_it_end(&it));
- assert(nghttp3_ksl_it_get(&it) == stream);
-
- nghttp3_ksl_remove(&encoder->blocked_streams, NULL, &bsk);
-}
-
-void nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
- uint64_t max_cnt) {
- nghttp3_blocked_streams_key bsk = {max_cnt, 0};
- nghttp3_ksl_it it;
-
- it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
-
- for (; !nghttp3_ksl_it_end(&it);) {
- bsk = *(nghttp3_blocked_streams_key *)nghttp3_ksl_it_key(&it);
- nghttp3_ksl_remove(&encoder->blocked_streams, &it, &bsk);
- }
-}
-
-void nghttp3_qpack_encoder_ack_header(nghttp3_qpack_encoder *encoder,
- int64_t stream_id) {
- nghttp3_qpack_stream *stream =
- nghttp3_qpack_encoder_find_stream(encoder, stream_id);
- const nghttp3_mem *mem = encoder->ctx.mem;
- nghttp3_qpack_header_block_ref *ref;
-
- if (stream == NULL) {
- /* This might be NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR, but we
- don't create stream which does not use dynamic table. */
- return;
- }
-
- assert(nghttp3_ringbuf_len(&stream->refs));
-
- ref =
- *(nghttp3_qpack_header_block_ref **)nghttp3_ringbuf_get(&stream->refs, 0);
-
- DEBUGF("qpack::encoder: Header acknowledgement stream=%ld ricnt=%" PRIu64
- " krcnt=%" PRIu64 "\n",
- stream_id, ref->max_cnt, encoder->krcnt);
-
- if (encoder->krcnt < ref->max_cnt) {
- encoder->krcnt = ref->max_cnt;
-
- nghttp3_qpack_encoder_unblock(encoder, ref->max_cnt);
- }
-
- nghttp3_qpack_stream_pop_ref(stream);
-
- assert(ref->min_cnts_pe.index != NGHTTP3_PQ_BAD_INDEX);
-
- nghttp3_pq_remove(&encoder->min_cnts, &ref->min_cnts_pe);
-
- nghttp3_qpack_header_block_ref_del(ref, mem);
-
- if (nghttp3_ringbuf_len(&stream->refs)) {
- return;
- }
-
- qpack_encoder_remove_stream(encoder, stream);
-
- nghttp3_qpack_stream_del(stream, mem);
-}
-
-int nghttp3_qpack_encoder_add_insert_count(nghttp3_qpack_encoder *encoder,
- uint64_t n) {
- if (encoder->ctx.next_absidx - encoder->krcnt < n) {
- return NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR;
- }
- encoder->krcnt += n;
-
- nghttp3_qpack_encoder_unblock(encoder, encoder->krcnt);
-
- return 0;
-}
-
-void nghttp3_qpack_encoder_ack_everything(nghttp3_qpack_encoder *encoder) {
- encoder->krcnt = encoder->ctx.next_absidx;
-
- nghttp3_ksl_clear(&encoder->blocked_streams);
- nghttp3_pq_clear(&encoder->min_cnts);
- nghttp3_map_each_free(&encoder->streams, map_stream_free,
- (void *)encoder->ctx.mem);
-}
-
-void nghttp3_qpack_encoder_cancel_stream(nghttp3_qpack_encoder *encoder,
- int64_t stream_id) {
- nghttp3_qpack_stream *stream =
- nghttp3_qpack_encoder_find_stream(encoder, stream_id);
- const nghttp3_mem *mem = encoder->ctx.mem;
-
- if (stream == NULL) {
- return;
- }
-
- if (nghttp3_qpack_encoder_stream_is_blocked(encoder, stream)) {
- nghttp3_qpack_encoder_unblock_stream(encoder, stream);
- }
-
- qpack_encoder_remove_stream(encoder, stream);
-
- nghttp3_qpack_stream_del(stream, mem);
-}
-
-size_t nghttp3_qpack_encoder_get_num_blocked(nghttp3_qpack_encoder *encoder) {
- return nghttp3_ksl_len(&encoder->blocked_streams);
-}
-
-int nghttp3_qpack_encoder_write_field_section_prefix(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *pbuf, uint64_t ricnt,
- uint64_t base) {
- size_t max_ents =
- encoder->ctx.hard_max_dtable_size / NGHTTP3_QPACK_ENTRY_OVERHEAD;
- uint64_t encricnt = ricnt == 0 ? 0 : (ricnt % (2 * max_ents)) + 1;
- int sign = base < ricnt;
- uint64_t delta_base = sign ? ricnt - base - 1 : base - ricnt;
- size_t len = nghttp3_qpack_put_varint_len(encricnt, 8) +
- nghttp3_qpack_put_varint_len(delta_base, 7);
- uint8_t *p;
- int rv;
-
- DEBUGF("qpack::encode: ricnt=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64 "\n",
- ricnt, base, encoder->ctx.next_absidx);
-
- rv = reserve_buf(pbuf, len, encoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = pbuf->last;
-
- p = nghttp3_qpack_put_varint(p, encricnt, 8);
- if (sign) {
- *p = 0x80;
- } else {
- *p = 0;
- }
- p = nghttp3_qpack_put_varint(p, delta_base, 7);
-
- assert((size_t)(p - pbuf->last) == len);
-
- pbuf->last = p;
-
- return 0;
-}
-
-/*
- * qpack_read_varint reads |rstate->prefix| prefixed integer stored
- * from |begin|. The |end| represents the 1 beyond the last of the
- * valid contiguous memory region from |begin|. The decoded integer
- * must be less than or equal to NGHTTP3_QPACK_INT_MAX.
- *
- * If the |rstate->left| is nonzero, it is used as an initial value,
- * and this function assumes the |begin| starts with intermediate
- * data. |rstate->shift| is used as initial integer shift.
- *
- * If an entire integer is decoded successfully, the |*fin| is set to
- * nonzero.
- *
- * This function stores the decoded integer in |rstate->left| if it
- * succeeds, including partial decoding (in this case, number of shift
- * to make in the next call will be stored in |rstate->shift|) and
- * returns number of bytes processed, or returns negative error code
- * NGHTTP3_ERR_QPACK_FATAL, indicating decoding error.
- */
-static nghttp3_ssize qpack_read_varint(int *fin,
- nghttp3_qpack_read_state *rstate,
- const uint8_t *begin,
- const uint8_t *end) {
- uint64_t k = (uint8_t)((1 << rstate->prefix) - 1);
- uint64_t n = rstate->left;
- uint64_t add;
- const uint8_t *p = begin;
- size_t shift = rstate->shift;
-
- rstate->shift = 0;
- *fin = 0;
-
- if (n == 0) {
- if (((*p) & k) != k) {
- rstate->left = (*p) & k;
- *fin = 1;
- return 1;
- }
-
- n = k;
-
- if (++p == end) {
- rstate->left = n;
- return (nghttp3_ssize)(p - begin);
- }
- }
-
- for (; p != end; ++p, shift += 7) {
- add = (*p) & 0x7f;
-
- if (shift > 62) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- if ((NGHTTP3_QPACK_INT_MAX >> shift) < add) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- add <<= shift;
-
- if (NGHTTP3_QPACK_INT_MAX - add < n) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- n += add;
-
- if (((*p) & (1 << 7)) == 0) {
- break;
- }
- }
-
- rstate->shift = shift;
-
- if (p == end) {
- rstate->left = n;
- return (nghttp3_ssize)(p - begin);
- }
-
- rstate->left = n;
- *fin = 1;
- return (nghttp3_ssize)(p + 1 - begin);
-}
-
-nghttp3_ssize nghttp3_qpack_encoder_read_decoder(nghttp3_qpack_encoder *encoder,
- const uint8_t *src,
- size_t srclen) {
- const uint8_t *p = src, *end;
- int rv;
- nghttp3_ssize nread;
- int rfin;
-
- if (encoder->ctx.bad) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- if (srclen == 0) {
- return 0;
- }
-
- end = src + srclen;
-
- for (; p != end;) {
- switch (encoder->state) {
- case NGHTTP3_QPACK_DS_STATE_OPCODE:
- if ((*p) & 0x80) {
- DEBUGF("qpack::encode: OPCODE_SECTION_ACK\n");
- encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK;
- encoder->rstate.prefix = 7;
- } else if ((*p) & 0x40) {
- DEBUGF("qpack::encode: OPCODE_STREAM_CANCEL\n");
- encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL;
- encoder->rstate.prefix = 6;
- } else {
- DEBUGF("qpack::encode: OPCODE_ICNT_INCREMENT\n");
- encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT;
- encoder->rstate.prefix = 6;
- }
- encoder->state = NGHTTP3_QPACK_DS_STATE_READ_NUMBER;
- /* fall through */
- case NGHTTP3_QPACK_DS_STATE_READ_NUMBER:
- nread = qpack_read_varint(&rfin, &encoder->rstate, p, end);
- if (nread < 0) {
- assert(nread == NGHTTP3_ERR_QPACK_FATAL);
- rv = NGHTTP3_ERR_QPACK_DECODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- return p - src;
- }
-
- switch (encoder->opcode) {
- case NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT:
- rv = nghttp3_qpack_encoder_add_insert_count(encoder,
- encoder->rstate.left);
- if (rv != 0) {
- goto fail;
- }
- break;
- case NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK:
- nghttp3_qpack_encoder_ack_header(encoder,
- (int64_t)encoder->rstate.left);
- break;
- case NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL:
- nghttp3_qpack_encoder_cancel_stream(encoder,
- (int64_t)encoder->rstate.left);
- break;
- default:
- /* unreachable */
- assert(0);
- break;
- }
-
- encoder->state = NGHTTP3_QPACK_DS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&encoder->rstate);
- break;
- default:
- /* unreachable */
- assert(0);
- break;
- }
- }
-
- return p - src;
-
-fail:
- encoder->ctx.bad = 1;
- return rv;
-}
-
-size_t nghttp3_qpack_put_varint_len(uint64_t n, size_t prefix) {
- size_t k = (size_t)((1 << prefix) - 1);
- size_t len = 0;
-
- if (n < k) {
- return 1;
- }
-
- n -= k;
- ++len;
-
- for (; n >= 128; n >>= 7, ++len)
- ;
-
- return len + 1;
-}
-
-uint8_t *nghttp3_qpack_put_varint(uint8_t *buf, uint64_t n, size_t prefix) {
- size_t k = (size_t)((1 << prefix) - 1);
-
- *buf = (uint8_t)(*buf & ~k);
-
- if (n < k) {
- *buf = (uint8_t)(*buf | n);
- return buf + 1;
- }
-
- *buf = (uint8_t)(*buf | k);
- ++buf;
-
- n -= k;
-
- for (; n >= 128; n >>= 7) {
- *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
- }
-
- *buf++ = (uint8_t)n;
-
- return buf;
-}
-
-void nghttp3_qpack_read_state_free(nghttp3_qpack_read_state *rstate) {
- nghttp3_rcbuf_decref(rstate->value);
- nghttp3_rcbuf_decref(rstate->name);
-}
-
-void nghttp3_qpack_read_state_reset(nghttp3_qpack_read_state *rstate) {
- rstate->name = NULL;
- rstate->value = NULL;
- nghttp3_buf_init(&rstate->namebuf);
- nghttp3_buf_init(&rstate->valuebuf);
- rstate->left = 0;
- rstate->prefix = 0;
- rstate->shift = 0;
- rstate->absidx = 0;
- rstate->never = 0;
- rstate->dynamic = 0;
- rstate->huffman_encoded = 0;
-}
-
-int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem) {
- int rv;
-
- rv = qpack_context_init(&decoder->ctx, max_dtable_size, max_blocked, mem);
- if (rv != 0) {
- return rv;
- }
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
- decoder->opcode = 0;
- decoder->written_icnt = 0;
- decoder->max_concurrent_streams = 0;
-
- nghttp3_qpack_read_state_reset(&decoder->rstate);
- nghttp3_buf_init(&decoder->dbuf);
-
- return 0;
-}
-
-void nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder) {
- nghttp3_buf_free(&decoder->dbuf, decoder->ctx.mem);
- nghttp3_qpack_read_state_free(&decoder->rstate);
- qpack_context_free(&decoder->ctx);
-}
-
-/*
- * qpack_read_huffman_string decodes huffman string in buffer [begin,
- * end) and writes the decoded string to |dest|. This function
- * assumes the buffer pointed by |dest| has enough space.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_QPACK_FATAL
- * Could not decode huffman string.
- */
-static nghttp3_ssize qpack_read_huffman_string(nghttp3_qpack_read_state *rstate,
- nghttp3_buf *dest,
- const uint8_t *begin,
- const uint8_t *end) {
- nghttp3_ssize nwrite;
- size_t len = (size_t)(end - begin);
- int fin = 0;
-
- if (len >= rstate->left) {
- len = (size_t)rstate->left;
- fin = 1;
- }
-
- nwrite = nghttp3_qpack_huffman_decode(&rstate->huffman_ctx, dest->last, begin,
- len, fin);
- if (nwrite < 0) {
- return nwrite;
- }
-
- if (nghttp3_qpack_huffman_decode_failure_state(&rstate->huffman_ctx)) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- dest->last += nwrite;
- rstate->left -= len;
- return (nghttp3_ssize)len;
-}
-
-static nghttp3_ssize qpack_read_string(nghttp3_qpack_read_state *rstate,
- nghttp3_buf *dest, const uint8_t *begin,
- const uint8_t *end) {
- size_t len = (size_t)(end - begin);
- size_t n = (size_t)nghttp3_min((uint64_t)len, rstate->left);
-
- dest->last = nghttp3_cpymem(dest->last, begin, n);
-
- rstate->left -= n;
- return (nghttp3_ssize)n;
-}
-
-/*
- * qpack_decoder_validate_index checks rstate->absidx is acceptable.
- *
- * It returns 0 if it suceeds, or one of the following negative error
- * codes:
- *
- * NGHTTP3_ERR_QPACK_FATAL
- * rstate->absidx is invalid.
- */
-static int qpack_decoder_validate_index(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_read_state *rstate) {
- if (rstate->dynamic) {
- return rstate->absidx < decoder->ctx.next_absidx &&
- decoder->ctx.next_absidx - rstate->absidx - 1 <
- nghttp3_ringbuf_len(&decoder->ctx.dtable)
- ? 0
- : NGHTTP3_ERR_QPACK_FATAL;
- }
- return rstate->absidx < nghttp3_arraylen(stable) ? 0
- : NGHTTP3_ERR_QPACK_FATAL;
-}
-
-static void qpack_read_state_check_huffman(nghttp3_qpack_read_state *rstate,
- const uint8_t b) {
- rstate->huffman_encoded = (b & (1 << rstate->prefix)) != 0;
-}
-
-static void qpack_read_state_terminate_name(nghttp3_qpack_read_state *rstate) {
- *rstate->namebuf.last = '\0';
- rstate->name->len = nghttp3_buf_len(&rstate->namebuf);
-}
-
-static void qpack_read_state_terminate_value(nghttp3_qpack_read_state *rstate) {
- *rstate->valuebuf.last = '\0';
- rstate->value->len = nghttp3_buf_len(&rstate->valuebuf);
-}
-
-nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder,
- const uint8_t *src,
- size_t srclen) {
- const uint8_t *p = src, *end;
- int rv;
- int busy = 0;
- const nghttp3_mem *mem = decoder->ctx.mem;
- nghttp3_ssize nread;
- int rfin;
-
- if (decoder->ctx.bad) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- if (srclen == 0) {
- return 0;
- }
-
- end = src + srclen;
-
- for (; p != end || busy;) {
- busy = 0;
- switch (decoder->state) {
- case NGHTTP3_QPACK_ES_STATE_OPCODE:
- if ((*p) & 0x80) {
- DEBUGF("qpack::decode: OPCODE_INSERT_INDEXED\n");
- decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED;
- decoder->rstate.dynamic = !((*p) & 0x40);
- decoder->rstate.prefix = 6;
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
- } else if ((*p) & 0x40) {
- DEBUGF("qpack::decode: OPCODE_INSERT\n");
- decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT;
- decoder->rstate.dynamic = 0;
- decoder->rstate.prefix = 5;
- decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN;
- } else if ((*p) & 0x20) {
- DEBUGF("qpack::decode: OPCODE_SET_DTABLE_TABLE_CAP\n");
- decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP;
- decoder->rstate.prefix = 5;
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
- } else if (!((*p) & 0x20)) {
- DEBUGF("qpack::decode: OPCODE_DUPLICATE\n");
- decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_DUPLICATE;
- decoder->rstate.dynamic = 1;
- decoder->rstate.prefix = 5;
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX;
- } else {
- DEBUGF("qpack::decode: unknown opcode %02x\n", *p);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
- break;
- case NGHTTP3_QPACK_ES_STATE_READ_INDEX:
- nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- return p - src;
- }
-
- if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP) {
- if (decoder->rstate.left > decoder->ctx.hard_max_dtable_size) {
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
- DEBUGF("qpack::decode: Set dtable capacity to %" PRIu64 "\n",
- decoder->rstate.left);
- nghttp3_qpack_decoder_set_dtable_cap(decoder,
- (size_t)decoder->rstate.left);
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&decoder->rstate);
- break;
- }
-
- rv = nghttp3_qpack_decoder_rel2abs(decoder, &decoder->rstate);
- if (rv < 0) {
- goto fail;
- }
-
- if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_DUPLICATE) {
- rv = nghttp3_qpack_decoder_dtable_duplicate_add(decoder);
- if (rv != 0) {
- goto fail;
- }
- decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&decoder->rstate);
- break;
- }
-
- if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED) {
- decoder->rstate.prefix = 7;
- decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
- break;
- }
-
- /* Unreachable */
- assert(0);
- break;
- case NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN:
- qpack_read_state_check_huffman(&decoder->rstate, *p);
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAMELEN;
- decoder->rstate.left = 0;
- decoder->rstate.shift = 0;
- /* Fall through */
- case NGHTTP3_QPACK_ES_STATE_READ_NAMELEN:
- nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- return p - src;
- }
-
- if (decoder->rstate.left > NGHTTP3_QPACK_MAX_NAMELEN) {
- rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
- goto fail;
- }
-
- if (decoder->rstate.huffman_encoded) {
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAME_HUFFMAN;
- nghttp3_qpack_huffman_decode_context_init(&decoder->rstate.huffman_ctx);
- rv = nghttp3_rcbuf_new(&decoder->rstate.name,
- (size_t)decoder->rstate.left * 2 + 1, mem);
- } else {
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_NAME;
- rv = nghttp3_rcbuf_new(&decoder->rstate.name,
- (size_t)decoder->rstate.left + 1, mem);
- }
- if (rv != 0) {
- goto fail;
- }
-
- nghttp3_buf_wrap_init(&decoder->rstate.namebuf,
- decoder->rstate.name->base,
- decoder->rstate.name->len);
- break;
- case NGHTTP3_QPACK_ES_STATE_READ_NAME_HUFFMAN:
- nread = qpack_read_huffman_string(&decoder->rstate,
- &decoder->rstate.namebuf, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (decoder->rstate.left) {
- return p - src;
- }
-
- qpack_read_state_terminate_name(&decoder->rstate);
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
- decoder->rstate.prefix = 7;
- break;
- case NGHTTP3_QPACK_ES_STATE_READ_NAME:
- nread =
- qpack_read_string(&decoder->rstate, &decoder->rstate.namebuf, p, end);
- if (nread < 0) {
- rv = (int)nread;
- goto fail;
- }
-
- p += nread;
-
- if (decoder->rstate.left) {
- return p - src;
- }
-
- qpack_read_state_terminate_name(&decoder->rstate);
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN;
- decoder->rstate.prefix = 7;
- break;
- case NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN:
- qpack_read_state_check_huffman(&decoder->rstate, *p);
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUELEN;
- decoder->rstate.left = 0;
- decoder->rstate.shift = 0;
- /* Fall through */
- case NGHTTP3_QPACK_ES_STATE_READ_VALUELEN:
- nread = qpack_read_varint(&rfin, &decoder->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- return p - src;
- }
-
- if (decoder->rstate.left > NGHTTP3_QPACK_MAX_VALUELEN) {
- rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
- goto fail;
- }
-
- if (decoder->rstate.huffman_encoded) {
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUE_HUFFMAN;
- nghttp3_qpack_huffman_decode_context_init(&decoder->rstate.huffman_ctx);
- rv = nghttp3_rcbuf_new(&decoder->rstate.value,
- (size_t)decoder->rstate.left * 2 + 1, mem);
- } else {
- decoder->state = NGHTTP3_QPACK_ES_STATE_READ_VALUE;
- rv = nghttp3_rcbuf_new(&decoder->rstate.value,
- (size_t)decoder->rstate.left + 1, mem);
- }
- if (rv != 0) {
- goto fail;
- }
-
- nghttp3_buf_wrap_init(&decoder->rstate.valuebuf,
- decoder->rstate.value->base,
- decoder->rstate.value->len);
-
- /* value might be 0 length */
- busy = 1;
- break;
- case NGHTTP3_QPACK_ES_STATE_READ_VALUE_HUFFMAN:
- nread = qpack_read_huffman_string(&decoder->rstate,
- &decoder->rstate.valuebuf, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- goto fail;
- }
-
- p += nread;
-
- if (decoder->rstate.left) {
- return p - src;
- }
-
- qpack_read_state_terminate_value(&decoder->rstate);
-
- switch (decoder->opcode) {
- case NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED:
- rv = nghttp3_qpack_decoder_dtable_indexed_add(decoder);
- break;
- case NGHTTP3_QPACK_ES_OPCODE_INSERT:
- rv = nghttp3_qpack_decoder_dtable_literal_add(decoder);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- if (rv != 0) {
- goto fail;
- }
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&decoder->rstate);
- break;
- case NGHTTP3_QPACK_ES_STATE_READ_VALUE:
- nread = qpack_read_string(&decoder->rstate, &decoder->rstate.valuebuf, p,
- end);
- if (nread < 0) {
- rv = (int)nread;
- goto fail;
- }
-
- p += nread;
-
- if (decoder->rstate.left) {
- return p - src;
- }
-
- qpack_read_state_terminate_value(&decoder->rstate);
-
- switch (decoder->opcode) {
- case NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED:
- rv = nghttp3_qpack_decoder_dtable_indexed_add(decoder);
- break;
- case NGHTTP3_QPACK_ES_OPCODE_INSERT:
- rv = nghttp3_qpack_decoder_dtable_literal_add(decoder);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- if (rv != 0) {
- goto fail;
- }
-
- decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&decoder->rstate);
- break;
- }
- }
-
- return p - src;
-
-fail:
- decoder->ctx.bad = 1;
- return rv;
-}
-
-void nghttp3_qpack_decoder_set_dtable_cap(nghttp3_qpack_decoder *decoder,
- size_t cap) {
- nghttp3_qpack_entry *ent;
- size_t i;
- nghttp3_qpack_context *ctx = &decoder->ctx;
- const nghttp3_mem *mem = ctx->mem;
-
- ctx->max_dtable_size = cap;
-
- while (ctx->dtable_size > cap) {
- i = nghttp3_ringbuf_len(&ctx->dtable);
- assert(i);
- ent = *(nghttp3_qpack_entry **)nghttp3_ringbuf_get(&ctx->dtable, i - 1);
-
- ctx->dtable_size -= table_space(ent->nv.name->len, ent->nv.value->len);
-
- nghttp3_ringbuf_pop_back(&ctx->dtable);
- nghttp3_qpack_entry_free(ent);
- nghttp3_mem_free(mem, ent);
- }
-}
-
-int nghttp3_qpack_decoder_dtable_indexed_add(nghttp3_qpack_decoder *decoder) {
- DEBUGF("qpack::decode: Insert With Name Reference (%s) absidx=%" PRIu64 ": "
- "value=%*s\n",
- decoder->rstate.dynamic ? "dynamic" : "static", decoder->rstate.absidx,
- (int)decoder->rstate.value->len, decoder->rstate.value->base);
-
- if (decoder->rstate.dynamic) {
- return nghttp3_qpack_decoder_dtable_dynamic_add(decoder);
- }
-
- return nghttp3_qpack_decoder_dtable_static_add(decoder);
-}
-
-int nghttp3_qpack_decoder_dtable_static_add(nghttp3_qpack_decoder *decoder) {
- nghttp3_qpack_nv qnv;
- int rv;
- const nghttp3_qpack_static_header *shd;
-
- shd = &stable[decoder->rstate.absidx];
-
- if (table_space(shd->name.len, decoder->rstate.value->len) >
- decoder->ctx.max_dtable_size) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
-
- qnv.name = (nghttp3_rcbuf *)&shd->name;
- qnv.value = decoder->rstate.value;
- qnv.token = shd->token;
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
-
- nghttp3_rcbuf_decref(qnv.value);
-
- return rv;
-}
-
-int nghttp3_qpack_decoder_dtable_dynamic_add(nghttp3_qpack_decoder *decoder) {
- nghttp3_qpack_nv qnv;
- int rv;
- nghttp3_qpack_entry *ent;
-
- ent = nghttp3_qpack_context_dtable_get(&decoder->ctx, decoder->rstate.absidx);
-
- if (table_space(ent->nv.name->len, decoder->rstate.value->len) >
- decoder->ctx.max_dtable_size) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
-
- qnv.name = ent->nv.name;
- qnv.value = decoder->rstate.value;
- qnv.token = ent->nv.token;
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- nghttp3_rcbuf_incref(qnv.name);
-
- rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
-
- nghttp3_rcbuf_decref(qnv.value);
- nghttp3_rcbuf_decref(qnv.name);
-
- return rv;
-}
-
-int nghttp3_qpack_decoder_dtable_duplicate_add(nghttp3_qpack_decoder *decoder) {
- int rv;
- nghttp3_qpack_entry *ent;
- nghttp3_qpack_nv qnv;
-
- DEBUGF("qpack::decode: Insert duplicate absidx=%" PRIu64 "\n",
- decoder->rstate.absidx);
-
- ent = nghttp3_qpack_context_dtable_get(&decoder->ctx, decoder->rstate.absidx);
-
- if (table_space(ent->nv.name->len, ent->nv.value->len) >
- decoder->ctx.max_dtable_size) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
-
- qnv = ent->nv;
- nghttp3_rcbuf_incref(qnv.name);
- nghttp3_rcbuf_incref(qnv.value);
-
- rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
-
- nghttp3_rcbuf_decref(qnv.value);
- nghttp3_rcbuf_decref(qnv.name);
-
- return rv;
-}
-
-int nghttp3_qpack_decoder_dtable_literal_add(nghttp3_qpack_decoder *decoder) {
- nghttp3_qpack_nv qnv;
- int rv;
-
- DEBUGF("qpack::decode: Insert Without Name Reference: name=%*s value=%*s\n",
- (int)decoder->rstate.name->len, decoder->rstate.name->base,
- (int)decoder->rstate.value->len, decoder->rstate.value->base);
-
- if (table_space(decoder->rstate.name->len, decoder->rstate.value->len) >
- decoder->ctx.max_dtable_size) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
-
- qnv.name = decoder->rstate.name;
- qnv.value = decoder->rstate.value;
- qnv.token = qpack_lookup_token(qnv.name->base, qnv.name->len);
- qnv.flags = NGHTTP3_NV_FLAG_NONE;
-
- rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
-
- nghttp3_rcbuf_decref(qnv.value);
- nghttp3_rcbuf_decref(qnv.name);
-
- return rv;
-}
-
-void nghttp3_qpack_decoder_set_max_concurrent_streams(
- nghttp3_qpack_decoder *decoder, size_t max_concurrent_streams) {
- decoder->max_concurrent_streams =
- nghttp3_max(decoder->max_concurrent_streams, max_concurrent_streams);
-}
-
-void nghttp3_qpack_stream_context_init(nghttp3_qpack_stream_context *sctx,
- int64_t stream_id,
- const nghttp3_mem *mem) {
- nghttp3_qpack_read_state_reset(&sctx->rstate);
-
- sctx->mem = mem;
- sctx->rstate.prefix = 8;
- sctx->state = NGHTTP3_QPACK_RS_STATE_RICNT;
- sctx->opcode = 0;
- sctx->stream_id = stream_id;
- sctx->ricnt = 0;
- sctx->dbase_sign = 0;
- sctx->base = 0;
-}
-
-void nghttp3_qpack_stream_context_free(nghttp3_qpack_stream_context *sctx) {
- nghttp3_qpack_read_state_free(&sctx->rstate);
-}
-
-void nghttp3_qpack_stream_context_reset(nghttp3_qpack_stream_context *sctx) {
- nghttp3_qpack_stream_context_init(sctx, sctx->stream_id, sctx->mem);
-}
-
-uint64_t
-nghttp3_qpack_stream_context_get_ricnt(nghttp3_qpack_stream_context *sctx) {
- return sctx->ricnt;
-}
-
-nghttp3_ssize
-nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv, uint8_t *pflags,
- const uint8_t *src, size_t srclen, int fin) {
- const uint8_t *p = src, *end = src ? src + srclen : src;
- int rv;
- int busy = 0;
- nghttp3_ssize nread;
- int rfin;
- const nghttp3_mem *mem = decoder->ctx.mem;
-
- if (decoder->ctx.bad) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- *pflags = NGHTTP3_QPACK_DECODE_FLAG_NONE;
-
- for (; p != end || busy;) {
- busy = 0;
- switch (sctx->state) {
- case NGHTTP3_QPACK_RS_STATE_RICNT:
- nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- goto almost_ok;
- }
-
- rv = nghttp3_qpack_decoder_reconstruct_ricnt(decoder, &sctx->ricnt,
- sctx->rstate.left);
- if (rv != 0) {
- goto fail;
- }
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_DBASE_SIGN;
- break;
- case NGHTTP3_QPACK_RS_STATE_DBASE_SIGN:
- if ((*p) & 0x80) {
- sctx->dbase_sign = 1;
- }
- sctx->state = NGHTTP3_QPACK_RS_STATE_DBASE;
- sctx->rstate.left = 0;
- sctx->rstate.prefix = 7;
- sctx->rstate.shift = 0;
- /* Fall through */
- case NGHTTP3_QPACK_RS_STATE_DBASE:
- nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- goto almost_ok;
- }
-
- if (sctx->dbase_sign) {
- if (sctx->ricnt < sctx->rstate.left) {
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
- sctx->base = sctx->ricnt - sctx->rstate.left - 1;
- } else {
- sctx->base = sctx->ricnt + sctx->rstate.left;
- }
-
- DEBUGF("qpack::decode: ricnt=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64
- "\n",
- sctx->ricnt, sctx->base, decoder->ctx.next_absidx);
-
- if (sctx->ricnt > decoder->ctx.next_absidx) {
- DEBUGF("qpack::decode: stream blocked\n");
- sctx->state = NGHTTP3_QPACK_RS_STATE_BLOCKED;
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_BLOCKED;
- return p - src;
- }
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- sctx->rstate.left = 0;
- sctx->rstate.shift = 0;
- break;
- case NGHTTP3_QPACK_RS_STATE_OPCODE:
- assert(sctx->rstate.left == 0);
- assert(sctx->rstate.shift == 0);
- if ((*p) & 0x80) {
- DEBUGF("qpack::decode: OPCODE_INDEXED\n");
- sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED;
- sctx->rstate.dynamic = !((*p) & 0x40);
- sctx->rstate.prefix = 6;
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
- } else if ((*p) & 0x40) {
- DEBUGF("qpack::decode: OPCODE_INDEXED_NAME\n");
- sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME;
- sctx->rstate.never = (*p) & 0x20;
- sctx->rstate.dynamic = !((*p) & 0x10);
- sctx->rstate.prefix = 4;
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
- } else if ((*p) & 0x20) {
- DEBUGF("qpack::decode: OPCODE_LITERAL\n");
- sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_LITERAL;
- sctx->rstate.never = (*p) & 0x10;
- sctx->rstate.dynamic = 0;
- sctx->rstate.prefix = 3;
- sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN;
- } else if ((*p) & 0x10) {
- DEBUGF("qpack::decode: OPCODE_INDEXED_PB\n");
- sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB;
- sctx->rstate.dynamic = 1;
- sctx->rstate.prefix = 4;
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
- } else {
- DEBUGF("qpack::decode: OPCODE_INDEXED_NAME_PB\n");
- sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB;
- sctx->rstate.never = (*p) & 0x08;
- sctx->rstate.dynamic = 1;
- sctx->rstate.prefix = 3;
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX;
- }
- break;
- case NGHTTP3_QPACK_RS_STATE_READ_INDEX:
- nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- goto almost_ok;
- }
-
- switch (sctx->opcode) {
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED:
- rv = nghttp3_qpack_decoder_brel2abs(decoder, sctx);
- if (rv != 0) {
- goto fail;
- }
- nghttp3_qpack_decoder_emit_indexed(decoder, sctx, nv);
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&sctx->rstate);
-
- return p - src;
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB:
- rv = nghttp3_qpack_decoder_pbrel2abs(decoder, sctx);
- if (rv != 0) {
- goto fail;
- }
- nghttp3_qpack_decoder_emit_indexed(decoder, sctx, nv);
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&sctx->rstate);
-
- return p - src;
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
- rv = nghttp3_qpack_decoder_brel2abs(decoder, sctx);
- if (rv != 0) {
- goto fail;
- }
- sctx->rstate.prefix = 7;
- sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
- break;
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
- rv = nghttp3_qpack_decoder_pbrel2abs(decoder, sctx);
- if (rv != 0) {
- goto fail;
- }
- sctx->rstate.prefix = 7;
- sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- break;
- case NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN:
- qpack_read_state_check_huffman(&sctx->rstate, *p);
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAMELEN;
- sctx->rstate.left = 0;
- sctx->rstate.shift = 0;
- /* Fall through */
- case NGHTTP3_QPACK_RS_STATE_READ_NAMELEN:
- nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- goto almost_ok;
- }
-
- if (sctx->rstate.left > NGHTTP3_QPACK_MAX_NAMELEN) {
- rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
- goto fail;
- }
-
- if (sctx->rstate.huffman_encoded) {
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAME_HUFFMAN;
- nghttp3_qpack_huffman_decode_context_init(&sctx->rstate.huffman_ctx);
- rv = nghttp3_rcbuf_new(&sctx->rstate.name,
- (size_t)sctx->rstate.left * 2 + 1, mem);
- } else {
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_NAME;
- rv = nghttp3_rcbuf_new(&sctx->rstate.name,
- (size_t)sctx->rstate.left + 1, mem);
- }
- if (rv != 0) {
- goto fail;
- }
-
- nghttp3_buf_wrap_init(&sctx->rstate.namebuf, sctx->rstate.name->base,
- sctx->rstate.name->len);
- break;
- case NGHTTP3_QPACK_RS_STATE_READ_NAME_HUFFMAN:
- nread = qpack_read_huffman_string(&sctx->rstate, &sctx->rstate.namebuf, p,
- end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (sctx->rstate.left) {
- goto almost_ok;
- }
-
- qpack_read_state_terminate_name(&sctx->rstate);
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
- sctx->rstate.prefix = 7;
- break;
- case NGHTTP3_QPACK_RS_STATE_READ_NAME:
- nread = qpack_read_string(&sctx->rstate, &sctx->rstate.namebuf, p, end);
- if (nread < 0) {
- rv = (int)nread;
- goto fail;
- }
-
- p += nread;
-
- if (sctx->rstate.left) {
- goto almost_ok;
- }
-
- qpack_read_state_terminate_name(&sctx->rstate);
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN;
- sctx->rstate.prefix = 7;
- break;
- case NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN:
- qpack_read_state_check_huffman(&sctx->rstate, *p);
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUELEN;
- sctx->rstate.left = 0;
- sctx->rstate.shift = 0;
- /* Fall through */
- case NGHTTP3_QPACK_RS_STATE_READ_VALUELEN:
- nread = qpack_read_varint(&rfin, &sctx->rstate, p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (!rfin) {
- goto almost_ok;
- }
-
- if (sctx->rstate.left > NGHTTP3_QPACK_MAX_VALUELEN) {
- rv = NGHTTP3_ERR_QPACK_HEADER_TOO_LARGE;
- goto fail;
- }
-
- if (sctx->rstate.huffman_encoded) {
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUE_HUFFMAN;
- nghttp3_qpack_huffman_decode_context_init(&sctx->rstate.huffman_ctx);
- rv = nghttp3_rcbuf_new(&sctx->rstate.value,
- (size_t)sctx->rstate.left * 2 + 1, mem);
- } else {
- sctx->state = NGHTTP3_QPACK_RS_STATE_READ_VALUE;
- rv = nghttp3_rcbuf_new(&sctx->rstate.value,
- (size_t)sctx->rstate.left + 1, mem);
- }
- if (rv != 0) {
- goto fail;
- }
-
- nghttp3_buf_wrap_init(&sctx->rstate.valuebuf, sctx->rstate.value->base,
- sctx->rstate.value->len);
-
- /* value might be 0 length */
- busy = 1;
- break;
- case NGHTTP3_QPACK_RS_STATE_READ_VALUE_HUFFMAN:
- nread = qpack_read_huffman_string(&sctx->rstate, &sctx->rstate.valuebuf,
- p, end);
- if (nread < 0) {
- assert(NGHTTP3_ERR_QPACK_FATAL == nread);
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- p += nread;
-
- if (sctx->rstate.left) {
- goto almost_ok;
- }
-
- qpack_read_state_terminate_value(&sctx->rstate);
-
- switch (sctx->opcode) {
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
- nghttp3_qpack_decoder_emit_indexed_name(decoder, sctx, nv);
- break;
- case NGHTTP3_QPACK_RS_OPCODE_LITERAL:
- nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&sctx->rstate);
-
- return p - src;
- case NGHTTP3_QPACK_RS_STATE_READ_VALUE:
- nread = qpack_read_string(&sctx->rstate, &sctx->rstate.valuebuf, p, end);
- if (nread < 0) {
- rv = (int)nread;
- goto fail;
- }
-
- p += nread;
-
- if (sctx->rstate.left) {
- goto almost_ok;
- }
-
- qpack_read_state_terminate_value(&sctx->rstate);
-
- switch (sctx->opcode) {
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME:
- case NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB:
- nghttp3_qpack_decoder_emit_indexed_name(decoder, sctx, nv);
- break;
- case NGHTTP3_QPACK_RS_OPCODE_LITERAL:
- nghttp3_qpack_decoder_emit_literal(decoder, sctx, nv);
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_EMIT;
-
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&sctx->rstate);
-
- return p - src;
- case NGHTTP3_QPACK_RS_STATE_BLOCKED:
- if (sctx->ricnt > decoder->ctx.next_absidx) {
- DEBUGF("qpack::decode: stream still blocked\n");
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_BLOCKED;
- return p - src;
- }
- sctx->state = NGHTTP3_QPACK_RS_STATE_OPCODE;
- nghttp3_qpack_read_state_reset(&sctx->rstate);
- break;
- }
- }
-
-almost_ok:
- if (fin) {
- if (sctx->state != NGHTTP3_QPACK_RS_STATE_OPCODE) {
- rv = NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- goto fail;
- }
-
- *pflags |= NGHTTP3_QPACK_DECODE_FLAG_FINAL;
-
- if (sctx->ricnt) {
- rv = nghttp3_qpack_decoder_write_section_ack(decoder, sctx);
- if (rv != 0) {
- goto fail;
- }
- }
- }
-
- return p - src;
-
-fail:
- decoder->ctx.bad = 1;
- return rv;
-}
-
-static int qpack_decoder_dbuf_overflow(nghttp3_qpack_decoder *decoder) {
- size_t limit = nghttp3_max(decoder->max_concurrent_streams, 100);
- /* 10 = nghttp3_qpack_put_varint_len((1ULL << 62) - 1, 2)) */
- return nghttp3_buf_len(&decoder->dbuf) > limit * 2 * 10;
-}
-
-int nghttp3_qpack_decoder_write_section_ack(
- nghttp3_qpack_decoder *decoder, const nghttp3_qpack_stream_context *sctx) {
- nghttp3_buf *dbuf = &decoder->dbuf;
- uint8_t *p;
- int rv;
-
- if (qpack_decoder_dbuf_overflow(decoder)) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- rv = reserve_buf_small(
- dbuf, nghttp3_qpack_put_varint_len((uint64_t)sctx->stream_id, 7),
- decoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = dbuf->last;
- *p = 0x80;
- dbuf->last = nghttp3_qpack_put_varint(p, (uint64_t)sctx->stream_id, 7);
-
- if (decoder->written_icnt < sctx->ricnt) {
- decoder->written_icnt = sctx->ricnt;
- }
-
- return 0;
-}
-
-size_t
-nghttp3_qpack_decoder_get_decoder_streamlen(nghttp3_qpack_decoder *decoder) {
- uint64_t n;
- size_t len = 0;
-
- if (decoder->written_icnt < decoder->ctx.next_absidx) {
- n = decoder->ctx.next_absidx - decoder->written_icnt;
- len = nghttp3_qpack_put_varint_len(n, 6);
- }
-
- return nghttp3_buf_len(&decoder->dbuf) + len;
-}
-
-void nghttp3_qpack_decoder_write_decoder(nghttp3_qpack_decoder *decoder,
- nghttp3_buf *dbuf) {
- uint8_t *p;
- uint64_t n = 0;
- size_t len = 0;
-
- if (decoder->written_icnt < decoder->ctx.next_absidx) {
- n = decoder->ctx.next_absidx - decoder->written_icnt;
- len = nghttp3_qpack_put_varint_len(n, 6);
- }
-
- assert(nghttp3_buf_left(dbuf) >= nghttp3_buf_len(&decoder->dbuf) + len);
-
- if (nghttp3_buf_len(&decoder->dbuf)) {
- dbuf->last = nghttp3_cpymem(dbuf->last, decoder->dbuf.pos,
- nghttp3_buf_len(&decoder->dbuf));
- }
-
- if (n) {
- p = dbuf->last;
- *p = 0;
- dbuf->last = nghttp3_qpack_put_varint(p, n, 6);
-
- decoder->written_icnt = decoder->ctx.next_absidx;
- }
-
- nghttp3_buf_reset(&decoder->dbuf);
-}
-
-int nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder,
- int64_t stream_id) {
- uint8_t *p;
- int rv;
-
- if (qpack_decoder_dbuf_overflow(decoder)) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- rv = reserve_buf(&decoder->dbuf,
- nghttp3_qpack_put_varint_len((uint64_t)stream_id, 6),
- decoder->ctx.mem);
- if (rv != 0) {
- return rv;
- }
-
- p = decoder->dbuf.last;
- *p = 0x40;
- decoder->dbuf.last = nghttp3_qpack_put_varint(p, (uint64_t)stream_id, 6);
-
- return 0;
-}
-
-int nghttp3_qpack_decoder_reconstruct_ricnt(nghttp3_qpack_decoder *decoder,
- uint64_t *dest, uint64_t encricnt) {
- uint64_t max_ents, full, max, max_wrapped, ricnt;
-
- if (encricnt == 0) {
- *dest = 0;
- return 0;
- }
-
- max_ents = decoder->ctx.hard_max_dtable_size / NGHTTP3_QPACK_ENTRY_OVERHEAD;
- full = 2 * max_ents;
-
- if (encricnt > full) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
-
- max = decoder->ctx.next_absidx + max_ents;
- max_wrapped = max / full * full;
- ricnt = max_wrapped + encricnt - 1;
-
- if (ricnt > max) {
- if (ricnt <= full) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
- ricnt -= full;
- }
-
- if (ricnt == 0) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
-
- *dest = ricnt;
-
- return 0;
-}
-
-int nghttp3_qpack_decoder_rel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_read_state *rstate) {
- DEBUGF("qpack::decode: dynamic=%d relidx=%" PRIu64 " icnt=%" PRIu64 "\n",
- rstate->dynamic, rstate->left, decoder->ctx.next_absidx);
-
- if (rstate->dynamic) {
- if (decoder->ctx.next_absidx < rstate->left + 1) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
- rstate->absidx = decoder->ctx.next_absidx - rstate->left - 1;
- } else {
- rstate->absidx = rstate->left;
- }
- if (qpack_decoder_validate_index(decoder, rstate) != 0) {
- return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR;
- }
- return 0;
-}
-
-int nghttp3_qpack_decoder_brel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx) {
- nghttp3_qpack_read_state *rstate = &sctx->rstate;
-
- DEBUGF("qpack::decode: dynamic=%d relidx=%" PRIu64 " base=%" PRIu64
- " icnt=%" PRIu64 "\n",
- rstate->dynamic, rstate->left, sctx->base, decoder->ctx.next_absidx);
-
- if (rstate->dynamic) {
- if (sctx->base < rstate->left + 1) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
- rstate->absidx = sctx->base - rstate->left - 1;
-
- if (rstate->absidx >= sctx->ricnt) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
- } else {
- rstate->absidx = rstate->left;
- }
-
- if (qpack_decoder_validate_index(decoder, rstate) != 0) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
- return 0;
-}
-
-int nghttp3_qpack_decoder_pbrel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx) {
- nghttp3_qpack_read_state *rstate = &sctx->rstate;
-
- DEBUGF("qpack::decode: pbidx=%" PRIu64 " base=%" PRIu64 " icnt=%" PRIu64 "\n",
- rstate->left, sctx->base, decoder->ctx.next_absidx);
-
- assert(rstate->dynamic);
-
- rstate->absidx = rstate->left + sctx->base;
-
- if (rstate->absidx >= sctx->ricnt) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
-
- if (qpack_decoder_validate_index(decoder, rstate) != 0) {
- return NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED;
- }
- return 0;
-}
-
-static void
-qpack_decoder_emit_static_indexed(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- const nghttp3_qpack_static_header *shd = &stable[sctx->rstate.absidx];
- (void)decoder;
-
- nv->name = (nghttp3_rcbuf *)&shd->name;
- nv->value = (nghttp3_rcbuf *)&shd->value;
- nv->token = shd->token;
- nv->flags = NGHTTP3_NV_FLAG_NONE;
-}
-
-static void
-qpack_decoder_emit_dynamic_indexed(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- nghttp3_qpack_entry *ent =
- nghttp3_qpack_context_dtable_get(&decoder->ctx, sctx->rstate.absidx);
-
- *nv = ent->nv;
-
- nghttp3_rcbuf_incref(nv->name);
- nghttp3_rcbuf_incref(nv->value);
-}
-
-void nghttp3_qpack_decoder_emit_indexed(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- DEBUGF("qpack::decode: Indexed (%s) absidx=%" PRIu64 "\n",
- sctx->rstate.dynamic ? "dynamic" : "static", sctx->rstate.absidx);
-
- if (sctx->rstate.dynamic) {
- qpack_decoder_emit_dynamic_indexed(decoder, sctx, nv);
- } else {
- qpack_decoder_emit_static_indexed(decoder, sctx, nv);
- }
-}
-
-static void
-qpack_decoder_emit_static_indexed_name(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- const nghttp3_qpack_static_header *shd = &stable[sctx->rstate.absidx];
- (void)decoder;
-
- nv->name = (nghttp3_rcbuf *)&shd->name;
- nv->value = sctx->rstate.value;
- nv->token = shd->token;
- nv->flags =
- sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
-
- sctx->rstate.value = NULL;
-}
-
-static void
-qpack_decoder_emit_dynamic_indexed_name(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- nghttp3_qpack_entry *ent =
- nghttp3_qpack_context_dtable_get(&decoder->ctx, sctx->rstate.absidx);
- (void)decoder;
-
- nv->name = ent->nv.name;
- nv->value = sctx->rstate.value;
- nv->token = ent->nv.token;
- nv->flags =
- sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
-
- nghttp3_rcbuf_incref(nv->name);
-
- sctx->rstate.value = NULL;
-}
-
-void nghttp3_qpack_decoder_emit_indexed_name(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- (void)decoder;
-
- DEBUGF("qpack::decode: Indexed name (%s) absidx=%" PRIu64 " value=%*s\n",
- sctx->rstate.dynamic ? "dynamic" : "static", sctx->rstate.absidx,
- (int)sctx->rstate.value->len, sctx->rstate.value->base);
-
- if (sctx->rstate.dynamic) {
- qpack_decoder_emit_dynamic_indexed_name(decoder, sctx, nv);
- } else {
- qpack_decoder_emit_static_indexed_name(decoder, sctx, nv);
- }
-}
-
-void nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv) {
- (void)decoder;
-
- DEBUGF("qpack::decode: Emit literal name=%*s value=%*s\n",
- (int)sctx->rstate.name->len, sctx->rstate.name->base,
- (int)sctx->rstate.value->len, sctx->rstate.value->base);
-
- nv->name = sctx->rstate.name;
- nv->value = sctx->rstate.value;
- nv->token = qpack_lookup_token(nv->name->base, nv->name->len);
- nv->flags =
- sctx->rstate.never ? NGHTTP3_NV_FLAG_NEVER_INDEX : NGHTTP3_NV_FLAG_NONE;
-
- sctx->rstate.name = NULL;
- sctx->rstate.value = NULL;
-}
-
-int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem) {
- int rv;
- nghttp3_qpack_encoder *p;
-
- p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder));
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- rv = nghttp3_qpack_encoder_init(p, max_dtable_size, max_blocked, mem);
- if (rv != 0) {
- return rv;
- }
-
- *pencoder = p;
-
- return 0;
-}
-
-void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder) {
- const nghttp3_mem *mem;
-
- if (encoder == NULL) {
- return;
- }
-
- mem = encoder->ctx.mem;
-
- nghttp3_qpack_encoder_free(encoder);
- nghttp3_mem_free(mem, encoder);
-}
-
-int nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx,
- int64_t stream_id,
- const nghttp3_mem *mem) {
- nghttp3_qpack_stream_context *p;
-
- p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream_context));
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- nghttp3_qpack_stream_context_init(p, stream_id, mem);
-
- *psctx = p;
-
- return 0;
-}
-
-void nghttp3_qpack_stream_context_del(nghttp3_qpack_stream_context *sctx) {
- const nghttp3_mem *mem;
-
- if (sctx == NULL) {
- return;
- }
-
- mem = sctx->mem;
-
- nghttp3_qpack_stream_context_free(sctx);
- nghttp3_mem_free(mem, sctx);
-}
-
-int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem) {
- int rv;
- nghttp3_qpack_decoder *p;
-
- p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_decoder));
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- rv = nghttp3_qpack_decoder_init(p, max_dtable_size, max_blocked, mem);
- if (rv != 0) {
- return rv;
- }
-
- *pdecoder = p;
-
- return 0;
-}
-
-void nghttp3_qpack_decoder_del(nghttp3_qpack_decoder *decoder) {
- const nghttp3_mem *mem;
-
- if (decoder == NULL) {
- return;
- }
-
- mem = decoder->ctx.mem;
-
- nghttp3_qpack_decoder_free(decoder);
- nghttp3_mem_free(mem, decoder);
-}
-
-uint64_t nghttp3_qpack_decoder_get_icnt(const nghttp3_qpack_decoder *decoder) {
- return decoder->ctx.next_absidx;
-}
diff --git a/deps/nghttp3/lib/nghttp3_qpack.h b/deps/nghttp3/lib/nghttp3_qpack.h
deleted file mode 100644
index ddfb2b6638..0000000000
--- a/deps/nghttp3/lib/nghttp3_qpack.h
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_QPACK_H
-#define NGHTTP3_QPACK_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_rcbuf.h"
-#include "nghttp3_map.h"
-#include "nghttp3_pq.h"
-#include "nghttp3_ringbuf.h"
-#include "nghttp3_buf.h"
-#include "nghttp3_ksl.h"
-#include "nghttp3_qpack_huffman.h"
-
-#define NGHTTP3_QPACK_INT_MAX ((1ull << 62) - 1)
-
-/* NGHTTP3_QPACK_MAX_NAMELEN is the maximum (compressed) length of
- header name this library can decode. */
-#define NGHTTP3_QPACK_MAX_NAMELEN 256
-/* NGHTTP3_QPACK_MAX_VALUELEN is the maximum (compressed) length of
- header value this library can decode. */
-#define NGHTTP3_QPACK_MAX_VALUELEN 65536
-
-/* nghttp3_qpack_indexing_mode is a indexing strategy. */
-typedef enum {
- /* NGHTTP3_QPACK_INDEXING_MODE_LITERAL means that header field
- should not be inserted into dynamic table. */
- NGHTTP3_QPACK_INDEXING_MODE_LITERAL,
- /* NGHTTP3_QPACK_INDEXING_MODE_STORE means that header field can be
- inserted into dynamic table. */
- NGHTTP3_QPACK_INDEXING_MODE_STORE,
- /* NGHTTP3_QPACK_INDEXING_MODE_NEVER means that header field should
- not be inserted into dynamic table and this must be true for all
- forwarding paths. */
- NGHTTP3_QPACK_INDEXING_MODE_NEVER,
-} nghttp3_qpack_indexing_mode;
-
-struct nghttp3_qpack_entry;
-typedef struct nghttp3_qpack_entry nghttp3_qpack_entry;
-
-struct nghttp3_qpack_entry {
- /* The header field name/value pair */
- nghttp3_qpack_nv nv;
- /* map_next points to the entry which shares same bucket in hash
- table. */
- nghttp3_qpack_entry *map_next;
- /* sum is the sum of all entries inserted up to this entry. This
- value does not contain the space required for this entry. */
- size_t sum;
- /* absidx is the absolute index of this entry. */
- uint64_t absidx;
- /* The hash value for header name (nv.name). */
- uint32_t hash;
-};
-
-/* The entry used for static table. */
-typedef struct {
- uint64_t absidx;
- int32_t token;
- uint32_t hash;
-} nghttp3_qpack_static_entry;
-
-typedef struct {
- nghttp3_rcbuf name;
- nghttp3_rcbuf value;
- int32_t token;
-} nghttp3_qpack_static_header;
-
-/*
- * nghttp3_qpack_header_block_ref is created per encoded header block
- * and includes the required insert count and the minimum insert count
- * of dynamic table entry it refers to.
- */
-typedef struct {
- nghttp3_pq_entry max_cnts_pe;
- nghttp3_pq_entry min_cnts_pe;
- /* max_cnt is the required insert count. */
- uint64_t max_cnt;
- /* min_cnt is the minimum insert count of dynamic table entry it
- refers to. In other words, this is the minimum absolute index of
- dynamic header table entry this encoded block refers to plus
- 1. */
- uint64_t min_cnt;
-} nghttp3_qpack_header_block_ref;
-
-int nghttp3_qpack_header_block_ref_new(nghttp3_qpack_header_block_ref **pref,
- uint64_t max_cnt, uint64_t min_cnt,
- const nghttp3_mem *mem);
-
-void nghttp3_qpack_header_block_ref_del(nghttp3_qpack_header_block_ref *ref,
- const nghttp3_mem *mem);
-
-typedef struct {
- nghttp3_map_entry me;
- /* refs is an array of pointer to nghttp3_qpack_header_block_ref in
- the order of the time they are encoded. HTTP/3 allows multiple
- header blocks (e.g., non-final response headers, final response
- headers, trailers, and push promises) per stream. */
- nghttp3_ringbuf refs;
- /* max_cnts is a priority queue sorted by descending order of
- max_cnt of nghttp3_qpack_header_block_ref. */
- nghttp3_pq max_cnts;
-} nghttp3_qpack_stream;
-
-int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
- const nghttp3_mem *mem);
-
-void nghttp3_qpack_stream_del(nghttp3_qpack_stream *stream,
- const nghttp3_mem *mem);
-
-uint64_t nghttp3_qpack_stream_get_max_cnt(const nghttp3_qpack_stream *stream);
-
-int nghttp3_qpack_stream_add_ref(nghttp3_qpack_stream *stream,
- nghttp3_qpack_header_block_ref *ref);
-
-void nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream);
-
-#define NGHTTP3_QPACK_ENTRY_OVERHEAD 32
-
-typedef struct {
- /* dtable is a dynamic table */
- nghttp3_ringbuf dtable;
- /* mem is memory allocator */
- const nghttp3_mem *mem;
- /* dtable_size is abstracted buffer size of dtable as described in
- the spec. This is the sum of length of name/value in dtable +
- NGHTTP3_QPACK_ENTRY_OVERHEAD bytes overhead per each entry. */
- size_t dtable_size;
- size_t dtable_sum;
- /* hard_max_dtable_size is the maximum size of dynamic table. In
- HTTP/3, it is notified by decoder as
- SETTINGS_QPACK_MAX_TABLE_CAPACITY. Any value lower than or equal
- to SETTINGS_QPACK_MAX_TABLE_CAPACITY is OK because encoder has
- the authority to decide how many entries are inserted into
- dynamic table. */
- size_t hard_max_dtable_size;
- /* max_dtable_size is the effective maximum size of dynamic table. */
- size_t max_dtable_size;
- /* max_blocked is the maximum number of stream which can be
- blocked. */
- size_t max_blocked;
- /* next_absidx is the next absolute index for nghttp3_qpack_entry.
- It is equivalent to insert count. */
- uint64_t next_absidx;
- /* If inflate/deflate error occurred, this value is set to 1 and
- further invocation of inflate/deflate will fail with
- NGHTTP3_ERR_QPACK_FATAL. */
- uint8_t bad;
-} nghttp3_qpack_context;
-
-typedef struct {
- nghttp3_qpack_huffman_decode_context huffman_ctx;
- nghttp3_buf namebuf;
- nghttp3_buf valuebuf;
- nghttp3_rcbuf *name;
- nghttp3_rcbuf *value;
- uint64_t left;
- size_t prefix;
- size_t shift;
- uint64_t absidx;
- int never;
- int dynamic;
- int huffman_encoded;
-} nghttp3_qpack_read_state;
-
-void nghttp3_qpack_read_state_free(nghttp3_qpack_read_state *rstate);
-
-void nghttp3_qpack_read_state_reset(nghttp3_qpack_read_state *rstate);
-
-#define NGHTTP3_QPACK_MAP_SIZE 64
-
-typedef struct {
- nghttp3_qpack_entry *table[NGHTTP3_QPACK_MAP_SIZE];
-} nghttp3_qpack_map;
-
-/* nghttp3_qpack_decoder_stream_state is a set of states when decoding
- decoder stream. */
-typedef enum {
- NGHTTP3_QPACK_DS_STATE_OPCODE,
- NGHTTP3_QPACK_DS_STATE_READ_NUMBER,
-} nghttp3_qpack_decoder_stream_state;
-
-/* nghttp3_qpack_decoder_stream_opcode is opcode used in decoder
- stream. */
-typedef enum {
- NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT,
- NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK,
- NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL,
-} nghttp3_qpack_decoder_stream_opcode;
-
-/* nghttp3_qpack_encoder_flag is a set of flags used by
- nghttp3_qpack_encoder. */
-typedef enum {
- NGHTTP3_QPACK_ENCODER_FLAG_NONE = 0x00,
- /* NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP indicates that
- Set Dynamic Table Capacity is required. */
- NGHTTP3_QPACK_ENCODER_FLAG_PENDING_SET_DTABLE_CAP = 0x01,
-} nghttp3_qpack_encoder_flag;
-
-struct nghttp3_qpack_encoder {
- nghttp3_qpack_context ctx;
- /* dtable_map is a map of hash to nghttp3_qpack_entry to provide
- fast access to an entry in dynamic table. */
- nghttp3_qpack_map dtable_map;
- /* streams is a map of stream ID to nghttp3_qpack_stream to keep
- track of unacknowledged streams. */
- nghttp3_map streams;
- /* blocked_streams is an ordered list of nghttp3_qpack_stream, in
- descending order of max_cnt, to search the unblocked streams by
- received known count. */
- nghttp3_ksl blocked_streams;
- /* min_cnts is a priority queue of nghttp3_qpack_header_block_ref
- sorted by ascending order of min_cnt to know that an entry can be
- evicted from dynamic table. */
- nghttp3_pq min_cnts;
- /* krcnt is Known Received Count. */
- uint64_t krcnt;
- /* state is a current state of reading decoder stream. */
- nghttp3_qpack_decoder_stream_state state;
- /* opcode is a decoder stream opcode being processed. */
- nghttp3_qpack_decoder_stream_opcode opcode;
- /* rstate is a set of intermediate state which are used to process
- decoder stream. */
- nghttp3_qpack_read_state rstate;
- /* min_dtable_update is the minimum dynamic table size required. */
- size_t min_dtable_update;
- /* last_max_dtable_update is the dynamic table size last
- requested. */
- size_t last_max_dtable_update;
- /* flags is bitwise OR of zero or more of
- nghttp3_qpack_encoder_flag. */
- uint8_t flags;
-};
-
-/*
- * nghttp3_qpack_encoder_init initializes |encoder|.
- * |max_dtable_size| is the maximum size of dynamic table.
- * |max_blocked| is the maximum number of stream which can be blocked.
- * |mem| is a memory allocator.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_qpack_encoder_free frees memory allocated for |encoder|.
- * This function does not free memory pointed by |encoder|.
- */
-void nghttp3_qpack_encoder_free(nghttp3_qpack_encoder *encoder);
-
-/*
- * nghttp3_qpack_encoder_encode_nv encodes |nv|. It writes request
- * stream into |rbuf| and writes encoder stream into |ebuf|. |nv| is
- * a header field to encode. |base| is base. |allow_blocking| is
- * nonzero if this stream can be blocked (or it has been blocked
- * already).
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
- uint64_t *pmax_cnt, uint64_t *pmin_cnt,
- nghttp3_buf *rbuf, nghttp3_buf *ebuf,
- const nghttp3_nv *nv, uint64_t base,
- int allow_blocking);
-
-/* nghttp3_qpack_lookup_result stores a result of table lookup. */
-typedef struct {
- /* index is an index of matched entry. -1 if no match is made. */
- nghttp3_ssize index;
- /* name_value_match is nonzero if both name and value are
- matched. */
- int name_value_match;
- /* pb_index is the absolute index of matched post-based dynamic
- table entry. -1 if no such entry exists. */
- nghttp3_ssize pb_index;
-} nghttp3_qpack_lookup_result;
-
-/*
- * nghttp3_qpack_lookup_stable searches |nv| in static table. |token|
- * is a token of nv->name and it is -1 if there is no corresponding
- * token defined. |indexing_mode| provides indexing strategy.
- */
-nghttp3_qpack_lookup_result
-nghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
- nghttp3_qpack_indexing_mode indexing_mode);
-
-/*
- * nghttp3_qpack_encoder_lookup_dtable searches |nv| in dynamic table.
- * |token| is a token of nv->name and it is -1 if there is no
- * corresponding token defined. |hash| is a hash of nv->name.
- * |indexing_mode| provides indexing strategy. |krcnt| is Known
- * Received Count. |allow_blocking| is nonzero if this stream can be
- * blocked (or it has been blocked already).
- */
-nghttp3_qpack_lookup_result nghttp3_qpack_encoder_lookup_dtable(
- nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
- uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
- int allow_blocking);
-
-/*
- * nghttp3_qpack_encoder_write_field_section_prefix writes Encoded
- * Field Section Prefix into |pbuf|. |ricnt| is Required Insert
- * Count. |base| is Base.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_field_section_prefix(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *pbuf, uint64_t ricnt,
- uint64_t base);
-
-/*
- * nghttp3_qpack_encoder_write_static_indexed writes Indexed Header
- * Field to |rbuf|. |absidx| is an absolute index into static table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_static_indexed(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- uint64_t absidx);
-
-/*
- * nghttp3_qpack_encoder_write_dynamic_indexed writes Indexed Header
- * Field to |rbuf|. |absidx| is an absolute index into dynamic table.
- * |base| is base.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_dynamic_indexed(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- uint64_t absidx, uint64_t base);
-
-/*
- * nghttp3_qpack_encoder_write_static_indexed writes Literal Header
- * Field With Name Reference to |rbuf|. |absidx| is an absolute index
- * into static table to reference a name. |nv| is a header field to
- * encode.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_static_indexed_name(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
- const nghttp3_nv *nv);
-
-/*
- * nghttp3_qpack_encoder_write_dynamic_indexed writes Literal Header
- * Field With Name Reference to |rbuf|. |absidx| is an absolute index
- * into dynamic table to reference a name. |base| is a base. |nv| is
- * a header field to encode.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_dynamic_indexed_name(
- nghttp3_qpack_encoder *encoder, nghttp3_buf *rbuf, uint64_t absidx,
- uint64_t base, const nghttp3_nv *nv);
-
-/*
- * nghttp3_qpack_encoder_write_literal writes Literal Header Field
- * Without Name Reference to |rbuf|. |nv| is a header field to
- * encode.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *rbuf,
- const nghttp3_nv *nv);
-
-/*
- * nghttp3_qpack_encoder_write_static_insert writes Insert With Name
- * Reference to |ebuf|. |absidx| is an absolute index into static
- * table to reference a name. |nv| is a header field to insert.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_static_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx,
- const nghttp3_nv *nv);
-
-/*
- * nghttp3_qpack_encoder_write_dynamic_insert writes Insert With Name
- * Reference to |ebuf|. |absidx| is an absolute index into dynamic
- * table to reference a name. |nv| is a header field to insert.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_dynamic_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx,
- const nghttp3_nv *nv);
-
-/*
- * nghttp3_qpack_encoder_write_duplicate_insert writes Duplicate to
- * |ebuf|. |absidx| is an absolute index into dynamic table to
- * reference an entry.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_duplicate_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- uint64_t absidx);
-
-/*
- * nghttp3_qpack_encoder_write_literal_insert writes Insert Without
- * Name Reference to |ebuf|. |nv| is a header field to insert.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_literal_insert(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf,
- const nghttp3_nv *nv);
-
-int nghttp3_qpack_encoder_stream_is_blocked(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream);
-
-/*
- * nghttp3_qpack_encoder_block_stream blocks |stream|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream);
-
-/*
- * nghttp3_qpack_encoder_unblock_stream unblocks |stream|.
- */
-void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
- nghttp3_qpack_stream *stream);
-
-/*
- * nghttp3_qpack_encoder_unblock unblocks stream whose max_cnt is less
- * than or equal to |max_cnt|.
- */
-void nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
- uint64_t max_cnt);
-
-/*
- * nghttp3_qpack_encoder_find_stream returns stream whose stream ID is
- * |stream_id|. This function returns NULL if there is no such
- * stream.
- */
-nghttp3_qpack_stream *
-nghttp3_qpack_encoder_find_stream(nghttp3_qpack_encoder *encoder,
- int64_t stream_id);
-
-uint64_t nghttp3_qpack_encoder_get_min_cnt(nghttp3_qpack_encoder *encoder);
-
-/*
- * nghttp3_qpack_encoder_shrink_dtable shrinks dynamic table so that
- * the dynamic table size is less than or equal to maximum size.
- */
-void nghttp3_qpack_encoder_shrink_dtable(nghttp3_qpack_encoder *encoder);
-
-/*
- * nghttp3_qpack_encoder_process_dtable_update processes pending
- * dynamic table size update. It might write encoder stream into
- * |ebuf|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_process_dtable_update(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf);
-
-/*
- * nghttp3_qpack_encoder_write_set_dtable_cap writes Set Dynamic Table
- * Capacity. to |ebuf|. |cap| is the capacity of dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_write_set_dtable_cap(nghttp3_qpack_encoder *encoder,
- nghttp3_buf *ebuf, size_t cap);
-
-/*
- * nghttp3_qpack_context_dtable_add adds |qnv| to dynamic table. If
- * |ctx| is a part of encoder, |dtable_map| is not NULL. |hash| is a
- * hash value of name.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_context_dtable_add(nghttp3_qpack_context *ctx,
- nghttp3_qpack_nv *qnv,
- nghttp3_qpack_map *dtable_map,
- uint32_t hash);
-
-/*
- * nghttp3_qpack_encoder_dtable_static_add adds |nv| to dynamic table
- * by referencing static table entry at an absolute index |absidx|.
- * The hash of name is given as |hash|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_dtable_static_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx,
- const nghttp3_nv *nv,
- uint32_t hash);
-
-/*
- * nghttp3_qpack_encoder_dtable_dynamic_add adds |nv| to dynamic table
- * by referencing dynamic table entry at an absolute index |absidx|.
- * The hash of name is given as |hash|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_dtable_dynamic_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx,
- const nghttp3_nv *nv,
- uint32_t hash);
-
-/*
- * nghttp3_qpack_encoder_dtable_duplicate_add duplicates dynamic table
- * entry at an absolute index |absidx|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_encoder_dtable_duplicate_add(nghttp3_qpack_encoder *encoder,
- uint64_t absidx);
-
-/*
- * nghttp3_qpack_encoder_dtable_literal_add adds |nv| to dynamic
- * table. |token| is a token of name and is -1 if it has no token
- * value defined. |hash| is a hash of name.
- *
- * NGHTTP3_ERR_NOMEM Out of memory.
- */
-int nghttp3_qpack_encoder_dtable_literal_add(nghttp3_qpack_encoder *encoder,
- const nghttp3_nv *nv,
- int32_t token, uint32_t hash);
-
-/*
- * nghttp3_qpack_context_dtable_get returns dynamic table entry whose
- * absolute index is |absidx|. This function assumes that such entry
- * exists.
- */
-nghttp3_qpack_entry *
-nghttp3_qpack_context_dtable_get(nghttp3_qpack_context *ctx, uint64_t absidx);
-
-/*
- * nghttp3_qpack_context_dtable_top returns latest dynamic table
- * entry. This function assumes dynamic table is not empty.
- */
-nghttp3_qpack_entry *
-nghttp3_qpack_context_dtable_top(nghttp3_qpack_context *ctx);
-
-/*
- * nghttp3_qpack_entry_init initializes |ent|. |qnv| is a header
- * field. |sum| is the sum of table space occupied by all entries
- * inserted so far. It does not include this entry. |absidx| is an
- * absolute index of this entry. |hash| is a hash of header field
- * name. This function increases reference count of qnv->nv.name and
- * qnv->nv.value.
- */
-void nghttp3_qpack_entry_init(nghttp3_qpack_entry *ent, nghttp3_qpack_nv *qnv,
- size_t sum, uint64_t absidx, uint32_t hash);
-
-/*
- * nghttp3_qpack_entry_free frees memory allocated for |ent|.
- */
-void nghttp3_qpack_entry_free(nghttp3_qpack_entry *ent);
-
-/*
- * nghttp3_qpack_put_varint_len returns the required number of bytes
- * to encode |n| with |prefix| bits.
- */
-size_t nghttp3_qpack_put_varint_len(uint64_t n, size_t prefix);
-
-/*
- * nghttp3_qpack_put_varint encodes |n| using variable integer
- * encoding with |prefix| bits into |buf|. This function assumes the
- * buffer pointed by |buf| has enough space. This function returns
- * the one byte beyond the last write (buf +
- * nghttp3_qpack_put_varint_len(n, prefix)).
- */
-uint8_t *nghttp3_qpack_put_varint(uint8_t *buf, uint64_t n, size_t prefix);
-
-/* nghttp3_qpack_encoder_stream_state is a set of states for encoder
- stream decoding. */
-typedef enum {
- NGHTTP3_QPACK_ES_STATE_OPCODE,
- NGHTTP3_QPACK_ES_STATE_READ_INDEX,
- NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN,
- NGHTTP3_QPACK_ES_STATE_READ_NAMELEN,
- NGHTTP3_QPACK_ES_STATE_READ_NAME_HUFFMAN,
- NGHTTP3_QPACK_ES_STATE_READ_NAME,
- NGHTTP3_QPACK_ES_STATE_CHECK_VALUE_HUFFMAN,
- NGHTTP3_QPACK_ES_STATE_READ_VALUELEN,
- NGHTTP3_QPACK_ES_STATE_READ_VALUE_HUFFMAN,
- NGHTTP3_QPACK_ES_STATE_READ_VALUE,
-} nghttp3_qpack_encoder_stream_state;
-
-/* nghttp3_qpack_encoder_stream_opcode is a set of opcodes used in
- encoder stream. */
-typedef enum {
- NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED,
- NGHTTP3_QPACK_ES_OPCODE_INSERT,
- NGHTTP3_QPACK_ES_OPCODE_DUPLICATE,
- NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP,
-} nghttp3_qpack_encoder_stream_opcode;
-
-/* nghttp3_qpack_request_stream_state is a set of states for request
- stream decoding. */
-typedef enum {
- NGHTTP3_QPACK_RS_STATE_RICNT,
- NGHTTP3_QPACK_RS_STATE_DBASE_SIGN,
- NGHTTP3_QPACK_RS_STATE_DBASE,
- NGHTTP3_QPACK_RS_STATE_OPCODE,
- NGHTTP3_QPACK_RS_STATE_READ_INDEX,
- NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN,
- NGHTTP3_QPACK_RS_STATE_READ_NAMELEN,
- NGHTTP3_QPACK_RS_STATE_READ_NAME_HUFFMAN,
- NGHTTP3_QPACK_RS_STATE_READ_NAME,
- NGHTTP3_QPACK_RS_STATE_CHECK_VALUE_HUFFMAN,
- NGHTTP3_QPACK_RS_STATE_READ_VALUELEN,
- NGHTTP3_QPACK_RS_STATE_READ_VALUE_HUFFMAN,
- NGHTTP3_QPACK_RS_STATE_READ_VALUE,
- NGHTTP3_QPACK_RS_STATE_BLOCKED,
-} nghttp3_qpack_request_stream_state;
-
-/* nghttp3_qpack_request_stream_opcode is a set of opcodes used in
- request stream. */
-typedef enum {
- NGHTTP3_QPACK_RS_OPCODE_INDEXED,
- NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB,
- NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME,
- NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB,
- NGHTTP3_QPACK_RS_OPCODE_LITERAL,
-} nghttp3_qpack_request_stream_opcode;
-
-struct nghttp3_qpack_decoder {
- nghttp3_qpack_context ctx;
- /* state is a current state of reading encoder stream. */
- nghttp3_qpack_encoder_stream_state state;
- /* opcode is an encoder stream opcode being processed. */
- nghttp3_qpack_encoder_stream_opcode opcode;
- /* rstate is a set of intermediate state which are used to process
- encoder stream. */
- nghttp3_qpack_read_state rstate;
- /* dbuf is decoder stream. */
- nghttp3_buf dbuf;
- /* written_icnt is Insert Count written to decoder stream so far. */
- uint64_t written_icnt;
- /* max_concurrent_streams is the number of concurrent streams that a
- remote endpoint can open, including both bidirectional and
- unidirectional streams which potentially receives QPACK encoded
- HEADER frame. */
- size_t max_concurrent_streams;
-};
-
-/*
- * nghttp3_qpack_decoder_init initializes |decoder|.
- * |max_dtable_size| is the maximum size of dynamic table.
- * |max_blocked| is the maximum number of stream which can be blocked.
- * |mem| is a memory allocator.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
- size_t max_dtable_size, size_t max_blocked,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_qpack_decoder_free frees memory allocated for |decoder|.
- * This function does not free memory pointed by |decoder|.
- */
-void nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder);
-
-/*
- * nghttp3_qpack_decoder_dtable_indexed_add adds entry received in
- * Insert With Name Reference to dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Space required for a decoded entry exceeds max dynamic table
- * size.
- */
-int nghttp3_qpack_decoder_dtable_indexed_add(nghttp3_qpack_decoder *decoder);
-
-/*
- * nghttp3_qpack_decoder_dtable_static_add adds entry received in
- * Insert With Name Reference (static) to dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Space required for a decoded entry exceeds max dynamic table
- * size.
- */
-int nghttp3_qpack_decoder_dtable_static_add(nghttp3_qpack_decoder *decoder);
-
-/*
- * nghttp3_qpack_decoder_dtable_dynamic_add adds entry received in
- * Insert With Name Reference (dynamic) to dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Space required for a decoded entry exceeds max dynamic table
- * size.
- */
-int nghttp3_qpack_decoder_dtable_dynamic_add(nghttp3_qpack_decoder *decoder);
-
-/*
- * nghttp3_qpack_decoder_dtable_duplicate_add adds entry received in
- * Duplicate to dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Space required for a decoded entry exceeds max dynamic table
- * size.
- */
-int nghttp3_qpack_decoder_dtable_duplicate_add(nghttp3_qpack_decoder *decoder);
-
-/*
- * nghttp3_qpack_decoder_dtable_literal_add adds entry received in
- * Insert Without Name Reference to dynamic table.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Space required for a decoded entry exceeds max dynamic table
- * size.
- */
-int nghttp3_qpack_decoder_dtable_literal_add(nghttp3_qpack_decoder *decoder);
-
-struct nghttp3_qpack_stream_context {
- /* state is a current state of reading request stream. */
- nghttp3_qpack_request_stream_state state;
- /* rstate is a set of intermediate state which are used to process
- request stream. */
- nghttp3_qpack_read_state rstate;
- const nghttp3_mem *mem;
- /* opcode is a request stream opcode being processed. */
- nghttp3_qpack_request_stream_opcode opcode;
- int64_t stream_id;
- /* ricnt is Required Insert Count to decode this header block. */
- uint64_t ricnt;
- /* base is Base in Header Block Prefix. */
- uint64_t base;
- /* dbase_sign is the delta base sign in Header Block Prefix. */
- int dbase_sign;
-};
-
-/*
- * nghttp3_qpack_stream_context_init initializes |sctx|.
- */
-void nghttp3_qpack_stream_context_init(nghttp3_qpack_stream_context *sctx,
- int64_t stream_id,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_qpack_stream_context_free frees memory allocated for
- * |sctx|. This function does not free memory pointed by |sctx|.
- */
-void nghttp3_qpack_stream_context_free(nghttp3_qpack_stream_context *sctx);
-
-void nghttp3_qpack_stream_context_reset(nghttp3_qpack_stream_context *sctx);
-
-/*
- * nghttp3_qpack_decoder_reconstruct_ricnt reconstructs Required
- * Insert Count from the encoded form |encricnt| and stores Required
- * Insert Count in |*dest|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED
- * Unable to reconstruct Required Insert Count.
- */
-int nghttp3_qpack_decoder_reconstruct_ricnt(nghttp3_qpack_decoder *decoder,
- uint64_t *dest, uint64_t encricnt);
-
-/*
- * nghttp3_qpack_decoder_rel2abs converts relative index rstate->left
- * received in encoder stream to absolute index and stores it in
- * rstate->absidx.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_QPACK_ENCODER_STREAM
- * Relative index is invalid.
- */
-int nghttp3_qpack_decoder_rel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_read_state *rstate);
-
-/*
- * nghttp3_qpack_decoder_brel2abs converts Base relative index
- * rstate->left received in request stream to absolute index and
- * stores it in rstate->absidx.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED
- * Base relative index is invalid.
- */
-int nghttp3_qpack_decoder_brel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx);
-
-/*
- * nghttp3_qpack_decoder_pbrel2abs converts Post-Base relative index
- * rstate->left received in request stream to absolute index and
- * stores it in rstate->absidx.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_QPACK_DECOMPRESSION_FAILED
- * Post-Base relative index is invalid.
- */
-int nghttp3_qpack_decoder_pbrel2abs(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx);
-
-void nghttp3_qpack_decoder_emit_indexed(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv);
-
-void nghttp3_qpack_decoder_emit_indexed_name(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv);
-
-void nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder,
- nghttp3_qpack_stream_context *sctx,
- nghttp3_qpack_nv *nv);
-
-/*
- * nghttp3_qpack_decoder_write_section_ack writes Section
- * Acknowledgement to decoder stream.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- * NGHTTP3_ERR_QPACK_FATAL
- * Decoder stream overflow.
- */
-int nghttp3_qpack_decoder_write_section_ack(
- nghttp3_qpack_decoder *decoder, const nghttp3_qpack_stream_context *sctx);
-
-#endif /* NGHTTP3_QPACK_H */
diff --git a/deps/nghttp3/lib/nghttp3_qpack_huffman.c b/deps/nghttp3/lib/nghttp3_qpack_huffman.c
deleted file mode 100644
index c36a68eded..0000000000
--- a/deps/nghttp3/lib/nghttp3_qpack_huffman.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_qpack_huffman.h"
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "nghttp3_conv.h"
-
-size_t nghttp3_qpack_huffman_encode_count(const uint8_t *src, size_t len) {
- size_t i;
- size_t nbits = 0;
-
- for (i = 0; i < len; ++i) {
- nbits += huffman_sym_table[src[i]].nbits;
- }
- /* pad the prefix of EOS (256) */
- return (nbits + 7) / 8;
-}
-
-uint8_t *nghttp3_qpack_huffman_encode(uint8_t *dest, const uint8_t *src,
- size_t srclen) {
- const nghttp3_qpack_huffman_sym *sym;
- const uint8_t *end = src + srclen;
- uint64_t code = 0;
- size_t nbits = 0;
- uint32_t x;
-
- for (; src != end;) {
- sym = &huffman_sym_table[*src++];
- code |= (uint64_t)sym->code << (32 - nbits);
- nbits += sym->nbits;
- if (nbits < 32) {
- continue;
- }
- x = htonl((uint32_t)(code >> 32));
- memcpy(dest, &x, 4);
- dest += 4;
- code <<= 32;
- nbits -= 32;
- }
-
- for (; nbits >= 8;) {
- *dest++ = (uint8_t)(code >> 56);
- code <<= 8;
- nbits -= 8;
- }
-
- if (nbits) {
- *dest++ = (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1));
- }
-
- return dest;
-}
-
-void nghttp3_qpack_huffman_decode_context_init(
- nghttp3_qpack_huffman_decode_context *ctx) {
- ctx->fstate = NGHTTP3_QPACK_HUFFMAN_ACCEPTED;
-}
-
-nghttp3_ssize
-nghttp3_qpack_huffman_decode(nghttp3_qpack_huffman_decode_context *ctx,
- uint8_t *dest, const uint8_t *src, size_t srclen,
- int fin) {
- uint8_t *p = dest;
- const uint8_t *end = src + srclen;
- nghttp3_qpack_huffman_decode_node node = {ctx->fstate, 0};
- const nghttp3_qpack_huffman_decode_node *t = &node;
- uint8_t c;
-
- /* We use the decoding algorithm described in
- http://graphics.ics.uci.edu/pub/Prefix.pdf */
- for (; src != end;) {
- c = *src++;
- t = &qpack_huffman_decode_table[t->fstate & 0x1ff][c >> 4];
- if (t->fstate & NGHTTP3_QPACK_HUFFMAN_SYM) {
- *p++ = t->sym;
- }
-
- t = &qpack_huffman_decode_table[t->fstate & 0x1ff][c & 0xf];
- if (t->fstate & NGHTTP3_QPACK_HUFFMAN_SYM) {
- *p++ = t->sym;
- }
- }
-
- ctx->fstate = t->fstate;
-
- if (fin && !(ctx->fstate & NGHTTP3_QPACK_HUFFMAN_ACCEPTED)) {
- return NGHTTP3_ERR_QPACK_FATAL;
- }
-
- return p - dest;
-}
-
-int nghttp3_qpack_huffman_decode_failure_state(
- nghttp3_qpack_huffman_decode_context *ctx) {
- return ctx->fstate == 0x100;
-}
diff --git a/deps/nghttp3/lib/nghttp3_qpack_huffman.h b/deps/nghttp3/lib/nghttp3_qpack_huffman.h
deleted file mode 100644
index 0cab6ed93e..0000000000
--- a/deps/nghttp3/lib/nghttp3_qpack_huffman.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_QPACK_HUFFMAN_H
-#define NGHTTP3_QPACK_HUFFMAN_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-typedef struct {
- /* The number of bits in this code */
- uint32_t nbits;
- /* Huffman code aligned to LSB */
- uint32_t code;
-} nghttp3_qpack_huffman_sym;
-
-extern const nghttp3_qpack_huffman_sym huffman_sym_table[];
-
-size_t nghttp3_qpack_huffman_encode_count(const uint8_t *src, size_t len);
-
-uint8_t *nghttp3_qpack_huffman_encode(uint8_t *dest, const uint8_t *src,
- size_t srclen);
-
-typedef enum {
- /* FSA accepts this state as the end of huffman encoding
- sequence. */
- NGHTTP3_QPACK_HUFFMAN_ACCEPTED = 1 << 14,
- /* This state emits symbol */
- NGHTTP3_QPACK_HUFFMAN_SYM = 1 << 15,
-} nghttp3_qpack_huffman_decode_flag;
-
-typedef struct {
- /* fstate is the current huffman decoding state, which is actually
- the node ID of internal huffman tree with
- nghttp3_qpack_huffman_decode_flag OR-ed. We have 257 leaf nodes,
- but they are identical to root node other than emitting a symbol,
- so we have 256 internal nodes [1..256], inclusive. The node ID
- 256 is a special node and it is a terminal state that means
- decoding failed. */
- uint16_t fstate;
- /* symbol if NGHTTP3_QPACK_HUFFMAN_SYM flag set */
- uint8_t sym;
-} nghttp3_qpack_huffman_decode_node;
-
-typedef struct {
- /* fstate is the current huffman decoding state. */
- uint16_t fstate;
-} nghttp3_qpack_huffman_decode_context;
-
-extern const nghttp3_qpack_huffman_decode_node qpack_huffman_decode_table[][16];
-
-void nghttp3_qpack_huffman_decode_context_init(
- nghttp3_qpack_huffman_decode_context *ctx);
-
-/*
- * nghttp3_qpack_huffman_decode decodes huffman encoded byte string
- * stored in |src| of length |srclen|. |ctx| is a decoding context.
- * |ctx| remembers the decoding state, and caller can call this
- * function multiple times to feed each chunk of huffman encoded
- * substring. |fin| must be nonzero if |src| contains the last chunk
- * of huffman string. The decoded string is written to the buffer
- * pointed by |dest|. This function assumes that the buffer pointed
- * by |dest| contains enough memory to store decoded byte string.
- *
- * This function returns the number of bytes written to |dest|, or one
- * of the following negative error codes:
- *
- * NGHTTP3_ERR_QPACK_FATAL
- * Could not decode huffman string.
- */
-nghttp3_ssize
-nghttp3_qpack_huffman_decode(nghttp3_qpack_huffman_decode_context *ctx,
- uint8_t *dest, const uint8_t *src, size_t srclen,
- int fin);
-
-/*
- * nghttp3_qpack_huffman_decode_failure_state returns nonzero if |ctx|
- * indicates that huffman decoding context is in failure state.
- */
-int nghttp3_qpack_huffman_decode_failure_state(
- nghttp3_qpack_huffman_decode_context *ctx);
-
-#endif /* NGHTTP3_QPACK_HUFFMAN_H */
diff --git a/deps/nghttp3/lib/nghttp3_qpack_huffman_data.c b/deps/nghttp3/lib/nghttp3_qpack_huffman_data.c
deleted file mode 100644
index 0c104dbc0a..0000000000
--- a/deps/nghttp3/lib/nghttp3_qpack_huffman_data.c
+++ /dev/null
@@ -1,4981 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2013 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_qpack_huffman.h"
-
-/* Generated by mkhufftbl.py */
-
-const nghttp3_qpack_huffman_sym huffman_sym_table[] = {
- {13, 0xffc00000u}, {23, 0xffffb000u}, {28, 0xfffffe20u}, {28, 0xfffffe30u},
- {28, 0xfffffe40u}, {28, 0xfffffe50u}, {28, 0xfffffe60u}, {28, 0xfffffe70u},
- {28, 0xfffffe80u}, {24, 0xffffea00u}, {30, 0xfffffff0u}, {28, 0xfffffe90u},
- {28, 0xfffffea0u}, {30, 0xfffffff4u}, {28, 0xfffffeb0u}, {28, 0xfffffec0u},
- {28, 0xfffffed0u}, {28, 0xfffffee0u}, {28, 0xfffffef0u}, {28, 0xffffff00u},
- {28, 0xffffff10u}, {28, 0xffffff20u}, {30, 0xfffffff8u}, {28, 0xffffff30u},
- {28, 0xffffff40u}, {28, 0xffffff50u}, {28, 0xffffff60u}, {28, 0xffffff70u},
- {28, 0xffffff80u}, {28, 0xffffff90u}, {28, 0xffffffa0u}, {28, 0xffffffb0u},
- {6, 0x50000000u}, {10, 0xfe000000u}, {10, 0xfe400000u}, {12, 0xffa00000u},
- {13, 0xffc80000u}, {6, 0x54000000u}, {8, 0xf8000000u}, {11, 0xff400000u},
- {10, 0xfe800000u}, {10, 0xfec00000u}, {8, 0xf9000000u}, {11, 0xff600000u},
- {8, 0xfa000000u}, {6, 0x58000000u}, {6, 0x5c000000u}, {6, 0x60000000u},
- {5, 0x0u}, {5, 0x8000000u}, {5, 0x10000000u}, {6, 0x64000000u},
- {6, 0x68000000u}, {6, 0x6c000000u}, {6, 0x70000000u}, {6, 0x74000000u},
- {6, 0x78000000u}, {6, 0x7c000000u}, {7, 0xb8000000u}, {8, 0xfb000000u},
- {15, 0xfff80000u}, {6, 0x80000000u}, {12, 0xffb00000u}, {10, 0xff000000u},
- {13, 0xffd00000u}, {6, 0x84000000u}, {7, 0xba000000u}, {7, 0xbc000000u},
- {7, 0xbe000000u}, {7, 0xc0000000u}, {7, 0xc2000000u}, {7, 0xc4000000u},
- {7, 0xc6000000u}, {7, 0xc8000000u}, {7, 0xca000000u}, {7, 0xcc000000u},
- {7, 0xce000000u}, {7, 0xd0000000u}, {7, 0xd2000000u}, {7, 0xd4000000u},
- {7, 0xd6000000u}, {7, 0xd8000000u}, {7, 0xda000000u}, {7, 0xdc000000u},
- {7, 0xde000000u}, {7, 0xe0000000u}, {7, 0xe2000000u}, {7, 0xe4000000u},
- {8, 0xfc000000u}, {7, 0xe6000000u}, {8, 0xfd000000u}, {13, 0xffd80000u},
- {19, 0xfffe0000u}, {13, 0xffe00000u}, {14, 0xfff00000u}, {6, 0x88000000u},
- {15, 0xfffa0000u}, {5, 0x18000000u}, {6, 0x8c000000u}, {5, 0x20000000u},
- {6, 0x90000000u}, {5, 0x28000000u}, {6, 0x94000000u}, {6, 0x98000000u},
- {6, 0x9c000000u}, {5, 0x30000000u}, {7, 0xe8000000u}, {7, 0xea000000u},
- {6, 0xa0000000u}, {6, 0xa4000000u}, {6, 0xa8000000u}, {5, 0x38000000u},
- {6, 0xac000000u}, {7, 0xec000000u}, {6, 0xb0000000u}, {5, 0x40000000u},
- {5, 0x48000000u}, {6, 0xb4000000u}, {7, 0xee000000u}, {7, 0xf0000000u},
- {7, 0xf2000000u}, {7, 0xf4000000u}, {7, 0xf6000000u}, {15, 0xfffc0000u},
- {11, 0xff800000u}, {14, 0xfff40000u}, {13, 0xffe80000u}, {28, 0xffffffc0u},
- {20, 0xfffe6000u}, {22, 0xffff4800u}, {20, 0xfffe7000u}, {20, 0xfffe8000u},
- {22, 0xffff4c00u}, {22, 0xffff5000u}, {22, 0xffff5400u}, {23, 0xffffb200u},
- {22, 0xffff5800u}, {23, 0xffffb400u}, {23, 0xffffb600u}, {23, 0xffffb800u},
- {23, 0xffffba00u}, {23, 0xffffbc00u}, {24, 0xffffeb00u}, {23, 0xffffbe00u},
- {24, 0xffffec00u}, {24, 0xffffed00u}, {22, 0xffff5c00u}, {23, 0xffffc000u},
- {24, 0xffffee00u}, {23, 0xffffc200u}, {23, 0xffffc400u}, {23, 0xffffc600u},
- {23, 0xffffc800u}, {21, 0xfffee000u}, {22, 0xffff6000u}, {23, 0xffffca00u},
- {22, 0xffff6400u}, {23, 0xffffcc00u}, {23, 0xffffce00u}, {24, 0xffffef00u},
- {22, 0xffff6800u}, {21, 0xfffee800u}, {20, 0xfffe9000u}, {22, 0xffff6c00u},
- {22, 0xffff7000u}, {23, 0xffffd000u}, {23, 0xffffd200u}, {21, 0xfffef000u},
- {23, 0xffffd400u}, {22, 0xffff7400u}, {22, 0xffff7800u}, {24, 0xfffff000u},
- {21, 0xfffef800u}, {22, 0xffff7c00u}, {23, 0xffffd600u}, {23, 0xffffd800u},
- {21, 0xffff0000u}, {21, 0xffff0800u}, {22, 0xffff8000u}, {21, 0xffff1000u},
- {23, 0xffffda00u}, {22, 0xffff8400u}, {23, 0xffffdc00u}, {23, 0xffffde00u},
- {20, 0xfffea000u}, {22, 0xffff8800u}, {22, 0xffff8c00u}, {22, 0xffff9000u},
- {23, 0xffffe000u}, {22, 0xffff9400u}, {22, 0xffff9800u}, {23, 0xffffe200u},
- {26, 0xfffff800u}, {26, 0xfffff840u}, {20, 0xfffeb000u}, {19, 0xfffe2000u},
- {22, 0xffff9c00u}, {23, 0xffffe400u}, {22, 0xffffa000u}, {25, 0xfffff600u},
- {26, 0xfffff880u}, {26, 0xfffff8c0u}, {26, 0xfffff900u}, {27, 0xfffffbc0u},
- {27, 0xfffffbe0u}, {26, 0xfffff940u}, {24, 0xfffff100u}, {25, 0xfffff680u},
- {19, 0xfffe4000u}, {21, 0xffff1800u}, {26, 0xfffff980u}, {27, 0xfffffc00u},
- {27, 0xfffffc20u}, {26, 0xfffff9c0u}, {27, 0xfffffc40u}, {24, 0xfffff200u},
- {21, 0xffff2000u}, {21, 0xffff2800u}, {26, 0xfffffa00u}, {26, 0xfffffa40u},
- {28, 0xffffffd0u}, {27, 0xfffffc60u}, {27, 0xfffffc80u}, {27, 0xfffffca0u},
- {20, 0xfffec000u}, {24, 0xfffff300u}, {20, 0xfffed000u}, {21, 0xffff3000u},
- {22, 0xffffa400u}, {21, 0xffff3800u}, {21, 0xffff4000u}, {23, 0xffffe600u},
- {22, 0xffffa800u}, {22, 0xffffac00u}, {25, 0xfffff700u}, {25, 0xfffff780u},
- {24, 0xfffff400u}, {24, 0xfffff500u}, {26, 0xfffffa80u}, {23, 0xffffe800u},
- {26, 0xfffffac0u}, {27, 0xfffffcc0u}, {26, 0xfffffb00u}, {26, 0xfffffb40u},
- {27, 0xfffffce0u}, {27, 0xfffffd00u}, {27, 0xfffffd20u}, {27, 0xfffffd40u},
- {27, 0xfffffd60u}, {28, 0xffffffe0u}, {27, 0xfffffd80u}, {27, 0xfffffda0u},
- {27, 0xfffffdc0u}, {27, 0xfffffde0u}, {27, 0xfffffe00u}, {26, 0xfffffb80u},
- {30, 0xfffffffcu}};
-
-const nghttp3_qpack_huffman_decode_node qpack_huffman_decode_table[][16] = {
- /* 0 */
- {
- {0x04, 0},
- {0x05, 0},
- {0x07, 0},
- {0x08, 0},
- {0x0b, 0},
- {0x0c, 0},
- {0x10, 0},
- {0x13, 0},
- {0x19, 0},
- {0x1c, 0},
- {0x20, 0},
- {0x23, 0},
- {0x2a, 0},
- {0x31, 0},
- {0x39, 0},
- {0x4040, 0},
- },
- /* 1 */
- {
- {0xc000, 48},
- {0xc000, 49},
- {0xc000, 50},
- {0xc000, 97},
- {0xc000, 99},
- {0xc000, 101},
- {0xc000, 105},
- {0xc000, 111},
- {0xc000, 115},
- {0xc000, 116},
- {0x0d, 0},
- {0x0e, 0},
- {0x11, 0},
- {0x12, 0},
- {0x14, 0},
- {0x15, 0},
- },
- /* 2 */
- {
- {0x8001, 48},
- {0xc016, 48},
- {0x8001, 49},
- {0xc016, 49},
- {0x8001, 50},
- {0xc016, 50},
- {0x8001, 97},
- {0xc016, 97},
- {0x8001, 99},
- {0xc016, 99},
- {0x8001, 101},
- {0xc016, 101},
- {0x8001, 105},
- {0xc016, 105},
- {0x8001, 111},
- {0xc016, 111},
- },
- /* 3 */
- {
- {0x8002, 48},
- {0x8009, 48},
- {0x8017, 48},
- {0xc028, 48},
- {0x8002, 49},
- {0x8009, 49},
- {0x8017, 49},
- {0xc028, 49},
- {0x8002, 50},
- {0x8009, 50},
- {0x8017, 50},
- {0xc028, 50},
- {0x8002, 97},
- {0x8009, 97},
- {0x8017, 97},
- {0xc028, 97},
- },
- /* 4 */
- {
- {0x8003, 48},
- {0x8006, 48},
- {0x800a, 48},
- {0x800f, 48},
- {0x8018, 48},
- {0x801f, 48},
- {0x8029, 48},
- {0xc038, 48},
- {0x8003, 49},
- {0x8006, 49},
- {0x800a, 49},
- {0x800f, 49},
- {0x8018, 49},
- {0x801f, 49},
- {0x8029, 49},
- {0xc038, 49},
- },
- /* 5 */
- {
- {0x8003, 50},
- {0x8006, 50},
- {0x800a, 50},
- {0x800f, 50},
- {0x8018, 50},
- {0x801f, 50},
- {0x8029, 50},
- {0xc038, 50},
- {0x8003, 97},
- {0x8006, 97},
- {0x800a, 97},
- {0x800f, 97},
- {0x8018, 97},
- {0x801f, 97},
- {0x8029, 97},
- {0xc038, 97},
- },
- /* 6 */
- {
- {0x8002, 99},
- {0x8009, 99},
- {0x8017, 99},
- {0xc028, 99},
- {0x8002, 101},
- {0x8009, 101},
- {0x8017, 101},
- {0xc028, 101},
- {0x8002, 105},
- {0x8009, 105},
- {0x8017, 105},
- {0xc028, 105},
- {0x8002, 111},
- {0x8009, 111},
- {0x8017, 111},
- {0xc028, 111},
- },
- /* 7 */
- {
- {0x8003, 99},
- {0x8006, 99},
- {0x800a, 99},
- {0x800f, 99},
- {0x8018, 99},
- {0x801f, 99},
- {0x8029, 99},
- {0xc038, 99},
- {0x8003, 101},
- {0x8006, 101},
- {0x800a, 101},
- {0x800f, 101},
- {0x8018, 101},
- {0x801f, 101},
- {0x8029, 101},
- {0xc038, 101},
- },
- /* 8 */
- {
- {0x8003, 105},
- {0x8006, 105},
- {0x800a, 105},
- {0x800f, 105},
- {0x8018, 105},
- {0x801f, 105},
- {0x8029, 105},
- {0xc038, 105},
- {0x8003, 111},
- {0x8006, 111},
- {0x800a, 111},
- {0x800f, 111},
- {0x8018, 111},
- {0x801f, 111},
- {0x8029, 111},
- {0xc038, 111},
- },
- /* 9 */
- {
- {0x8001, 115},
- {0xc016, 115},
- {0x8001, 116},
- {0xc016, 116},
- {0xc000, 32},
- {0xc000, 37},
- {0xc000, 45},
- {0xc000, 46},
- {0xc000, 47},
- {0xc000, 51},
- {0xc000, 52},
- {0xc000, 53},
- {0xc000, 54},
- {0xc000, 55},
- {0xc000, 56},
- {0xc000, 57},
- },
- /* 10 */
- {
- {0x8002, 115},
- {0x8009, 115},
- {0x8017, 115},
- {0xc028, 115},
- {0x8002, 116},
- {0x8009, 116},
- {0x8017, 116},
- {0xc028, 116},
- {0x8001, 32},
- {0xc016, 32},
- {0x8001, 37},
- {0xc016, 37},
- {0x8001, 45},
- {0xc016, 45},
- {0x8001, 46},
- {0xc016, 46},
- },
- /* 11 */
- {
- {0x8003, 115},
- {0x8006, 115},
- {0x800a, 115},
- {0x800f, 115},
- {0x8018, 115},
- {0x801f, 115},
- {0x8029, 115},
- {0xc038, 115},
- {0x8003, 116},
- {0x8006, 116},
- {0x800a, 116},
- {0x800f, 116},
- {0x8018, 116},
- {0x801f, 116},
- {0x8029, 116},
- {0xc038, 116},
- },
- /* 12 */
- {
- {0x8002, 32},
- {0x8009, 32},
- {0x8017, 32},
- {0xc028, 32},
- {0x8002, 37},
- {0x8009, 37},
- {0x8017, 37},
- {0xc028, 37},
- {0x8002, 45},
- {0x8009, 45},
- {0x8017, 45},
- {0xc028, 45},
- {0x8002, 46},
- {0x8009, 46},
- {0x8017, 46},
- {0xc028, 46},
- },
- /* 13 */
- {
- {0x8003, 32},
- {0x8006, 32},
- {0x800a, 32},
- {0x800f, 32},
- {0x8018, 32},
- {0x801f, 32},
- {0x8029, 32},
- {0xc038, 32},
- {0x8003, 37},
- {0x8006, 37},
- {0x800a, 37},
- {0x800f, 37},
- {0x8018, 37},
- {0x801f, 37},
- {0x8029, 37},
- {0xc038, 37},
- },
- /* 14 */
- {
- {0x8003, 45},
- {0x8006, 45},
- {0x800a, 45},
- {0x800f, 45},
- {0x8018, 45},
- {0x801f, 45},
- {0x8029, 45},
- {0xc038, 45},
- {0x8003, 46},
- {0x8006, 46},
- {0x800a, 46},
- {0x800f, 46},
- {0x8018, 46},
- {0x801f, 46},
- {0x8029, 46},
- {0xc038, 46},
- },
- /* 15 */
- {
- {0x8001, 47},
- {0xc016, 47},
- {0x8001, 51},
- {0xc016, 51},
- {0x8001, 52},
- {0xc016, 52},
- {0x8001, 53},
- {0xc016, 53},
- {0x8001, 54},
- {0xc016, 54},
- {0x8001, 55},
- {0xc016, 55},
- {0x8001, 56},
- {0xc016, 56},
- {0x8001, 57},
- {0xc016, 57},
- },
- /* 16 */
- {
- {0x8002, 47},
- {0x8009, 47},
- {0x8017, 47},
- {0xc028, 47},
- {0x8002, 51},
- {0x8009, 51},
- {0x8017, 51},
- {0xc028, 51},
- {0x8002, 52},
- {0x8009, 52},
- {0x8017, 52},
- {0xc028, 52},
- {0x8002, 53},
- {0x8009, 53},
- {0x8017, 53},
- {0xc028, 53},
- },
- /* 17 */
- {
- {0x8003, 47},
- {0x8006, 47},
- {0x800a, 47},
- {0x800f, 47},
- {0x8018, 47},
- {0x801f, 47},
- {0x8029, 47},
- {0xc038, 47},
- {0x8003, 51},
- {0x8006, 51},
- {0x800a, 51},
- {0x800f, 51},
- {0x8018, 51},
- {0x801f, 51},
- {0x8029, 51},
- {0xc038, 51},
- },
- /* 18 */
- {
- {0x8003, 52},
- {0x8006, 52},
- {0x800a, 52},
- {0x800f, 52},
- {0x8018, 52},
- {0x801f, 52},
- {0x8029, 52},
- {0xc038, 52},
- {0x8003, 53},
- {0x8006, 53},
- {0x800a, 53},
- {0x800f, 53},
- {0x8018, 53},
- {0x801f, 53},
- {0x8029, 53},
- {0xc038, 53},
- },
- /* 19 */
- {
- {0x8002, 54},
- {0x8009, 54},
- {0x8017, 54},
- {0xc028, 54},
- {0x8002, 55},
- {0x8009, 55},
- {0x8017, 55},
- {0xc028, 55},
- {0x8002, 56},
- {0x8009, 56},
- {0x8017, 56},
- {0xc028, 56},
- {0x8002, 57},
- {0x8009, 57},
- {0x8017, 57},
- {0xc028, 57},
- },
- /* 20 */
- {
- {0x8003, 54},
- {0x8006, 54},
- {0x800a, 54},
- {0x800f, 54},
- {0x8018, 54},
- {0x801f, 54},
- {0x8029, 54},
- {0xc038, 54},
- {0x8003, 55},
- {0x8006, 55},
- {0x800a, 55},
- {0x800f, 55},
- {0x8018, 55},
- {0x801f, 55},
- {0x8029, 55},
- {0xc038, 55},
- },
- /* 21 */
- {
- {0x8003, 56},
- {0x8006, 56},
- {0x800a, 56},
- {0x800f, 56},
- {0x8018, 56},
- {0x801f, 56},
- {0x8029, 56},
- {0xc038, 56},
- {0x8003, 57},
- {0x8006, 57},
- {0x800a, 57},
- {0x800f, 57},
- {0x8018, 57},
- {0x801f, 57},
- {0x8029, 57},
- {0xc038, 57},
- },
- /* 22 */
- {
- {0x1a, 0},
- {0x1b, 0},
- {0x1d, 0},
- {0x1e, 0},
- {0x21, 0},
- {0x22, 0},
- {0x24, 0},
- {0x25, 0},
- {0x2b, 0},
- {0x2e, 0},
- {0x32, 0},
- {0x35, 0},
- {0x3a, 0},
- {0x3d, 0},
- {0x41, 0},
- {0x4044, 0},
- },
- /* 23 */
- {
- {0xc000, 61},
- {0xc000, 65},
- {0xc000, 95},
- {0xc000, 98},
- {0xc000, 100},
- {0xc000, 102},
- {0xc000, 103},
- {0xc000, 104},
- {0xc000, 108},
- {0xc000, 109},
- {0xc000, 110},
- {0xc000, 112},
- {0xc000, 114},
- {0xc000, 117},
- {0x26, 0},
- {0x27, 0},
- },
- /* 24 */
- {
- {0x8001, 61},
- {0xc016, 61},
- {0x8001, 65},
- {0xc016, 65},
- {0x8001, 95},
- {0xc016, 95},
- {0x8001, 98},
- {0xc016, 98},
- {0x8001, 100},
- {0xc016, 100},
- {0x8001, 102},
- {0xc016, 102},
- {0x8001, 103},
- {0xc016, 103},
- {0x8001, 104},
- {0xc016, 104},
- },
- /* 25 */
- {
- {0x8002, 61},
- {0x8009, 61},
- {0x8017, 61},
- {0xc028, 61},
- {0x8002, 65},
- {0x8009, 65},
- {0x8017, 65},
- {0xc028, 65},
- {0x8002, 95},
- {0x8009, 95},
- {0x8017, 95},
- {0xc028, 95},
- {0x8002, 98},
- {0x8009, 98},
- {0x8017, 98},
- {0xc028, 98},
- },
- /* 26 */
- {
- {0x8003, 61},
- {0x8006, 61},
- {0x800a, 61},
- {0x800f, 61},
- {0x8018, 61},
- {0x801f, 61},
- {0x8029, 61},
- {0xc038, 61},
- {0x8003, 65},
- {0x8006, 65},
- {0x800a, 65},
- {0x800f, 65},
- {0x8018, 65},
- {0x801f, 65},
- {0x8029, 65},
- {0xc038, 65},
- },
- /* 27 */
- {
- {0x8003, 95},
- {0x8006, 95},
- {0x800a, 95},
- {0x800f, 95},
- {0x8018, 95},
- {0x801f, 95},
- {0x8029, 95},
- {0xc038, 95},
- {0x8003, 98},
- {0x8006, 98},
- {0x800a, 98},
- {0x800f, 98},
- {0x8018, 98},
- {0x801f, 98},
- {0x8029, 98},
- {0xc038, 98},
- },
- /* 28 */
- {
- {0x8002, 100},
- {0x8009, 100},
- {0x8017, 100},
- {0xc028, 100},
- {0x8002, 102},
- {0x8009, 102},
- {0x8017, 102},
- {0xc028, 102},
- {0x8002, 103},
- {0x8009, 103},
- {0x8017, 103},
- {0xc028, 103},
- {0x8002, 104},
- {0x8009, 104},
- {0x8017, 104},
- {0xc028, 104},
- },
- /* 29 */
- {
- {0x8003, 100},
- {0x8006, 100},
- {0x800a, 100},
- {0x800f, 100},
- {0x8018, 100},
- {0x801f, 100},
- {0x8029, 100},
- {0xc038, 100},
- {0x8003, 102},
- {0x8006, 102},
- {0x800a, 102},
- {0x800f, 102},
- {0x8018, 102},
- {0x801f, 102},
- {0x8029, 102},
- {0xc038, 102},
- },
- /* 30 */
- {
- {0x8003, 103},
- {0x8006, 103},
- {0x800a, 103},
- {0x800f, 103},
- {0x8018, 103},
- {0x801f, 103},
- {0x8029, 103},
- {0xc038, 103},
- {0x8003, 104},
- {0x8006, 104},
- {0x800a, 104},
- {0x800f, 104},
- {0x8018, 104},
- {0x801f, 104},
- {0x8029, 104},
- {0xc038, 104},
- },
- /* 31 */
- {
- {0x8001, 108},
- {0xc016, 108},
- {0x8001, 109},
- {0xc016, 109},
- {0x8001, 110},
- {0xc016, 110},
- {0x8001, 112},
- {0xc016, 112},
- {0x8001, 114},
- {0xc016, 114},
- {0x8001, 117},
- {0xc016, 117},
- {0xc000, 58},
- {0xc000, 66},
- {0xc000, 67},
- {0xc000, 68},
- },
- /* 32 */
- {
- {0x8002, 108},
- {0x8009, 108},
- {0x8017, 108},
- {0xc028, 108},
- {0x8002, 109},
- {0x8009, 109},
- {0x8017, 109},
- {0xc028, 109},
- {0x8002, 110},
- {0x8009, 110},
- {0x8017, 110},
- {0xc028, 110},
- {0x8002, 112},
- {0x8009, 112},
- {0x8017, 112},
- {0xc028, 112},
- },
- /* 33 */
- {
- {0x8003, 108},
- {0x8006, 108},
- {0x800a, 108},
- {0x800f, 108},
- {0x8018, 108},
- {0x801f, 108},
- {0x8029, 108},
- {0xc038, 108},
- {0x8003, 109},
- {0x8006, 109},
- {0x800a, 109},
- {0x800f, 109},
- {0x8018, 109},
- {0x801f, 109},
- {0x8029, 109},
- {0xc038, 109},
- },
- /* 34 */
- {
- {0x8003, 110},
- {0x8006, 110},
- {0x800a, 110},
- {0x800f, 110},
- {0x8018, 110},
- {0x801f, 110},
- {0x8029, 110},
- {0xc038, 110},
- {0x8003, 112},
- {0x8006, 112},
- {0x800a, 112},
- {0x800f, 112},
- {0x8018, 112},
- {0x801f, 112},
- {0x8029, 112},
- {0xc038, 112},
- },
- /* 35 */
- {
- {0x8002, 114},
- {0x8009, 114},
- {0x8017, 114},
- {0xc028, 114},
- {0x8002, 117},
- {0x8009, 117},
- {0x8017, 117},
- {0xc028, 117},
- {0x8001, 58},
- {0xc016, 58},
- {0x8001, 66},
- {0xc016, 66},
- {0x8001, 67},
- {0xc016, 67},
- {0x8001, 68},
- {0xc016, 68},
- },
- /* 36 */
- {
- {0x8003, 114},
- {0x8006, 114},
- {0x800a, 114},
- {0x800f, 114},
- {0x8018, 114},
- {0x801f, 114},
- {0x8029, 114},
- {0xc038, 114},
- {0x8003, 117},
- {0x8006, 117},
- {0x800a, 117},
- {0x800f, 117},
- {0x8018, 117},
- {0x801f, 117},
- {0x8029, 117},
- {0xc038, 117},
- },
- /* 37 */
- {
- {0x8002, 58},
- {0x8009, 58},
- {0x8017, 58},
- {0xc028, 58},
- {0x8002, 66},
- {0x8009, 66},
- {0x8017, 66},
- {0xc028, 66},
- {0x8002, 67},
- {0x8009, 67},
- {0x8017, 67},
- {0xc028, 67},
- {0x8002, 68},
- {0x8009, 68},
- {0x8017, 68},
- {0xc028, 68},
- },
- /* 38 */
- {
- {0x8003, 58},
- {0x8006, 58},
- {0x800a, 58},
- {0x800f, 58},
- {0x8018, 58},
- {0x801f, 58},
- {0x8029, 58},
- {0xc038, 58},
- {0x8003, 66},
- {0x8006, 66},
- {0x800a, 66},
- {0x800f, 66},
- {0x8018, 66},
- {0x801f, 66},
- {0x8029, 66},
- {0xc038, 66},
- },
- /* 39 */
- {
- {0x8003, 67},
- {0x8006, 67},
- {0x800a, 67},
- {0x800f, 67},
- {0x8018, 67},
- {0x801f, 67},
- {0x8029, 67},
- {0xc038, 67},
- {0x8003, 68},
- {0x8006, 68},
- {0x800a, 68},
- {0x800f, 68},
- {0x8018, 68},
- {0x801f, 68},
- {0x8029, 68},
- {0xc038, 68},
- },
- /* 40 */
- {
- {0x2c, 0},
- {0x2d, 0},
- {0x2f, 0},
- {0x30, 0},
- {0x33, 0},
- {0x34, 0},
- {0x36, 0},
- {0x37, 0},
- {0x3b, 0},
- {0x3c, 0},
- {0x3e, 0},
- {0x3f, 0},
- {0x42, 0},
- {0x43, 0},
- {0x45, 0},
- {0x4048, 0},
- },
- /* 41 */
- {
- {0xc000, 69},
- {0xc000, 70},
- {0xc000, 71},
- {0xc000, 72},
- {0xc000, 73},
- {0xc000, 74},
- {0xc000, 75},
- {0xc000, 76},
- {0xc000, 77},
- {0xc000, 78},
- {0xc000, 79},
- {0xc000, 80},
- {0xc000, 81},
- {0xc000, 82},
- {0xc000, 83},
- {0xc000, 84},
- },
- /* 42 */
- {
- {0x8001, 69},
- {0xc016, 69},
- {0x8001, 70},
- {0xc016, 70},
- {0x8001, 71},
- {0xc016, 71},
- {0x8001, 72},
- {0xc016, 72},
- {0x8001, 73},
- {0xc016, 73},
- {0x8001, 74},
- {0xc016, 74},
- {0x8001, 75},
- {0xc016, 75},
- {0x8001, 76},
- {0xc016, 76},
- },
- /* 43 */
- {
- {0x8002, 69},
- {0x8009, 69},
- {0x8017, 69},
- {0xc028, 69},
- {0x8002, 70},
- {0x8009, 70},
- {0x8017, 70},
- {0xc028, 70},
- {0x8002, 71},
- {0x8009, 71},
- {0x8017, 71},
- {0xc028, 71},
- {0x8002, 72},
- {0x8009, 72},
- {0x8017, 72},
- {0xc028, 72},
- },
- /* 44 */
- {
- {0x8003, 69},
- {0x8006, 69},
- {0x800a, 69},
- {0x800f, 69},
- {0x8018, 69},
- {0x801f, 69},
- {0x8029, 69},
- {0xc038, 69},
- {0x8003, 70},
- {0x8006, 70},
- {0x800a, 70},
- {0x800f, 70},
- {0x8018, 70},
- {0x801f, 70},
- {0x8029, 70},
- {0xc038, 70},
- },
- /* 45 */
- {
- {0x8003, 71},
- {0x8006, 71},
- {0x800a, 71},
- {0x800f, 71},
- {0x8018, 71},
- {0x801f, 71},
- {0x8029, 71},
- {0xc038, 71},
- {0x8003, 72},
- {0x8006, 72},
- {0x800a, 72},
- {0x800f, 72},
- {0x8018, 72},
- {0x801f, 72},
- {0x8029, 72},
- {0xc038, 72},
- },
- /* 46 */
- {
- {0x8002, 73},
- {0x8009, 73},
- {0x8017, 73},
- {0xc028, 73},
- {0x8002, 74},
- {0x8009, 74},
- {0x8017, 74},
- {0xc028, 74},
- {0x8002, 75},
- {0x8009, 75},
- {0x8017, 75},
- {0xc028, 75},
- {0x8002, 76},
- {0x8009, 76},
- {0x8017, 76},
- {0xc028, 76},
- },
- /* 47 */
- {
- {0x8003, 73},
- {0x8006, 73},
- {0x800a, 73},
- {0x800f, 73},
- {0x8018, 73},
- {0x801f, 73},
- {0x8029, 73},
- {0xc038, 73},
- {0x8003, 74},
- {0x8006, 74},
- {0x800a, 74},
- {0x800f, 74},
- {0x8018, 74},
- {0x801f, 74},
- {0x8029, 74},
- {0xc038, 74},
- },
- /* 48 */
- {
- {0x8003, 75},
- {0x8006, 75},
- {0x800a, 75},
- {0x800f, 75},
- {0x8018, 75},
- {0x801f, 75},
- {0x8029, 75},
- {0xc038, 75},
- {0x8003, 76},
- {0x8006, 76},
- {0x800a, 76},
- {0x800f, 76},
- {0x8018, 76},
- {0x801f, 76},
- {0x8029, 76},
- {0xc038, 76},
- },
- /* 49 */
- {
- {0x8001, 77},
- {0xc016, 77},
- {0x8001, 78},
- {0xc016, 78},
- {0x8001, 79},
- {0xc016, 79},
- {0x8001, 80},
- {0xc016, 80},
- {0x8001, 81},
- {0xc016, 81},
- {0x8001, 82},
- {0xc016, 82},
- {0x8001, 83},
- {0xc016, 83},
- {0x8001, 84},
- {0xc016, 84},
- },
- /* 50 */
- {
- {0x8002, 77},
- {0x8009, 77},
- {0x8017, 77},
- {0xc028, 77},
- {0x8002, 78},
- {0x8009, 78},
- {0x8017, 78},
- {0xc028, 78},
- {0x8002, 79},
- {0x8009, 79},
- {0x8017, 79},
- {0xc028, 79},
- {0x8002, 80},
- {0x8009, 80},
- {0x8017, 80},
- {0xc028, 80},
- },
- /* 51 */
- {
- {0x8003, 77},
- {0x8006, 77},
- {0x800a, 77},
- {0x800f, 77},
- {0x8018, 77},
- {0x801f, 77},
- {0x8029, 77},
- {0xc038, 77},
- {0x8003, 78},
- {0x8006, 78},
- {0x800a, 78},
- {0x800f, 78},
- {0x8018, 78},
- {0x801f, 78},
- {0x8029, 78},
- {0xc038, 78},
- },
- /* 52 */
- {
- {0x8003, 79},
- {0x8006, 79},
- {0x800a, 79},
- {0x800f, 79},
- {0x8018, 79},
- {0x801f, 79},
- {0x8029, 79},
- {0xc038, 79},
- {0x8003, 80},
- {0x8006, 80},
- {0x800a, 80},
- {0x800f, 80},
- {0x8018, 80},
- {0x801f, 80},
- {0x8029, 80},
- {0xc038, 80},
- },
- /* 53 */
- {
- {0x8002, 81},
- {0x8009, 81},
- {0x8017, 81},
- {0xc028, 81},
- {0x8002, 82},
- {0x8009, 82},
- {0x8017, 82},
- {0xc028, 82},
- {0x8002, 83},
- {0x8009, 83},
- {0x8017, 83},
- {0xc028, 83},
- {0x8002, 84},
- {0x8009, 84},
- {0x8017, 84},
- {0xc028, 84},
- },
- /* 54 */
- {
- {0x8003, 81},
- {0x8006, 81},
- {0x800a, 81},
- {0x800f, 81},
- {0x8018, 81},
- {0x801f, 81},
- {0x8029, 81},
- {0xc038, 81},
- {0x8003, 82},
- {0x8006, 82},
- {0x800a, 82},
- {0x800f, 82},
- {0x8018, 82},
- {0x801f, 82},
- {0x8029, 82},
- {0xc038, 82},
- },
- /* 55 */
- {
- {0x8003, 83},
- {0x8006, 83},
- {0x800a, 83},
- {0x800f, 83},
- {0x8018, 83},
- {0x801f, 83},
- {0x8029, 83},
- {0xc038, 83},
- {0x8003, 84},
- {0x8006, 84},
- {0x800a, 84},
- {0x800f, 84},
- {0x8018, 84},
- {0x801f, 84},
- {0x8029, 84},
- {0xc038, 84},
- },
- /* 56 */
- {
- {0xc000, 85},
- {0xc000, 86},
- {0xc000, 87},
- {0xc000, 89},
- {0xc000, 106},
- {0xc000, 107},
- {0xc000, 113},
- {0xc000, 118},
- {0xc000, 119},
- {0xc000, 120},
- {0xc000, 121},
- {0xc000, 122},
- {0x46, 0},
- {0x47, 0},
- {0x49, 0},
- {0x404a, 0},
- },
- /* 57 */
- {
- {0x8001, 85},
- {0xc016, 85},
- {0x8001, 86},
- {0xc016, 86},
- {0x8001, 87},
- {0xc016, 87},
- {0x8001, 89},
- {0xc016, 89},
- {0x8001, 106},
- {0xc016, 106},
- {0x8001, 107},
- {0xc016, 107},
- {0x8001, 113},
- {0xc016, 113},
- {0x8001, 118},
- {0xc016, 118},
- },
- /* 58 */
- {
- {0x8002, 85},
- {0x8009, 85},
- {0x8017, 85},
- {0xc028, 85},
- {0x8002, 86},
- {0x8009, 86},
- {0x8017, 86},
- {0xc028, 86},
- {0x8002, 87},
- {0x8009, 87},
- {0x8017, 87},
- {0xc028, 87},
- {0x8002, 89},
- {0x8009, 89},
- {0x8017, 89},
- {0xc028, 89},
- },
- /* 59 */
- {
- {0x8003, 85},
- {0x8006, 85},
- {0x800a, 85},
- {0x800f, 85},
- {0x8018, 85},
- {0x801f, 85},
- {0x8029, 85},
- {0xc038, 85},
- {0x8003, 86},
- {0x8006, 86},
- {0x800a, 86},
- {0x800f, 86},
- {0x8018, 86},
- {0x801f, 86},
- {0x8029, 86},
- {0xc038, 86},
- },
- /* 60 */
- {
- {0x8003, 87},
- {0x8006, 87},
- {0x800a, 87},
- {0x800f, 87},
- {0x8018, 87},
- {0x801f, 87},
- {0x8029, 87},
- {0xc038, 87},
- {0x8003, 89},
- {0x8006, 89},
- {0x800a, 89},
- {0x800f, 89},
- {0x8018, 89},
- {0x801f, 89},
- {0x8029, 89},
- {0xc038, 89},
- },
- /* 61 */
- {
- {0x8002, 106},
- {0x8009, 106},
- {0x8017, 106},
- {0xc028, 106},
- {0x8002, 107},
- {0x8009, 107},
- {0x8017, 107},
- {0xc028, 107},
- {0x8002, 113},
- {0x8009, 113},
- {0x8017, 113},
- {0xc028, 113},
- {0x8002, 118},
- {0x8009, 118},
- {0x8017, 118},
- {0xc028, 118},
- },
- /* 62 */
- {
- {0x8003, 106},
- {0x8006, 106},
- {0x800a, 106},
- {0x800f, 106},
- {0x8018, 106},
- {0x801f, 106},
- {0x8029, 106},
- {0xc038, 106},
- {0x8003, 107},
- {0x8006, 107},
- {0x800a, 107},
- {0x800f, 107},
- {0x8018, 107},
- {0x801f, 107},
- {0x8029, 107},
- {0xc038, 107},
- },
- /* 63 */
- {
- {0x8003, 113},
- {0x8006, 113},
- {0x800a, 113},
- {0x800f, 113},
- {0x8018, 113},
- {0x801f, 113},
- {0x8029, 113},
- {0xc038, 113},
- {0x8003, 118},
- {0x8006, 118},
- {0x800a, 118},
- {0x800f, 118},
- {0x8018, 118},
- {0x801f, 118},
- {0x8029, 118},
- {0xc038, 118},
- },
- /* 64 */
- {
- {0x8001, 119},
- {0xc016, 119},
- {0x8001, 120},
- {0xc016, 120},
- {0x8001, 121},
- {0xc016, 121},
- {0x8001, 122},
- {0xc016, 122},
- {0xc000, 38},
- {0xc000, 42},
- {0xc000, 44},
- {0xc000, 59},
- {0xc000, 88},
- {0xc000, 90},
- {0x4b, 0},
- {0x4e, 0},
- },
- /* 65 */
- {
- {0x8002, 119},
- {0x8009, 119},
- {0x8017, 119},
- {0xc028, 119},
- {0x8002, 120},
- {0x8009, 120},
- {0x8017, 120},
- {0xc028, 120},
- {0x8002, 121},
- {0x8009, 121},
- {0x8017, 121},
- {0xc028, 121},
- {0x8002, 122},
- {0x8009, 122},
- {0x8017, 122},
- {0xc028, 122},
- },
- /* 66 */
- {
- {0x8003, 119},
- {0x8006, 119},
- {0x800a, 119},
- {0x800f, 119},
- {0x8018, 119},
- {0x801f, 119},
- {0x8029, 119},
- {0xc038, 119},
- {0x8003, 120},
- {0x8006, 120},
- {0x800a, 120},
- {0x800f, 120},
- {0x8018, 120},
- {0x801f, 120},
- {0x8029, 120},
- {0xc038, 120},
- },
- /* 67 */
- {
- {0x8003, 121},
- {0x8006, 121},
- {0x800a, 121},
- {0x800f, 121},
- {0x8018, 121},
- {0x801f, 121},
- {0x8029, 121},
- {0xc038, 121},
- {0x8003, 122},
- {0x8006, 122},
- {0x800a, 122},
- {0x800f, 122},
- {0x8018, 122},
- {0x801f, 122},
- {0x8029, 122},
- {0xc038, 122},
- },
- /* 68 */
- {
- {0x8001, 38},
- {0xc016, 38},
- {0x8001, 42},
- {0xc016, 42},
- {0x8001, 44},
- {0xc016, 44},
- {0x8001, 59},
- {0xc016, 59},
- {0x8001, 88},
- {0xc016, 88},
- {0x8001, 90},
- {0xc016, 90},
- {0x4c, 0},
- {0x4d, 0},
- {0x4f, 0},
- {0x51, 0},
- },
- /* 69 */
- {
- {0x8002, 38},
- {0x8009, 38},
- {0x8017, 38},
- {0xc028, 38},
- {0x8002, 42},
- {0x8009, 42},
- {0x8017, 42},
- {0xc028, 42},
- {0x8002, 44},
- {0x8009, 44},
- {0x8017, 44},
- {0xc028, 44},
- {0x8002, 59},
- {0x8009, 59},
- {0x8017, 59},
- {0xc028, 59},
- },
- /* 70 */
- {
- {0x8003, 38},
- {0x8006, 38},
- {0x800a, 38},
- {0x800f, 38},
- {0x8018, 38},
- {0x801f, 38},
- {0x8029, 38},
- {0xc038, 38},
- {0x8003, 42},
- {0x8006, 42},
- {0x800a, 42},
- {0x800f, 42},
- {0x8018, 42},
- {0x801f, 42},
- {0x8029, 42},
- {0xc038, 42},
- },
- /* 71 */
- {
- {0x8003, 44},
- {0x8006, 44},
- {0x800a, 44},
- {0x800f, 44},
- {0x8018, 44},
- {0x801f, 44},
- {0x8029, 44},
- {0xc038, 44},
- {0x8003, 59},
- {0x8006, 59},
- {0x800a, 59},
- {0x800f, 59},
- {0x8018, 59},
- {0x801f, 59},
- {0x8029, 59},
- {0xc038, 59},
- },
- /* 72 */
- {
- {0x8002, 88},
- {0x8009, 88},
- {0x8017, 88},
- {0xc028, 88},
- {0x8002, 90},
- {0x8009, 90},
- {0x8017, 90},
- {0xc028, 90},
- {0xc000, 33},
- {0xc000, 34},
- {0xc000, 40},
- {0xc000, 41},
- {0xc000, 63},
- {0x50, 0},
- {0x52, 0},
- {0x54, 0},
- },
- /* 73 */
- {
- {0x8003, 88},
- {0x8006, 88},
- {0x800a, 88},
- {0x800f, 88},
- {0x8018, 88},
- {0x801f, 88},
- {0x8029, 88},
- {0xc038, 88},
- {0x8003, 90},
- {0x8006, 90},
- {0x800a, 90},
- {0x800f, 90},
- {0x8018, 90},
- {0x801f, 90},
- {0x8029, 90},
- {0xc038, 90},
- },
- /* 74 */
- {
- {0x8001, 33},
- {0xc016, 33},
- {0x8001, 34},
- {0xc016, 34},
- {0x8001, 40},
- {0xc016, 40},
- {0x8001, 41},
- {0xc016, 41},
- {0x8001, 63},
- {0xc016, 63},
- {0xc000, 39},
- {0xc000, 43},
- {0xc000, 124},
- {0x53, 0},
- {0x55, 0},
- {0x58, 0},
- },
- /* 75 */
- {
- {0x8002, 33},
- {0x8009, 33},
- {0x8017, 33},
- {0xc028, 33},
- {0x8002, 34},
- {0x8009, 34},
- {0x8017, 34},
- {0xc028, 34},
- {0x8002, 40},
- {0x8009, 40},
- {0x8017, 40},
- {0xc028, 40},
- {0x8002, 41},
- {0x8009, 41},
- {0x8017, 41},
- {0xc028, 41},
- },
- /* 76 */
- {
- {0x8003, 33},
- {0x8006, 33},
- {0x800a, 33},
- {0x800f, 33},
- {0x8018, 33},
- {0x801f, 33},
- {0x8029, 33},
- {0xc038, 33},
- {0x8003, 34},
- {0x8006, 34},
- {0x800a, 34},
- {0x800f, 34},
- {0x8018, 34},
- {0x801f, 34},
- {0x8029, 34},
- {0xc038, 34},
- },
- /* 77 */
- {
- {0x8003, 40},
- {0x8006, 40},
- {0x800a, 40},
- {0x800f, 40},
- {0x8018, 40},
- {0x801f, 40},
- {0x8029, 40},
- {0xc038, 40},
- {0x8003, 41},
- {0x8006, 41},
- {0x800a, 41},
- {0x800f, 41},
- {0x8018, 41},
- {0x801f, 41},
- {0x8029, 41},
- {0xc038, 41},
- },
- /* 78 */
- {
- {0x8002, 63},
- {0x8009, 63},
- {0x8017, 63},
- {0xc028, 63},
- {0x8001, 39},
- {0xc016, 39},
- {0x8001, 43},
- {0xc016, 43},
- {0x8001, 124},
- {0xc016, 124},
- {0xc000, 35},
- {0xc000, 62},
- {0x56, 0},
- {0x57, 0},
- {0x59, 0},
- {0x5a, 0},
- },
- /* 79 */
- {
- {0x8003, 63},
- {0x8006, 63},
- {0x800a, 63},
- {0x800f, 63},
- {0x8018, 63},
- {0x801f, 63},
- {0x8029, 63},
- {0xc038, 63},
- {0x8002, 39},
- {0x8009, 39},
- {0x8017, 39},
- {0xc028, 39},
- {0x8002, 43},
- {0x8009, 43},
- {0x8017, 43},
- {0xc028, 43},
- },
- /* 80 */
- {
- {0x8003, 39},
- {0x8006, 39},
- {0x800a, 39},
- {0x800f, 39},
- {0x8018, 39},
- {0x801f, 39},
- {0x8029, 39},
- {0xc038, 39},
- {0x8003, 43},
- {0x8006, 43},
- {0x800a, 43},
- {0x800f, 43},
- {0x8018, 43},
- {0x801f, 43},
- {0x8029, 43},
- {0xc038, 43},
- },
- /* 81 */
- {
- {0x8002, 124},
- {0x8009, 124},
- {0x8017, 124},
- {0xc028, 124},
- {0x8001, 35},
- {0xc016, 35},
- {0x8001, 62},
- {0xc016, 62},
- {0xc000, 0},
- {0xc000, 36},
- {0xc000, 64},
- {0xc000, 91},
- {0xc000, 93},
- {0xc000, 126},
- {0x5b, 0},
- {0x5c, 0},
- },
- /* 82 */
- {
- {0x8003, 124},
- {0x8006, 124},
- {0x800a, 124},
- {0x800f, 124},
- {0x8018, 124},
- {0x801f, 124},
- {0x8029, 124},
- {0xc038, 124},
- {0x8002, 35},
- {0x8009, 35},
- {0x8017, 35},
- {0xc028, 35},
- {0x8002, 62},
- {0x8009, 62},
- {0x8017, 62},
- {0xc028, 62},
- },
- /* 83 */
- {
- {0x8003, 35},
- {0x8006, 35},
- {0x800a, 35},
- {0x800f, 35},
- {0x8018, 35},
- {0x801f, 35},
- {0x8029, 35},
- {0xc038, 35},
- {0x8003, 62},
- {0x8006, 62},
- {0x800a, 62},
- {0x800f, 62},
- {0x8018, 62},
- {0x801f, 62},
- {0x8029, 62},
- {0xc038, 62},
- },
- /* 84 */
- {
- {0x8001, 0},
- {0xc016, 0},
- {0x8001, 36},
- {0xc016, 36},
- {0x8001, 64},
- {0xc016, 64},
- {0x8001, 91},
- {0xc016, 91},
- {0x8001, 93},
- {0xc016, 93},
- {0x8001, 126},
- {0xc016, 126},
- {0xc000, 94},
- {0xc000, 125},
- {0x5d, 0},
- {0x5e, 0},
- },
- /* 85 */
- {
- {0x8002, 0},
- {0x8009, 0},
- {0x8017, 0},
- {0xc028, 0},
- {0x8002, 36},
- {0x8009, 36},
- {0x8017, 36},
- {0xc028, 36},
- {0x8002, 64},
- {0x8009, 64},
- {0x8017, 64},
- {0xc028, 64},
- {0x8002, 91},
- {0x8009, 91},
- {0x8017, 91},
- {0xc028, 91},
- },
- /* 86 */
- {
- {0x8003, 0},
- {0x8006, 0},
- {0x800a, 0},
- {0x800f, 0},
- {0x8018, 0},
- {0x801f, 0},
- {0x8029, 0},
- {0xc038, 0},
- {0x8003, 36},
- {0x8006, 36},
- {0x800a, 36},
- {0x800f, 36},
- {0x8018, 36},
- {0x801f, 36},
- {0x8029, 36},
- {0xc038, 36},
- },
- /* 87 */
- {
- {0x8003, 64},
- {0x8006, 64},
- {0x800a, 64},
- {0x800f, 64},
- {0x8018, 64},
- {0x801f, 64},
- {0x8029, 64},
- {0xc038, 64},
- {0x8003, 91},
- {0x8006, 91},
- {0x800a, 91},
- {0x800f, 91},
- {0x8018, 91},
- {0x801f, 91},
- {0x8029, 91},
- {0xc038, 91},
- },
- /* 88 */
- {
- {0x8002, 93},
- {0x8009, 93},
- {0x8017, 93},
- {0xc028, 93},
- {0x8002, 126},
- {0x8009, 126},
- {0x8017, 126},
- {0xc028, 126},
- {0x8001, 94},
- {0xc016, 94},
- {0x8001, 125},
- {0xc016, 125},
- {0xc000, 60},
- {0xc000, 96},
- {0xc000, 123},
- {0x5f, 0},
- },
- /* 89 */
- {
- {0x8003, 93},
- {0x8006, 93},
- {0x800a, 93},
- {0x800f, 93},
- {0x8018, 93},
- {0x801f, 93},
- {0x8029, 93},
- {0xc038, 93},
- {0x8003, 126},
- {0x8006, 126},
- {0x800a, 126},
- {0x800f, 126},
- {0x8018, 126},
- {0x801f, 126},
- {0x8029, 126},
- {0xc038, 126},
- },
- /* 90 */
- {
- {0x8002, 94},
- {0x8009, 94},
- {0x8017, 94},
- {0xc028, 94},
- {0x8002, 125},
- {0x8009, 125},
- {0x8017, 125},
- {0xc028, 125},
- {0x8001, 60},
- {0xc016, 60},
- {0x8001, 96},
- {0xc016, 96},
- {0x8001, 123},
- {0xc016, 123},
- {0x60, 0},
- {0x6e, 0},
- },
- /* 91 */
- {
- {0x8003, 94},
- {0x8006, 94},
- {0x800a, 94},
- {0x800f, 94},
- {0x8018, 94},
- {0x801f, 94},
- {0x8029, 94},
- {0xc038, 94},
- {0x8003, 125},
- {0x8006, 125},
- {0x800a, 125},
- {0x800f, 125},
- {0x8018, 125},
- {0x801f, 125},
- {0x8029, 125},
- {0xc038, 125},
- },
- /* 92 */
- {
- {0x8002, 60},
- {0x8009, 60},
- {0x8017, 60},
- {0xc028, 60},
- {0x8002, 96},
- {0x8009, 96},
- {0x8017, 96},
- {0xc028, 96},
- {0x8002, 123},
- {0x8009, 123},
- {0x8017, 123},
- {0xc028, 123},
- {0x61, 0},
- {0x65, 0},
- {0x6f, 0},
- {0x85, 0},
- },
- /* 93 */
- {
- {0x8003, 60},
- {0x8006, 60},
- {0x800a, 60},
- {0x800f, 60},
- {0x8018, 60},
- {0x801f, 60},
- {0x8029, 60},
- {0xc038, 60},
- {0x8003, 96},
- {0x8006, 96},
- {0x800a, 96},
- {0x800f, 96},
- {0x8018, 96},
- {0x801f, 96},
- {0x8029, 96},
- {0xc038, 96},
- },
- /* 94 */
- {
- {0x8003, 123},
- {0x8006, 123},
- {0x800a, 123},
- {0x800f, 123},
- {0x8018, 123},
- {0x801f, 123},
- {0x8029, 123},
- {0xc038, 123},
- {0x62, 0},
- {0x63, 0},
- {0x66, 0},
- {0x69, 0},
- {0x70, 0},
- {0x77, 0},
- {0x86, 0},
- {0x99, 0},
- },
- /* 95 */
- {
- {0xc000, 92},
- {0xc000, 195},
- {0xc000, 208},
- {0x64, 0},
- {0x67, 0},
- {0x68, 0},
- {0x6a, 0},
- {0x6b, 0},
- {0x71, 0},
- {0x74, 0},
- {0x78, 0},
- {0x7e, 0},
- {0x87, 0},
- {0x8e, 0},
- {0x9a, 0},
- {0xa9, 0},
- },
- /* 96 */
- {
- {0x8001, 92},
- {0xc016, 92},
- {0x8001, 195},
- {0xc016, 195},
- {0x8001, 208},
- {0xc016, 208},
- {0xc000, 128},
- {0xc000, 130},
- {0xc000, 131},
- {0xc000, 162},
- {0xc000, 184},
- {0xc000, 194},
- {0xc000, 224},
- {0xc000, 226},
- {0x6c, 0},
- {0x6d, 0},
- },
- /* 97 */
- {
- {0x8002, 92},
- {0x8009, 92},
- {0x8017, 92},
- {0xc028, 92},
- {0x8002, 195},
- {0x8009, 195},
- {0x8017, 195},
- {0xc028, 195},
- {0x8002, 208},
- {0x8009, 208},
- {0x8017, 208},
- {0xc028, 208},
- {0x8001, 128},
- {0xc016, 128},
- {0x8001, 130},
- {0xc016, 130},
- },
- /* 98 */
- {
- {0x8003, 92},
- {0x8006, 92},
- {0x800a, 92},
- {0x800f, 92},
- {0x8018, 92},
- {0x801f, 92},
- {0x8029, 92},
- {0xc038, 92},
- {0x8003, 195},
- {0x8006, 195},
- {0x800a, 195},
- {0x800f, 195},
- {0x8018, 195},
- {0x801f, 195},
- {0x8029, 195},
- {0xc038, 195},
- },
- /* 99 */
- {
- {0x8003, 208},
- {0x8006, 208},
- {0x800a, 208},
- {0x800f, 208},
- {0x8018, 208},
- {0x801f, 208},
- {0x8029, 208},
- {0xc038, 208},
- {0x8002, 128},
- {0x8009, 128},
- {0x8017, 128},
- {0xc028, 128},
- {0x8002, 130},
- {0x8009, 130},
- {0x8017, 130},
- {0xc028, 130},
- },
- /* 100 */
- {
- {0x8003, 128},
- {0x8006, 128},
- {0x800a, 128},
- {0x800f, 128},
- {0x8018, 128},
- {0x801f, 128},
- {0x8029, 128},
- {0xc038, 128},
- {0x8003, 130},
- {0x8006, 130},
- {0x800a, 130},
- {0x800f, 130},
- {0x8018, 130},
- {0x801f, 130},
- {0x8029, 130},
- {0xc038, 130},
- },
- /* 101 */
- {
- {0x8001, 131},
- {0xc016, 131},
- {0x8001, 162},
- {0xc016, 162},
- {0x8001, 184},
- {0xc016, 184},
- {0x8001, 194},
- {0xc016, 194},
- {0x8001, 224},
- {0xc016, 224},
- {0x8001, 226},
- {0xc016, 226},
- {0xc000, 153},
- {0xc000, 161},
- {0xc000, 167},
- {0xc000, 172},
- },
- /* 102 */
- {
- {0x8002, 131},
- {0x8009, 131},
- {0x8017, 131},
- {0xc028, 131},
- {0x8002, 162},
- {0x8009, 162},
- {0x8017, 162},
- {0xc028, 162},
- {0x8002, 184},
- {0x8009, 184},
- {0x8017, 184},
- {0xc028, 184},
- {0x8002, 194},
- {0x8009, 194},
- {0x8017, 194},
- {0xc028, 194},
- },
- /* 103 */
- {
- {0x8003, 131},
- {0x8006, 131},
- {0x800a, 131},
- {0x800f, 131},
- {0x8018, 131},
- {0x801f, 131},
- {0x8029, 131},
- {0xc038, 131},
- {0x8003, 162},
- {0x8006, 162},
- {0x800a, 162},
- {0x800f, 162},
- {0x8018, 162},
- {0x801f, 162},
- {0x8029, 162},
- {0xc038, 162},
- },
- /* 104 */
- {
- {0x8003, 184},
- {0x8006, 184},
- {0x800a, 184},
- {0x800f, 184},
- {0x8018, 184},
- {0x801f, 184},
- {0x8029, 184},
- {0xc038, 184},
- {0x8003, 194},
- {0x8006, 194},
- {0x800a, 194},
- {0x800f, 194},
- {0x8018, 194},
- {0x801f, 194},
- {0x8029, 194},
- {0xc038, 194},
- },
- /* 105 */
- {
- {0x8002, 224},
- {0x8009, 224},
- {0x8017, 224},
- {0xc028, 224},
- {0x8002, 226},
- {0x8009, 226},
- {0x8017, 226},
- {0xc028, 226},
- {0x8001, 153},
- {0xc016, 153},
- {0x8001, 161},
- {0xc016, 161},
- {0x8001, 167},
- {0xc016, 167},
- {0x8001, 172},
- {0xc016, 172},
- },
- /* 106 */
- {
- {0x8003, 224},
- {0x8006, 224},
- {0x800a, 224},
- {0x800f, 224},
- {0x8018, 224},
- {0x801f, 224},
- {0x8029, 224},
- {0xc038, 224},
- {0x8003, 226},
- {0x8006, 226},
- {0x800a, 226},
- {0x800f, 226},
- {0x8018, 226},
- {0x801f, 226},
- {0x8029, 226},
- {0xc038, 226},
- },
- /* 107 */
- {
- {0x8002, 153},
- {0x8009, 153},
- {0x8017, 153},
- {0xc028, 153},
- {0x8002, 161},
- {0x8009, 161},
- {0x8017, 161},
- {0xc028, 161},
- {0x8002, 167},
- {0x8009, 167},
- {0x8017, 167},
- {0xc028, 167},
- {0x8002, 172},
- {0x8009, 172},
- {0x8017, 172},
- {0xc028, 172},
- },
- /* 108 */
- {
- {0x8003, 153},
- {0x8006, 153},
- {0x800a, 153},
- {0x800f, 153},
- {0x8018, 153},
- {0x801f, 153},
- {0x8029, 153},
- {0xc038, 153},
- {0x8003, 161},
- {0x8006, 161},
- {0x800a, 161},
- {0x800f, 161},
- {0x8018, 161},
- {0x801f, 161},
- {0x8029, 161},
- {0xc038, 161},
- },
- /* 109 */
- {
- {0x8003, 167},
- {0x8006, 167},
- {0x800a, 167},
- {0x800f, 167},
- {0x8018, 167},
- {0x801f, 167},
- {0x8029, 167},
- {0xc038, 167},
- {0x8003, 172},
- {0x8006, 172},
- {0x800a, 172},
- {0x800f, 172},
- {0x8018, 172},
- {0x801f, 172},
- {0x8029, 172},
- {0xc038, 172},
- },
- /* 110 */
- {
- {0x72, 0},
- {0x73, 0},
- {0x75, 0},
- {0x76, 0},
- {0x79, 0},
- {0x7b, 0},
- {0x7f, 0},
- {0x82, 0},
- {0x88, 0},
- {0x8b, 0},
- {0x8f, 0},
- {0x92, 0},
- {0x9b, 0},
- {0xa2, 0},
- {0xaa, 0},
- {0xb4, 0},
- },
- /* 111 */
- {
- {0xc000, 176},
- {0xc000, 177},
- {0xc000, 179},
- {0xc000, 209},
- {0xc000, 216},
- {0xc000, 217},
- {0xc000, 227},
- {0xc000, 229},
- {0xc000, 230},
- {0x7a, 0},
- {0x7c, 0},
- {0x7d, 0},
- {0x80, 0},
- {0x81, 0},
- {0x83, 0},
- {0x84, 0},
- },
- /* 112 */
- {
- {0x8001, 176},
- {0xc016, 176},
- {0x8001, 177},
- {0xc016, 177},
- {0x8001, 179},
- {0xc016, 179},
- {0x8001, 209},
- {0xc016, 209},
- {0x8001, 216},
- {0xc016, 216},
- {0x8001, 217},
- {0xc016, 217},
- {0x8001, 227},
- {0xc016, 227},
- {0x8001, 229},
- {0xc016, 229},
- },
- /* 113 */
- {
- {0x8002, 176},
- {0x8009, 176},
- {0x8017, 176},
- {0xc028, 176},
- {0x8002, 177},
- {0x8009, 177},
- {0x8017, 177},
- {0xc028, 177},
- {0x8002, 179},
- {0x8009, 179},
- {0x8017, 179},
- {0xc028, 179},
- {0x8002, 209},
- {0x8009, 209},
- {0x8017, 209},
- {0xc028, 209},
- },
- /* 114 */
- {
- {0x8003, 176},
- {0x8006, 176},
- {0x800a, 176},
- {0x800f, 176},
- {0x8018, 176},
- {0x801f, 176},
- {0x8029, 176},
- {0xc038, 176},
- {0x8003, 177},
- {0x8006, 177},
- {0x800a, 177},
- {0x800f, 177},
- {0x8018, 177},
- {0x801f, 177},
- {0x8029, 177},
- {0xc038, 177},
- },
- /* 115 */
- {
- {0x8003, 179},
- {0x8006, 179},
- {0x800a, 179},
- {0x800f, 179},
- {0x8018, 179},
- {0x801f, 179},
- {0x8029, 179},
- {0xc038, 179},
- {0x8003, 209},
- {0x8006, 209},
- {0x800a, 209},
- {0x800f, 209},
- {0x8018, 209},
- {0x801f, 209},
- {0x8029, 209},
- {0xc038, 209},
- },
- /* 116 */
- {
- {0x8002, 216},
- {0x8009, 216},
- {0x8017, 216},
- {0xc028, 216},
- {0x8002, 217},
- {0x8009, 217},
- {0x8017, 217},
- {0xc028, 217},
- {0x8002, 227},
- {0x8009, 227},
- {0x8017, 227},
- {0xc028, 227},
- {0x8002, 229},
- {0x8009, 229},
- {0x8017, 229},
- {0xc028, 229},
- },
- /* 117 */
- {
- {0x8003, 216},
- {0x8006, 216},
- {0x800a, 216},
- {0x800f, 216},
- {0x8018, 216},
- {0x801f, 216},
- {0x8029, 216},
- {0xc038, 216},
- {0x8003, 217},
- {0x8006, 217},
- {0x800a, 217},
- {0x800f, 217},
- {0x8018, 217},
- {0x801f, 217},
- {0x8029, 217},
- {0xc038, 217},
- },
- /* 118 */
- {
- {0x8003, 227},
- {0x8006, 227},
- {0x800a, 227},
- {0x800f, 227},
- {0x8018, 227},
- {0x801f, 227},
- {0x8029, 227},
- {0xc038, 227},
- {0x8003, 229},
- {0x8006, 229},
- {0x800a, 229},
- {0x800f, 229},
- {0x8018, 229},
- {0x801f, 229},
- {0x8029, 229},
- {0xc038, 229},
- },
- /* 119 */
- {
- {0x8001, 230},
- {0xc016, 230},
- {0xc000, 129},
- {0xc000, 132},
- {0xc000, 133},
- {0xc000, 134},
- {0xc000, 136},
- {0xc000, 146},
- {0xc000, 154},
- {0xc000, 156},
- {0xc000, 160},
- {0xc000, 163},
- {0xc000, 164},
- {0xc000, 169},
- {0xc000, 170},
- {0xc000, 173},
- },
- /* 120 */
- {
- {0x8002, 230},
- {0x8009, 230},
- {0x8017, 230},
- {0xc028, 230},
- {0x8001, 129},
- {0xc016, 129},
- {0x8001, 132},
- {0xc016, 132},
- {0x8001, 133},
- {0xc016, 133},
- {0x8001, 134},
- {0xc016, 134},
- {0x8001, 136},
- {0xc016, 136},
- {0x8001, 146},
- {0xc016, 146},
- },
- /* 121 */
- {
- {0x8003, 230},
- {0x8006, 230},
- {0x800a, 230},
- {0x800f, 230},
- {0x8018, 230},
- {0x801f, 230},
- {0x8029, 230},
- {0xc038, 230},
- {0x8002, 129},
- {0x8009, 129},
- {0x8017, 129},
- {0xc028, 129},
- {0x8002, 132},
- {0x8009, 132},
- {0x8017, 132},
- {0xc028, 132},
- },
- /* 122 */
- {
- {0x8003, 129},
- {0x8006, 129},
- {0x800a, 129},
- {0x800f, 129},
- {0x8018, 129},
- {0x801f, 129},
- {0x8029, 129},
- {0xc038, 129},
- {0x8003, 132},
- {0x8006, 132},
- {0x800a, 132},
- {0x800f, 132},
- {0x8018, 132},
- {0x801f, 132},
- {0x8029, 132},
- {0xc038, 132},
- },
- /* 123 */
- {
- {0x8002, 133},
- {0x8009, 133},
- {0x8017, 133},
- {0xc028, 133},
- {0x8002, 134},
- {0x8009, 134},
- {0x8017, 134},
- {0xc028, 134},
- {0x8002, 136},
- {0x8009, 136},
- {0x8017, 136},
- {0xc028, 136},
- {0x8002, 146},
- {0x8009, 146},
- {0x8017, 146},
- {0xc028, 146},
- },
- /* 124 */
- {
- {0x8003, 133},
- {0x8006, 133},
- {0x800a, 133},
- {0x800f, 133},
- {0x8018, 133},
- {0x801f, 133},
- {0x8029, 133},
- {0xc038, 133},
- {0x8003, 134},
- {0x8006, 134},
- {0x800a, 134},
- {0x800f, 134},
- {0x8018, 134},
- {0x801f, 134},
- {0x8029, 134},
- {0xc038, 134},
- },
- /* 125 */
- {
- {0x8003, 136},
- {0x8006, 136},
- {0x800a, 136},
- {0x800f, 136},
- {0x8018, 136},
- {0x801f, 136},
- {0x8029, 136},
- {0xc038, 136},
- {0x8003, 146},
- {0x8006, 146},
- {0x800a, 146},
- {0x800f, 146},
- {0x8018, 146},
- {0x801f, 146},
- {0x8029, 146},
- {0xc038, 146},
- },
- /* 126 */
- {
- {0x8001, 154},
- {0xc016, 154},
- {0x8001, 156},
- {0xc016, 156},
- {0x8001, 160},
- {0xc016, 160},
- {0x8001, 163},
- {0xc016, 163},
- {0x8001, 164},
- {0xc016, 164},
- {0x8001, 169},
- {0xc016, 169},
- {0x8001, 170},
- {0xc016, 170},
- {0x8001, 173},
- {0xc016, 173},
- },
- /* 127 */
- {
- {0x8002, 154},
- {0x8009, 154},
- {0x8017, 154},
- {0xc028, 154},
- {0x8002, 156},
- {0x8009, 156},
- {0x8017, 156},
- {0xc028, 156},
- {0x8002, 160},
- {0x8009, 160},
- {0x8017, 160},
- {0xc028, 160},
- {0x8002, 163},
- {0x8009, 163},
- {0x8017, 163},
- {0xc028, 163},
- },
- /* 128 */
- {
- {0x8003, 154},
- {0x8006, 154},
- {0x800a, 154},
- {0x800f, 154},
- {0x8018, 154},
- {0x801f, 154},
- {0x8029, 154},
- {0xc038, 154},
- {0x8003, 156},
- {0x8006, 156},
- {0x800a, 156},
- {0x800f, 156},
- {0x8018, 156},
- {0x801f, 156},
- {0x8029, 156},
- {0xc038, 156},
- },
- /* 129 */
- {
- {0x8003, 160},
- {0x8006, 160},
- {0x800a, 160},
- {0x800f, 160},
- {0x8018, 160},
- {0x801f, 160},
- {0x8029, 160},
- {0xc038, 160},
- {0x8003, 163},
- {0x8006, 163},
- {0x800a, 163},
- {0x800f, 163},
- {0x8018, 163},
- {0x801f, 163},
- {0x8029, 163},
- {0xc038, 163},
- },
- /* 130 */
- {
- {0x8002, 164},
- {0x8009, 164},
- {0x8017, 164},
- {0xc028, 164},
- {0x8002, 169},
- {0x8009, 169},
- {0x8017, 169},
- {0xc028, 169},
- {0x8002, 170},
- {0x8009, 170},
- {0x8017, 170},
- {0xc028, 170},
- {0x8002, 173},
- {0x8009, 173},
- {0x8017, 173},
- {0xc028, 173},
- },
- /* 131 */
- {
- {0x8003, 164},
- {0x8006, 164},
- {0x800a, 164},
- {0x800f, 164},
- {0x8018, 164},
- {0x801f, 164},
- {0x8029, 164},
- {0xc038, 164},
- {0x8003, 169},
- {0x8006, 169},
- {0x800a, 169},
- {0x800f, 169},
- {0x8018, 169},
- {0x801f, 169},
- {0x8029, 169},
- {0xc038, 169},
- },
- /* 132 */
- {
- {0x8003, 170},
- {0x8006, 170},
- {0x800a, 170},
- {0x800f, 170},
- {0x8018, 170},
- {0x801f, 170},
- {0x8029, 170},
- {0xc038, 170},
- {0x8003, 173},
- {0x8006, 173},
- {0x800a, 173},
- {0x800f, 173},
- {0x8018, 173},
- {0x801f, 173},
- {0x8029, 173},
- {0xc038, 173},
- },
- /* 133 */
- {
- {0x89, 0},
- {0x8a, 0},
- {0x8c, 0},
- {0x8d, 0},
- {0x90, 0},
- {0x91, 0},
- {0x93, 0},
- {0x96, 0},
- {0x9c, 0},
- {0x9f, 0},
- {0xa3, 0},
- {0xa6, 0},
- {0xab, 0},
- {0xae, 0},
- {0xb5, 0},
- {0xbe, 0},
- },
- /* 134 */
- {
- {0xc000, 178},
- {0xc000, 181},
- {0xc000, 185},
- {0xc000, 186},
- {0xc000, 187},
- {0xc000, 189},
- {0xc000, 190},
- {0xc000, 196},
- {0xc000, 198},
- {0xc000, 228},
- {0xc000, 232},
- {0xc000, 233},
- {0x94, 0},
- {0x95, 0},
- {0x97, 0},
- {0x98, 0},
- },
- /* 135 */
- {
- {0x8001, 178},
- {0xc016, 178},
- {0x8001, 181},
- {0xc016, 181},
- {0x8001, 185},
- {0xc016, 185},
- {0x8001, 186},
- {0xc016, 186},
- {0x8001, 187},
- {0xc016, 187},
- {0x8001, 189},
- {0xc016, 189},
- {0x8001, 190},
- {0xc016, 190},
- {0x8001, 196},
- {0xc016, 196},
- },
- /* 136 */
- {
- {0x8002, 178},
- {0x8009, 178},
- {0x8017, 178},
- {0xc028, 178},
- {0x8002, 181},
- {0x8009, 181},
- {0x8017, 181},
- {0xc028, 181},
- {0x8002, 185},
- {0x8009, 185},
- {0x8017, 185},
- {0xc028, 185},
- {0x8002, 186},
- {0x8009, 186},
- {0x8017, 186},
- {0xc028, 186},
- },
- /* 137 */
- {
- {0x8003, 178},
- {0x8006, 178},
- {0x800a, 178},
- {0x800f, 178},
- {0x8018, 178},
- {0x801f, 178},
- {0x8029, 178},
- {0xc038, 178},
- {0x8003, 181},
- {0x8006, 181},
- {0x800a, 181},
- {0x800f, 181},
- {0x8018, 181},
- {0x801f, 181},
- {0x8029, 181},
- {0xc038, 181},
- },
- /* 138 */
- {
- {0x8003, 185},
- {0x8006, 185},
- {0x800a, 185},
- {0x800f, 185},
- {0x8018, 185},
- {0x801f, 185},
- {0x8029, 185},
- {0xc038, 185},
- {0x8003, 186},
- {0x8006, 186},
- {0x800a, 186},
- {0x800f, 186},
- {0x8018, 186},
- {0x801f, 186},
- {0x8029, 186},
- {0xc038, 186},
- },
- /* 139 */
- {
- {0x8002, 187},
- {0x8009, 187},
- {0x8017, 187},
- {0xc028, 187},
- {0x8002, 189},
- {0x8009, 189},
- {0x8017, 189},
- {0xc028, 189},
- {0x8002, 190},
- {0x8009, 190},
- {0x8017, 190},
- {0xc028, 190},
- {0x8002, 196},
- {0x8009, 196},
- {0x8017, 196},
- {0xc028, 196},
- },
- /* 140 */
- {
- {0x8003, 187},
- {0x8006, 187},
- {0x800a, 187},
- {0x800f, 187},
- {0x8018, 187},
- {0x801f, 187},
- {0x8029, 187},
- {0xc038, 187},
- {0x8003, 189},
- {0x8006, 189},
- {0x800a, 189},
- {0x800f, 189},
- {0x8018, 189},
- {0x801f, 189},
- {0x8029, 189},
- {0xc038, 189},
- },
- /* 141 */
- {
- {0x8003, 190},
- {0x8006, 190},
- {0x800a, 190},
- {0x800f, 190},
- {0x8018, 190},
- {0x801f, 190},
- {0x8029, 190},
- {0xc038, 190},
- {0x8003, 196},
- {0x8006, 196},
- {0x800a, 196},
- {0x800f, 196},
- {0x8018, 196},
- {0x801f, 196},
- {0x8029, 196},
- {0xc038, 196},
- },
- /* 142 */
- {
- {0x8001, 198},
- {0xc016, 198},
- {0x8001, 228},
- {0xc016, 228},
- {0x8001, 232},
- {0xc016, 232},
- {0x8001, 233},
- {0xc016, 233},
- {0xc000, 1},
- {0xc000, 135},
- {0xc000, 137},
- {0xc000, 138},
- {0xc000, 139},
- {0xc000, 140},
- {0xc000, 141},
- {0xc000, 143},
- },
- /* 143 */
- {
- {0x8002, 198},
- {0x8009, 198},
- {0x8017, 198},
- {0xc028, 198},
- {0x8002, 228},
- {0x8009, 228},
- {0x8017, 228},
- {0xc028, 228},
- {0x8002, 232},
- {0x8009, 232},
- {0x8017, 232},
- {0xc028, 232},
- {0x8002, 233},
- {0x8009, 233},
- {0x8017, 233},
- {0xc028, 233},
- },
- /* 144 */
- {
- {0x8003, 198},
- {0x8006, 198},
- {0x800a, 198},
- {0x800f, 198},
- {0x8018, 198},
- {0x801f, 198},
- {0x8029, 198},
- {0xc038, 198},
- {0x8003, 228},
- {0x8006, 228},
- {0x800a, 228},
- {0x800f, 228},
- {0x8018, 228},
- {0x801f, 228},
- {0x8029, 228},
- {0xc038, 228},
- },
- /* 145 */
- {
- {0x8003, 232},
- {0x8006, 232},
- {0x800a, 232},
- {0x800f, 232},
- {0x8018, 232},
- {0x801f, 232},
- {0x8029, 232},
- {0xc038, 232},
- {0x8003, 233},
- {0x8006, 233},
- {0x800a, 233},
- {0x800f, 233},
- {0x8018, 233},
- {0x801f, 233},
- {0x8029, 233},
- {0xc038, 233},
- },
- /* 146 */
- {
- {0x8001, 1},
- {0xc016, 1},
- {0x8001, 135},
- {0xc016, 135},
- {0x8001, 137},
- {0xc016, 137},
- {0x8001, 138},
- {0xc016, 138},
- {0x8001, 139},
- {0xc016, 139},
- {0x8001, 140},
- {0xc016, 140},
- {0x8001, 141},
- {0xc016, 141},
- {0x8001, 143},
- {0xc016, 143},
- },
- /* 147 */
- {
- {0x8002, 1},
- {0x8009, 1},
- {0x8017, 1},
- {0xc028, 1},
- {0x8002, 135},
- {0x8009, 135},
- {0x8017, 135},
- {0xc028, 135},
- {0x8002, 137},
- {0x8009, 137},
- {0x8017, 137},
- {0xc028, 137},
- {0x8002, 138},
- {0x8009, 138},
- {0x8017, 138},
- {0xc028, 138},
- },
- /* 148 */
- {
- {0x8003, 1},
- {0x8006, 1},
- {0x800a, 1},
- {0x800f, 1},
- {0x8018, 1},
- {0x801f, 1},
- {0x8029, 1},
- {0xc038, 1},
- {0x8003, 135},
- {0x8006, 135},
- {0x800a, 135},
- {0x800f, 135},
- {0x8018, 135},
- {0x801f, 135},
- {0x8029, 135},
- {0xc038, 135},
- },
- /* 149 */
- {
- {0x8003, 137},
- {0x8006, 137},
- {0x800a, 137},
- {0x800f, 137},
- {0x8018, 137},
- {0x801f, 137},
- {0x8029, 137},
- {0xc038, 137},
- {0x8003, 138},
- {0x8006, 138},
- {0x800a, 138},
- {0x800f, 138},
- {0x8018, 138},
- {0x801f, 138},
- {0x8029, 138},
- {0xc038, 138},
- },
- /* 150 */
- {
- {0x8002, 139},
- {0x8009, 139},
- {0x8017, 139},
- {0xc028, 139},
- {0x8002, 140},
- {0x8009, 140},
- {0x8017, 140},
- {0xc028, 140},
- {0x8002, 141},
- {0x8009, 141},
- {0x8017, 141},
- {0xc028, 141},
- {0x8002, 143},
- {0x8009, 143},
- {0x8017, 143},
- {0xc028, 143},
- },
- /* 151 */
- {
- {0x8003, 139},
- {0x8006, 139},
- {0x800a, 139},
- {0x800f, 139},
- {0x8018, 139},
- {0x801f, 139},
- {0x8029, 139},
- {0xc038, 139},
- {0x8003, 140},
- {0x8006, 140},
- {0x800a, 140},
- {0x800f, 140},
- {0x8018, 140},
- {0x801f, 140},
- {0x8029, 140},
- {0xc038, 140},
- },
- /* 152 */
- {
- {0x8003, 141},
- {0x8006, 141},
- {0x800a, 141},
- {0x800f, 141},
- {0x8018, 141},
- {0x801f, 141},
- {0x8029, 141},
- {0xc038, 141},
- {0x8003, 143},
- {0x8006, 143},
- {0x800a, 143},
- {0x800f, 143},
- {0x8018, 143},
- {0x801f, 143},
- {0x8029, 143},
- {0xc038, 143},
- },
- /* 153 */
- {
- {0x9d, 0},
- {0x9e, 0},
- {0xa0, 0},
- {0xa1, 0},
- {0xa4, 0},
- {0xa5, 0},
- {0xa7, 0},
- {0xa8, 0},
- {0xac, 0},
- {0xad, 0},
- {0xaf, 0},
- {0xb1, 0},
- {0xb6, 0},
- {0xb9, 0},
- {0xbf, 0},
- {0xcf, 0},
- },
- /* 154 */
- {
- {0xc000, 147},
- {0xc000, 149},
- {0xc000, 150},
- {0xc000, 151},
- {0xc000, 152},
- {0xc000, 155},
- {0xc000, 157},
- {0xc000, 158},
- {0xc000, 165},
- {0xc000, 166},
- {0xc000, 168},
- {0xc000, 174},
- {0xc000, 175},
- {0xc000, 180},
- {0xc000, 182},
- {0xc000, 183},
- },
- /* 155 */
- {
- {0x8001, 147},
- {0xc016, 147},
- {0x8001, 149},
- {0xc016, 149},
- {0x8001, 150},
- {0xc016, 150},
- {0x8001, 151},
- {0xc016, 151},
- {0x8001, 152},
- {0xc016, 152},
- {0x8001, 155},
- {0xc016, 155},
- {0x8001, 157},
- {0xc016, 157},
- {0x8001, 158},
- {0xc016, 158},
- },
- /* 156 */
- {
- {0x8002, 147},
- {0x8009, 147},
- {0x8017, 147},
- {0xc028, 147},
- {0x8002, 149},
- {0x8009, 149},
- {0x8017, 149},
- {0xc028, 149},
- {0x8002, 150},
- {0x8009, 150},
- {0x8017, 150},
- {0xc028, 150},
- {0x8002, 151},
- {0x8009, 151},
- {0x8017, 151},
- {0xc028, 151},
- },
- /* 157 */
- {
- {0x8003, 147},
- {0x8006, 147},
- {0x800a, 147},
- {0x800f, 147},
- {0x8018, 147},
- {0x801f, 147},
- {0x8029, 147},
- {0xc038, 147},
- {0x8003, 149},
- {0x8006, 149},
- {0x800a, 149},
- {0x800f, 149},
- {0x8018, 149},
- {0x801f, 149},
- {0x8029, 149},
- {0xc038, 149},
- },
- /* 158 */
- {
- {0x8003, 150},
- {0x8006, 150},
- {0x800a, 150},
- {0x800f, 150},
- {0x8018, 150},
- {0x801f, 150},
- {0x8029, 150},
- {0xc038, 150},
- {0x8003, 151},
- {0x8006, 151},
- {0x800a, 151},
- {0x800f, 151},
- {0x8018, 151},
- {0x801f, 151},
- {0x8029, 151},
- {0xc038, 151},
- },
- /* 159 */
- {
- {0x8002, 152},
- {0x8009, 152},
- {0x8017, 152},
- {0xc028, 152},
- {0x8002, 155},
- {0x8009, 155},
- {0x8017, 155},
- {0xc028, 155},
- {0x8002, 157},
- {0x8009, 157},
- {0x8017, 157},
- {0xc028, 157},
- {0x8002, 158},
- {0x8009, 158},
- {0x8017, 158},
- {0xc028, 158},
- },
- /* 160 */
- {
- {0x8003, 152},
- {0x8006, 152},
- {0x800a, 152},
- {0x800f, 152},
- {0x8018, 152},
- {0x801f, 152},
- {0x8029, 152},
- {0xc038, 152},
- {0x8003, 155},
- {0x8006, 155},
- {0x800a, 155},
- {0x800f, 155},
- {0x8018, 155},
- {0x801f, 155},
- {0x8029, 155},
- {0xc038, 155},
- },
- /* 161 */
- {
- {0x8003, 157},
- {0x8006, 157},
- {0x800a, 157},
- {0x800f, 157},
- {0x8018, 157},
- {0x801f, 157},
- {0x8029, 157},
- {0xc038, 157},
- {0x8003, 158},
- {0x8006, 158},
- {0x800a, 158},
- {0x800f, 158},
- {0x8018, 158},
- {0x801f, 158},
- {0x8029, 158},
- {0xc038, 158},
- },
- /* 162 */
- {
- {0x8001, 165},
- {0xc016, 165},
- {0x8001, 166},
- {0xc016, 166},
- {0x8001, 168},
- {0xc016, 168},
- {0x8001, 174},
- {0xc016, 174},
- {0x8001, 175},
- {0xc016, 175},
- {0x8001, 180},
- {0xc016, 180},
- {0x8001, 182},
- {0xc016, 182},
- {0x8001, 183},
- {0xc016, 183},
- },
- /* 163 */
- {
- {0x8002, 165},
- {0x8009, 165},
- {0x8017, 165},
- {0xc028, 165},
- {0x8002, 166},
- {0x8009, 166},
- {0x8017, 166},
- {0xc028, 166},
- {0x8002, 168},
- {0x8009, 168},
- {0x8017, 168},
- {0xc028, 168},
- {0x8002, 174},
- {0x8009, 174},
- {0x8017, 174},
- {0xc028, 174},
- },
- /* 164 */
- {
- {0x8003, 165},
- {0x8006, 165},
- {0x800a, 165},
- {0x800f, 165},
- {0x8018, 165},
- {0x801f, 165},
- {0x8029, 165},
- {0xc038, 165},
- {0x8003, 166},
- {0x8006, 166},
- {0x800a, 166},
- {0x800f, 166},
- {0x8018, 166},
- {0x801f, 166},
- {0x8029, 166},
- {0xc038, 166},
- },
- /* 165 */
- {
- {0x8003, 168},
- {0x8006, 168},
- {0x800a, 168},
- {0x800f, 168},
- {0x8018, 168},
- {0x801f, 168},
- {0x8029, 168},
- {0xc038, 168},
- {0x8003, 174},
- {0x8006, 174},
- {0x800a, 174},
- {0x800f, 174},
- {0x8018, 174},
- {0x801f, 174},
- {0x8029, 174},
- {0xc038, 174},
- },
- /* 166 */
- {
- {0x8002, 175},
- {0x8009, 175},
- {0x8017, 175},
- {0xc028, 175},
- {0x8002, 180},
- {0x8009, 180},
- {0x8017, 180},
- {0xc028, 180},
- {0x8002, 182},
- {0x8009, 182},
- {0x8017, 182},
- {0xc028, 182},
- {0x8002, 183},
- {0x8009, 183},
- {0x8017, 183},
- {0xc028, 183},
- },
- /* 167 */
- {
- {0x8003, 175},
- {0x8006, 175},
- {0x800a, 175},
- {0x800f, 175},
- {0x8018, 175},
- {0x801f, 175},
- {0x8029, 175},
- {0xc038, 175},
- {0x8003, 180},
- {0x8006, 180},
- {0x800a, 180},
- {0x800f, 180},
- {0x8018, 180},
- {0x801f, 180},
- {0x8029, 180},
- {0xc038, 180},
- },
- /* 168 */
- {
- {0x8003, 182},
- {0x8006, 182},
- {0x800a, 182},
- {0x800f, 182},
- {0x8018, 182},
- {0x801f, 182},
- {0x8029, 182},
- {0xc038, 182},
- {0x8003, 183},
- {0x8006, 183},
- {0x800a, 183},
- {0x800f, 183},
- {0x8018, 183},
- {0x801f, 183},
- {0x8029, 183},
- {0xc038, 183},
- },
- /* 169 */
- {
- {0xc000, 188},
- {0xc000, 191},
- {0xc000, 197},
- {0xc000, 231},
- {0xc000, 239},
- {0xb0, 0},
- {0xb2, 0},
- {0xb3, 0},
- {0xb7, 0},
- {0xb8, 0},
- {0xba, 0},
- {0xbb, 0},
- {0xc0, 0},
- {0xc7, 0},
- {0xd0, 0},
- {0xdf, 0},
- },
- /* 170 */
- {
- {0x8001, 188},
- {0xc016, 188},
- {0x8001, 191},
- {0xc016, 191},
- {0x8001, 197},
- {0xc016, 197},
- {0x8001, 231},
- {0xc016, 231},
- {0x8001, 239},
- {0xc016, 239},
- {0xc000, 9},
- {0xc000, 142},
- {0xc000, 144},
- {0xc000, 145},
- {0xc000, 148},
- {0xc000, 159},
- },
- /* 171 */
- {
- {0x8002, 188},
- {0x8009, 188},
- {0x8017, 188},
- {0xc028, 188},
- {0x8002, 191},
- {0x8009, 191},
- {0x8017, 191},
- {0xc028, 191},
- {0x8002, 197},
- {0x8009, 197},
- {0x8017, 197},
- {0xc028, 197},
- {0x8002, 231},
- {0x8009, 231},
- {0x8017, 231},
- {0xc028, 231},
- },
- /* 172 */
- {
- {0x8003, 188},
- {0x8006, 188},
- {0x800a, 188},
- {0x800f, 188},
- {0x8018, 188},
- {0x801f, 188},
- {0x8029, 188},
- {0xc038, 188},
- {0x8003, 191},
- {0x8006, 191},
- {0x800a, 191},
- {0x800f, 191},
- {0x8018, 191},
- {0x801f, 191},
- {0x8029, 191},
- {0xc038, 191},
- },
- /* 173 */
- {
- {0x8003, 197},
- {0x8006, 197},
- {0x800a, 197},
- {0x800f, 197},
- {0x8018, 197},
- {0x801f, 197},
- {0x8029, 197},
- {0xc038, 197},
- {0x8003, 231},
- {0x8006, 231},
- {0x800a, 231},
- {0x800f, 231},
- {0x8018, 231},
- {0x801f, 231},
- {0x8029, 231},
- {0xc038, 231},
- },
- /* 174 */
- {
- {0x8002, 239},
- {0x8009, 239},
- {0x8017, 239},
- {0xc028, 239},
- {0x8001, 9},
- {0xc016, 9},
- {0x8001, 142},
- {0xc016, 142},
- {0x8001, 144},
- {0xc016, 144},
- {0x8001, 145},
- {0xc016, 145},
- {0x8001, 148},
- {0xc016, 148},
- {0x8001, 159},
- {0xc016, 159},
- },
- /* 175 */
- {
- {0x8003, 239},
- {0x8006, 239},
- {0x800a, 239},
- {0x800f, 239},
- {0x8018, 239},
- {0x801f, 239},
- {0x8029, 239},
- {0xc038, 239},
- {0x8002, 9},
- {0x8009, 9},
- {0x8017, 9},
- {0xc028, 9},
- {0x8002, 142},
- {0x8009, 142},
- {0x8017, 142},
- {0xc028, 142},
- },
- /* 176 */
- {
- {0x8003, 9},
- {0x8006, 9},
- {0x800a, 9},
- {0x800f, 9},
- {0x8018, 9},
- {0x801f, 9},
- {0x8029, 9},
- {0xc038, 9},
- {0x8003, 142},
- {0x8006, 142},
- {0x800a, 142},
- {0x800f, 142},
- {0x8018, 142},
- {0x801f, 142},
- {0x8029, 142},
- {0xc038, 142},
- },
- /* 177 */
- {
- {0x8002, 144},
- {0x8009, 144},
- {0x8017, 144},
- {0xc028, 144},
- {0x8002, 145},
- {0x8009, 145},
- {0x8017, 145},
- {0xc028, 145},
- {0x8002, 148},
- {0x8009, 148},
- {0x8017, 148},
- {0xc028, 148},
- {0x8002, 159},
- {0x8009, 159},
- {0x8017, 159},
- {0xc028, 159},
- },
- /* 178 */
- {
- {0x8003, 144},
- {0x8006, 144},
- {0x800a, 144},
- {0x800f, 144},
- {0x8018, 144},
- {0x801f, 144},
- {0x8029, 144},
- {0xc038, 144},
- {0x8003, 145},
- {0x8006, 145},
- {0x800a, 145},
- {0x800f, 145},
- {0x8018, 145},
- {0x801f, 145},
- {0x8029, 145},
- {0xc038, 145},
- },
- /* 179 */
- {
- {0x8003, 148},
- {0x8006, 148},
- {0x800a, 148},
- {0x800f, 148},
- {0x8018, 148},
- {0x801f, 148},
- {0x8029, 148},
- {0xc038, 148},
- {0x8003, 159},
- {0x8006, 159},
- {0x800a, 159},
- {0x800f, 159},
- {0x8018, 159},
- {0x801f, 159},
- {0x8029, 159},
- {0xc038, 159},
- },
- /* 180 */
- {
- {0xc000, 171},
- {0xc000, 206},
- {0xc000, 215},
- {0xc000, 225},
- {0xc000, 236},
- {0xc000, 237},
- {0xbc, 0},
- {0xbd, 0},
- {0xc1, 0},
- {0xc4, 0},
- {0xc8, 0},
- {0xcb, 0},
- {0xd1, 0},
- {0xd8, 0},
- {0xe0, 0},
- {0xee, 0},
- },
- /* 181 */
- {
- {0x8001, 171},
- {0xc016, 171},
- {0x8001, 206},
- {0xc016, 206},
- {0x8001, 215},
- {0xc016, 215},
- {0x8001, 225},
- {0xc016, 225},
- {0x8001, 236},
- {0xc016, 236},
- {0x8001, 237},
- {0xc016, 237},
- {0xc000, 199},
- {0xc000, 207},
- {0xc000, 234},
- {0xc000, 235},
- },
- /* 182 */
- {
- {0x8002, 171},
- {0x8009, 171},
- {0x8017, 171},
- {0xc028, 171},
- {0x8002, 206},
- {0x8009, 206},
- {0x8017, 206},
- {0xc028, 206},
- {0x8002, 215},
- {0x8009, 215},
- {0x8017, 215},
- {0xc028, 215},
- {0x8002, 225},
- {0x8009, 225},
- {0x8017, 225},
- {0xc028, 225},
- },
- /* 183 */
- {
- {0x8003, 171},
- {0x8006, 171},
- {0x800a, 171},
- {0x800f, 171},
- {0x8018, 171},
- {0x801f, 171},
- {0x8029, 171},
- {0xc038, 171},
- {0x8003, 206},
- {0x8006, 206},
- {0x800a, 206},
- {0x800f, 206},
- {0x8018, 206},
- {0x801f, 206},
- {0x8029, 206},
- {0xc038, 206},
- },
- /* 184 */
- {
- {0x8003, 215},
- {0x8006, 215},
- {0x800a, 215},
- {0x800f, 215},
- {0x8018, 215},
- {0x801f, 215},
- {0x8029, 215},
- {0xc038, 215},
- {0x8003, 225},
- {0x8006, 225},
- {0x800a, 225},
- {0x800f, 225},
- {0x8018, 225},
- {0x801f, 225},
- {0x8029, 225},
- {0xc038, 225},
- },
- /* 185 */
- {
- {0x8002, 236},
- {0x8009, 236},
- {0x8017, 236},
- {0xc028, 236},
- {0x8002, 237},
- {0x8009, 237},
- {0x8017, 237},
- {0xc028, 237},
- {0x8001, 199},
- {0xc016, 199},
- {0x8001, 207},
- {0xc016, 207},
- {0x8001, 234},
- {0xc016, 234},
- {0x8001, 235},
- {0xc016, 235},
- },
- /* 186 */
- {
- {0x8003, 236},
- {0x8006, 236},
- {0x800a, 236},
- {0x800f, 236},
- {0x8018, 236},
- {0x801f, 236},
- {0x8029, 236},
- {0xc038, 236},
- {0x8003, 237},
- {0x8006, 237},
- {0x800a, 237},
- {0x800f, 237},
- {0x8018, 237},
- {0x801f, 237},
- {0x8029, 237},
- {0xc038, 237},
- },
- /* 187 */
- {
- {0x8002, 199},
- {0x8009, 199},
- {0x8017, 199},
- {0xc028, 199},
- {0x8002, 207},
- {0x8009, 207},
- {0x8017, 207},
- {0xc028, 207},
- {0x8002, 234},
- {0x8009, 234},
- {0x8017, 234},
- {0xc028, 234},
- {0x8002, 235},
- {0x8009, 235},
- {0x8017, 235},
- {0xc028, 235},
- },
- /* 188 */
- {
- {0x8003, 199},
- {0x8006, 199},
- {0x800a, 199},
- {0x800f, 199},
- {0x8018, 199},
- {0x801f, 199},
- {0x8029, 199},
- {0xc038, 199},
- {0x8003, 207},
- {0x8006, 207},
- {0x800a, 207},
- {0x800f, 207},
- {0x8018, 207},
- {0x801f, 207},
- {0x8029, 207},
- {0xc038, 207},
- },
- /* 189 */
- {
- {0x8003, 234},
- {0x8006, 234},
- {0x800a, 234},
- {0x800f, 234},
- {0x8018, 234},
- {0x801f, 234},
- {0x8029, 234},
- {0xc038, 234},
- {0x8003, 235},
- {0x8006, 235},
- {0x800a, 235},
- {0x800f, 235},
- {0x8018, 235},
- {0x801f, 235},
- {0x8029, 235},
- {0xc038, 235},
- },
- /* 190 */
- {
- {0xc2, 0},
- {0xc3, 0},
- {0xc5, 0},
- {0xc6, 0},
- {0xc9, 0},
- {0xca, 0},
- {0xcc, 0},
- {0xcd, 0},
- {0xd2, 0},
- {0xd5, 0},
- {0xd9, 0},
- {0xdc, 0},
- {0xe1, 0},
- {0xe7, 0},
- {0xef, 0},
- {0xf6, 0},
- },
- /* 191 */
- {
- {0xc000, 192},
- {0xc000, 193},
- {0xc000, 200},
- {0xc000, 201},
- {0xc000, 202},
- {0xc000, 205},
- {0xc000, 210},
- {0xc000, 213},
- {0xc000, 218},
- {0xc000, 219},
- {0xc000, 238},
- {0xc000, 240},
- {0xc000, 242},
- {0xc000, 243},
- {0xc000, 255},
- {0xce, 0},
- },
- /* 192 */
- {
- {0x8001, 192},
- {0xc016, 192},
- {0x8001, 193},
- {0xc016, 193},
- {0x8001, 200},
- {0xc016, 200},
- {0x8001, 201},
- {0xc016, 201},
- {0x8001, 202},
- {0xc016, 202},
- {0x8001, 205},
- {0xc016, 205},
- {0x8001, 210},
- {0xc016, 210},
- {0x8001, 213},
- {0xc016, 213},
- },
- /* 193 */
- {
- {0x8002, 192},
- {0x8009, 192},
- {0x8017, 192},
- {0xc028, 192},
- {0x8002, 193},
- {0x8009, 193},
- {0x8017, 193},
- {0xc028, 193},
- {0x8002, 200},
- {0x8009, 200},
- {0x8017, 200},
- {0xc028, 200},
- {0x8002, 201},
- {0x8009, 201},
- {0x8017, 201},
- {0xc028, 201},
- },
- /* 194 */
- {
- {0x8003, 192},
- {0x8006, 192},
- {0x800a, 192},
- {0x800f, 192},
- {0x8018, 192},
- {0x801f, 192},
- {0x8029, 192},
- {0xc038, 192},
- {0x8003, 193},
- {0x8006, 193},
- {0x800a, 193},
- {0x800f, 193},
- {0x8018, 193},
- {0x801f, 193},
- {0x8029, 193},
- {0xc038, 193},
- },
- /* 195 */
- {
- {0x8003, 200},
- {0x8006, 200},
- {0x800a, 200},
- {0x800f, 200},
- {0x8018, 200},
- {0x801f, 200},
- {0x8029, 200},
- {0xc038, 200},
- {0x8003, 201},
- {0x8006, 201},
- {0x800a, 201},
- {0x800f, 201},
- {0x8018, 201},
- {0x801f, 201},
- {0x8029, 201},
- {0xc038, 201},
- },
- /* 196 */
- {
- {0x8002, 202},
- {0x8009, 202},
- {0x8017, 202},
- {0xc028, 202},
- {0x8002, 205},
- {0x8009, 205},
- {0x8017, 205},
- {0xc028, 205},
- {0x8002, 210},
- {0x8009, 210},
- {0x8017, 210},
- {0xc028, 210},
- {0x8002, 213},
- {0x8009, 213},
- {0x8017, 213},
- {0xc028, 213},
- },
- /* 197 */
- {
- {0x8003, 202},
- {0x8006, 202},
- {0x800a, 202},
- {0x800f, 202},
- {0x8018, 202},
- {0x801f, 202},
- {0x8029, 202},
- {0xc038, 202},
- {0x8003, 205},
- {0x8006, 205},
- {0x800a, 205},
- {0x800f, 205},
- {0x8018, 205},
- {0x801f, 205},
- {0x8029, 205},
- {0xc038, 205},
- },
- /* 198 */
- {
- {0x8003, 210},
- {0x8006, 210},
- {0x800a, 210},
- {0x800f, 210},
- {0x8018, 210},
- {0x801f, 210},
- {0x8029, 210},
- {0xc038, 210},
- {0x8003, 213},
- {0x8006, 213},
- {0x800a, 213},
- {0x800f, 213},
- {0x8018, 213},
- {0x801f, 213},
- {0x8029, 213},
- {0xc038, 213},
- },
- /* 199 */
- {
- {0x8001, 218},
- {0xc016, 218},
- {0x8001, 219},
- {0xc016, 219},
- {0x8001, 238},
- {0xc016, 238},
- {0x8001, 240},
- {0xc016, 240},
- {0x8001, 242},
- {0xc016, 242},
- {0x8001, 243},
- {0xc016, 243},
- {0x8001, 255},
- {0xc016, 255},
- {0xc000, 203},
- {0xc000, 204},
- },
- /* 200 */
- {
- {0x8002, 218},
- {0x8009, 218},
- {0x8017, 218},
- {0xc028, 218},
- {0x8002, 219},
- {0x8009, 219},
- {0x8017, 219},
- {0xc028, 219},
- {0x8002, 238},
- {0x8009, 238},
- {0x8017, 238},
- {0xc028, 238},
- {0x8002, 240},
- {0x8009, 240},
- {0x8017, 240},
- {0xc028, 240},
- },
- /* 201 */
- {
- {0x8003, 218},
- {0x8006, 218},
- {0x800a, 218},
- {0x800f, 218},
- {0x8018, 218},
- {0x801f, 218},
- {0x8029, 218},
- {0xc038, 218},
- {0x8003, 219},
- {0x8006, 219},
- {0x800a, 219},
- {0x800f, 219},
- {0x8018, 219},
- {0x801f, 219},
- {0x8029, 219},
- {0xc038, 219},
- },
- /* 202 */
- {
- {0x8003, 238},
- {0x8006, 238},
- {0x800a, 238},
- {0x800f, 238},
- {0x8018, 238},
- {0x801f, 238},
- {0x8029, 238},
- {0xc038, 238},
- {0x8003, 240},
- {0x8006, 240},
- {0x800a, 240},
- {0x800f, 240},
- {0x8018, 240},
- {0x801f, 240},
- {0x8029, 240},
- {0xc038, 240},
- },
- /* 203 */
- {
- {0x8002, 242},
- {0x8009, 242},
- {0x8017, 242},
- {0xc028, 242},
- {0x8002, 243},
- {0x8009, 243},
- {0x8017, 243},
- {0xc028, 243},
- {0x8002, 255},
- {0x8009, 255},
- {0x8017, 255},
- {0xc028, 255},
- {0x8001, 203},
- {0xc016, 203},
- {0x8001, 204},
- {0xc016, 204},
- },
- /* 204 */
- {
- {0x8003, 242},
- {0x8006, 242},
- {0x800a, 242},
- {0x800f, 242},
- {0x8018, 242},
- {0x801f, 242},
- {0x8029, 242},
- {0xc038, 242},
- {0x8003, 243},
- {0x8006, 243},
- {0x800a, 243},
- {0x800f, 243},
- {0x8018, 243},
- {0x801f, 243},
- {0x8029, 243},
- {0xc038, 243},
- },
- /* 205 */
- {
- {0x8003, 255},
- {0x8006, 255},
- {0x800a, 255},
- {0x800f, 255},
- {0x8018, 255},
- {0x801f, 255},
- {0x8029, 255},
- {0xc038, 255},
- {0x8002, 203},
- {0x8009, 203},
- {0x8017, 203},
- {0xc028, 203},
- {0x8002, 204},
- {0x8009, 204},
- {0x8017, 204},
- {0xc028, 204},
- },
- /* 206 */
- {
- {0x8003, 203},
- {0x8006, 203},
- {0x800a, 203},
- {0x800f, 203},
- {0x8018, 203},
- {0x801f, 203},
- {0x8029, 203},
- {0xc038, 203},
- {0x8003, 204},
- {0x8006, 204},
- {0x800a, 204},
- {0x800f, 204},
- {0x8018, 204},
- {0x801f, 204},
- {0x8029, 204},
- {0xc038, 204},
- },
- /* 207 */
- {
- {0xd3, 0},
- {0xd4, 0},
- {0xd6, 0},
- {0xd7, 0},
- {0xda, 0},
- {0xdb, 0},
- {0xdd, 0},
- {0xde, 0},
- {0xe2, 0},
- {0xe4, 0},
- {0xe8, 0},
- {0xeb, 0},
- {0xf0, 0},
- {0xf3, 0},
- {0xf7, 0},
- {0xfa, 0},
- },
- /* 208 */
- {
- {0xc000, 211},
- {0xc000, 212},
- {0xc000, 214},
- {0xc000, 221},
- {0xc000, 222},
- {0xc000, 223},
- {0xc000, 241},
- {0xc000, 244},
- {0xc000, 245},
- {0xc000, 246},
- {0xc000, 247},
- {0xc000, 248},
- {0xc000, 250},
- {0xc000, 251},
- {0xc000, 252},
- {0xc000, 253},
- },
- /* 209 */
- {
- {0x8001, 211},
- {0xc016, 211},
- {0x8001, 212},
- {0xc016, 212},
- {0x8001, 214},
- {0xc016, 214},
- {0x8001, 221},
- {0xc016, 221},
- {0x8001, 222},
- {0xc016, 222},
- {0x8001, 223},
- {0xc016, 223},
- {0x8001, 241},
- {0xc016, 241},
- {0x8001, 244},
- {0xc016, 244},
- },
- /* 210 */
- {
- {0x8002, 211},
- {0x8009, 211},
- {0x8017, 211},
- {0xc028, 211},
- {0x8002, 212},
- {0x8009, 212},
- {0x8017, 212},
- {0xc028, 212},
- {0x8002, 214},
- {0x8009, 214},
- {0x8017, 214},
- {0xc028, 214},
- {0x8002, 221},
- {0x8009, 221},
- {0x8017, 221},
- {0xc028, 221},
- },
- /* 211 */
- {
- {0x8003, 211},
- {0x8006, 211},
- {0x800a, 211},
- {0x800f, 211},
- {0x8018, 211},
- {0x801f, 211},
- {0x8029, 211},
- {0xc038, 211},
- {0x8003, 212},
- {0x8006, 212},
- {0x800a, 212},
- {0x800f, 212},
- {0x8018, 212},
- {0x801f, 212},
- {0x8029, 212},
- {0xc038, 212},
- },
- /* 212 */
- {
- {0x8003, 214},
- {0x8006, 214},
- {0x800a, 214},
- {0x800f, 214},
- {0x8018, 214},
- {0x801f, 214},
- {0x8029, 214},
- {0xc038, 214},
- {0x8003, 221},
- {0x8006, 221},
- {0x800a, 221},
- {0x800f, 221},
- {0x8018, 221},
- {0x801f, 221},
- {0x8029, 221},
- {0xc038, 221},
- },
- /* 213 */
- {
- {0x8002, 222},
- {0x8009, 222},
- {0x8017, 222},
- {0xc028, 222},
- {0x8002, 223},
- {0x8009, 223},
- {0x8017, 223},
- {0xc028, 223},
- {0x8002, 241},
- {0x8009, 241},
- {0x8017, 241},
- {0xc028, 241},
- {0x8002, 244},
- {0x8009, 244},
- {0x8017, 244},
- {0xc028, 244},
- },
- /* 214 */
- {
- {0x8003, 222},
- {0x8006, 222},
- {0x800a, 222},
- {0x800f, 222},
- {0x8018, 222},
- {0x801f, 222},
- {0x8029, 222},
- {0xc038, 222},
- {0x8003, 223},
- {0x8006, 223},
- {0x800a, 223},
- {0x800f, 223},
- {0x8018, 223},
- {0x801f, 223},
- {0x8029, 223},
- {0xc038, 223},
- },
- /* 215 */
- {
- {0x8003, 241},
- {0x8006, 241},
- {0x800a, 241},
- {0x800f, 241},
- {0x8018, 241},
- {0x801f, 241},
- {0x8029, 241},
- {0xc038, 241},
- {0x8003, 244},
- {0x8006, 244},
- {0x800a, 244},
- {0x800f, 244},
- {0x8018, 244},
- {0x801f, 244},
- {0x8029, 244},
- {0xc038, 244},
- },
- /* 216 */
- {
- {0x8001, 245},
- {0xc016, 245},
- {0x8001, 246},
- {0xc016, 246},
- {0x8001, 247},
- {0xc016, 247},
- {0x8001, 248},
- {0xc016, 248},
- {0x8001, 250},
- {0xc016, 250},
- {0x8001, 251},
- {0xc016, 251},
- {0x8001, 252},
- {0xc016, 252},
- {0x8001, 253},
- {0xc016, 253},
- },
- /* 217 */
- {
- {0x8002, 245},
- {0x8009, 245},
- {0x8017, 245},
- {0xc028, 245},
- {0x8002, 246},
- {0x8009, 246},
- {0x8017, 246},
- {0xc028, 246},
- {0x8002, 247},
- {0x8009, 247},
- {0x8017, 247},
- {0xc028, 247},
- {0x8002, 248},
- {0x8009, 248},
- {0x8017, 248},
- {0xc028, 248},
- },
- /* 218 */
- {
- {0x8003, 245},
- {0x8006, 245},
- {0x800a, 245},
- {0x800f, 245},
- {0x8018, 245},
- {0x801f, 245},
- {0x8029, 245},
- {0xc038, 245},
- {0x8003, 246},
- {0x8006, 246},
- {0x800a, 246},
- {0x800f, 246},
- {0x8018, 246},
- {0x801f, 246},
- {0x8029, 246},
- {0xc038, 246},
- },
- /* 219 */
- {
- {0x8003, 247},
- {0x8006, 247},
- {0x800a, 247},
- {0x800f, 247},
- {0x8018, 247},
- {0x801f, 247},
- {0x8029, 247},
- {0xc038, 247},
- {0x8003, 248},
- {0x8006, 248},
- {0x800a, 248},
- {0x800f, 248},
- {0x8018, 248},
- {0x801f, 248},
- {0x8029, 248},
- {0xc038, 248},
- },
- /* 220 */
- {
- {0x8002, 250},
- {0x8009, 250},
- {0x8017, 250},
- {0xc028, 250},
- {0x8002, 251},
- {0x8009, 251},
- {0x8017, 251},
- {0xc028, 251},
- {0x8002, 252},
- {0x8009, 252},
- {0x8017, 252},
- {0xc028, 252},
- {0x8002, 253},
- {0x8009, 253},
- {0x8017, 253},
- {0xc028, 253},
- },
- /* 221 */
- {
- {0x8003, 250},
- {0x8006, 250},
- {0x800a, 250},
- {0x800f, 250},
- {0x8018, 250},
- {0x801f, 250},
- {0x8029, 250},
- {0xc038, 250},
- {0x8003, 251},
- {0x8006, 251},
- {0x800a, 251},
- {0x800f, 251},
- {0x8018, 251},
- {0x801f, 251},
- {0x8029, 251},
- {0xc038, 251},
- },
- /* 222 */
- {
- {0x8003, 252},
- {0x8006, 252},
- {0x800a, 252},
- {0x800f, 252},
- {0x8018, 252},
- {0x801f, 252},
- {0x8029, 252},
- {0xc038, 252},
- {0x8003, 253},
- {0x8006, 253},
- {0x800a, 253},
- {0x800f, 253},
- {0x8018, 253},
- {0x801f, 253},
- {0x8029, 253},
- {0xc038, 253},
- },
- /* 223 */
- {
- {0xc000, 254},
- {0xe3, 0},
- {0xe5, 0},
- {0xe6, 0},
- {0xe9, 0},
- {0xea, 0},
- {0xec, 0},
- {0xed, 0},
- {0xf1, 0},
- {0xf2, 0},
- {0xf4, 0},
- {0xf5, 0},
- {0xf8, 0},
- {0xf9, 0},
- {0xfb, 0},
- {0xfc, 0},
- },
- /* 224 */
- {
- {0x8001, 254},
- {0xc016, 254},
- {0xc000, 2},
- {0xc000, 3},
- {0xc000, 4},
- {0xc000, 5},
- {0xc000, 6},
- {0xc000, 7},
- {0xc000, 8},
- {0xc000, 11},
- {0xc000, 12},
- {0xc000, 14},
- {0xc000, 15},
- {0xc000, 16},
- {0xc000, 17},
- {0xc000, 18},
- },
- /* 225 */
- {
- {0x8002, 254},
- {0x8009, 254},
- {0x8017, 254},
- {0xc028, 254},
- {0x8001, 2},
- {0xc016, 2},
- {0x8001, 3},
- {0xc016, 3},
- {0x8001, 4},
- {0xc016, 4},
- {0x8001, 5},
- {0xc016, 5},
- {0x8001, 6},
- {0xc016, 6},
- {0x8001, 7},
- {0xc016, 7},
- },
- /* 226 */
- {
- {0x8003, 254},
- {0x8006, 254},
- {0x800a, 254},
- {0x800f, 254},
- {0x8018, 254},
- {0x801f, 254},
- {0x8029, 254},
- {0xc038, 254},
- {0x8002, 2},
- {0x8009, 2},
- {0x8017, 2},
- {0xc028, 2},
- {0x8002, 3},
- {0x8009, 3},
- {0x8017, 3},
- {0xc028, 3},
- },
- /* 227 */
- {
- {0x8003, 2},
- {0x8006, 2},
- {0x800a, 2},
- {0x800f, 2},
- {0x8018, 2},
- {0x801f, 2},
- {0x8029, 2},
- {0xc038, 2},
- {0x8003, 3},
- {0x8006, 3},
- {0x800a, 3},
- {0x800f, 3},
- {0x8018, 3},
- {0x801f, 3},
- {0x8029, 3},
- {0xc038, 3},
- },
- /* 228 */
- {
- {0x8002, 4},
- {0x8009, 4},
- {0x8017, 4},
- {0xc028, 4},
- {0x8002, 5},
- {0x8009, 5},
- {0x8017, 5},
- {0xc028, 5},
- {0x8002, 6},
- {0x8009, 6},
- {0x8017, 6},
- {0xc028, 6},
- {0x8002, 7},
- {0x8009, 7},
- {0x8017, 7},
- {0xc028, 7},
- },
- /* 229 */
- {
- {0x8003, 4},
- {0x8006, 4},
- {0x800a, 4},
- {0x800f, 4},
- {0x8018, 4},
- {0x801f, 4},
- {0x8029, 4},
- {0xc038, 4},
- {0x8003, 5},
- {0x8006, 5},
- {0x800a, 5},
- {0x800f, 5},
- {0x8018, 5},
- {0x801f, 5},
- {0x8029, 5},
- {0xc038, 5},
- },
- /* 230 */
- {
- {0x8003, 6},
- {0x8006, 6},
- {0x800a, 6},
- {0x800f, 6},
- {0x8018, 6},
- {0x801f, 6},
- {0x8029, 6},
- {0xc038, 6},
- {0x8003, 7},
- {0x8006, 7},
- {0x800a, 7},
- {0x800f, 7},
- {0x8018, 7},
- {0x801f, 7},
- {0x8029, 7},
- {0xc038, 7},
- },
- /* 231 */
- {
- {0x8001, 8},
- {0xc016, 8},
- {0x8001, 11},
- {0xc016, 11},
- {0x8001, 12},
- {0xc016, 12},
- {0x8001, 14},
- {0xc016, 14},
- {0x8001, 15},
- {0xc016, 15},
- {0x8001, 16},
- {0xc016, 16},
- {0x8001, 17},
- {0xc016, 17},
- {0x8001, 18},
- {0xc016, 18},
- },
- /* 232 */
- {
- {0x8002, 8},
- {0x8009, 8},
- {0x8017, 8},
- {0xc028, 8},
- {0x8002, 11},
- {0x8009, 11},
- {0x8017, 11},
- {0xc028, 11},
- {0x8002, 12},
- {0x8009, 12},
- {0x8017, 12},
- {0xc028, 12},
- {0x8002, 14},
- {0x8009, 14},
- {0x8017, 14},
- {0xc028, 14},
- },
- /* 233 */
- {
- {0x8003, 8},
- {0x8006, 8},
- {0x800a, 8},
- {0x800f, 8},
- {0x8018, 8},
- {0x801f, 8},
- {0x8029, 8},
- {0xc038, 8},
- {0x8003, 11},
- {0x8006, 11},
- {0x800a, 11},
- {0x800f, 11},
- {0x8018, 11},
- {0x801f, 11},
- {0x8029, 11},
- {0xc038, 11},
- },
- /* 234 */
- {
- {0x8003, 12},
- {0x8006, 12},
- {0x800a, 12},
- {0x800f, 12},
- {0x8018, 12},
- {0x801f, 12},
- {0x8029, 12},
- {0xc038, 12},
- {0x8003, 14},
- {0x8006, 14},
- {0x800a, 14},
- {0x800f, 14},
- {0x8018, 14},
- {0x801f, 14},
- {0x8029, 14},
- {0xc038, 14},
- },
- /* 235 */
- {
- {0x8002, 15},
- {0x8009, 15},
- {0x8017, 15},
- {0xc028, 15},
- {0x8002, 16},
- {0x8009, 16},
- {0x8017, 16},
- {0xc028, 16},
- {0x8002, 17},
- {0x8009, 17},
- {0x8017, 17},
- {0xc028, 17},
- {0x8002, 18},
- {0x8009, 18},
- {0x8017, 18},
- {0xc028, 18},
- },
- /* 236 */
- {
- {0x8003, 15},
- {0x8006, 15},
- {0x800a, 15},
- {0x800f, 15},
- {0x8018, 15},
- {0x801f, 15},
- {0x8029, 15},
- {0xc038, 15},
- {0x8003, 16},
- {0x8006, 16},
- {0x800a, 16},
- {0x800f, 16},
- {0x8018, 16},
- {0x801f, 16},
- {0x8029, 16},
- {0xc038, 16},
- },
- /* 237 */
- {
- {0x8003, 17},
- {0x8006, 17},
- {0x800a, 17},
- {0x800f, 17},
- {0x8018, 17},
- {0x801f, 17},
- {0x8029, 17},
- {0xc038, 17},
- {0x8003, 18},
- {0x8006, 18},
- {0x800a, 18},
- {0x800f, 18},
- {0x8018, 18},
- {0x801f, 18},
- {0x8029, 18},
- {0xc038, 18},
- },
- /* 238 */
- {
- {0xc000, 19},
- {0xc000, 20},
- {0xc000, 21},
- {0xc000, 23},
- {0xc000, 24},
- {0xc000, 25},
- {0xc000, 26},
- {0xc000, 27},
- {0xc000, 28},
- {0xc000, 29},
- {0xc000, 30},
- {0xc000, 31},
- {0xc000, 127},
- {0xc000, 220},
- {0xc000, 249},
- {0xfd, 0},
- },
- /* 239 */
- {
- {0x8001, 19},
- {0xc016, 19},
- {0x8001, 20},
- {0xc016, 20},
- {0x8001, 21},
- {0xc016, 21},
- {0x8001, 23},
- {0xc016, 23},
- {0x8001, 24},
- {0xc016, 24},
- {0x8001, 25},
- {0xc016, 25},
- {0x8001, 26},
- {0xc016, 26},
- {0x8001, 27},
- {0xc016, 27},
- },
- /* 240 */
- {
- {0x8002, 19},
- {0x8009, 19},
- {0x8017, 19},
- {0xc028, 19},
- {0x8002, 20},
- {0x8009, 20},
- {0x8017, 20},
- {0xc028, 20},
- {0x8002, 21},
- {0x8009, 21},
- {0x8017, 21},
- {0xc028, 21},
- {0x8002, 23},
- {0x8009, 23},
- {0x8017, 23},
- {0xc028, 23},
- },
- /* 241 */
- {
- {0x8003, 19},
- {0x8006, 19},
- {0x800a, 19},
- {0x800f, 19},
- {0x8018, 19},
- {0x801f, 19},
- {0x8029, 19},
- {0xc038, 19},
- {0x8003, 20},
- {0x8006, 20},
- {0x800a, 20},
- {0x800f, 20},
- {0x8018, 20},
- {0x801f, 20},
- {0x8029, 20},
- {0xc038, 20},
- },
- /* 242 */
- {
- {0x8003, 21},
- {0x8006, 21},
- {0x800a, 21},
- {0x800f, 21},
- {0x8018, 21},
- {0x801f, 21},
- {0x8029, 21},
- {0xc038, 21},
- {0x8003, 23},
- {0x8006, 23},
- {0x800a, 23},
- {0x800f, 23},
- {0x8018, 23},
- {0x801f, 23},
- {0x8029, 23},
- {0xc038, 23},
- },
- /* 243 */
- {
- {0x8002, 24},
- {0x8009, 24},
- {0x8017, 24},
- {0xc028, 24},
- {0x8002, 25},
- {0x8009, 25},
- {0x8017, 25},
- {0xc028, 25},
- {0x8002, 26},
- {0x8009, 26},
- {0x8017, 26},
- {0xc028, 26},
- {0x8002, 27},
- {0x8009, 27},
- {0x8017, 27},
- {0xc028, 27},
- },
- /* 244 */
- {
- {0x8003, 24},
- {0x8006, 24},
- {0x800a, 24},
- {0x800f, 24},
- {0x8018, 24},
- {0x801f, 24},
- {0x8029, 24},
- {0xc038, 24},
- {0x8003, 25},
- {0x8006, 25},
- {0x800a, 25},
- {0x800f, 25},
- {0x8018, 25},
- {0x801f, 25},
- {0x8029, 25},
- {0xc038, 25},
- },
- /* 245 */
- {
- {0x8003, 26},
- {0x8006, 26},
- {0x800a, 26},
- {0x800f, 26},
- {0x8018, 26},
- {0x801f, 26},
- {0x8029, 26},
- {0xc038, 26},
- {0x8003, 27},
- {0x8006, 27},
- {0x800a, 27},
- {0x800f, 27},
- {0x8018, 27},
- {0x801f, 27},
- {0x8029, 27},
- {0xc038, 27},
- },
- /* 246 */
- {
- {0x8001, 28},
- {0xc016, 28},
- {0x8001, 29},
- {0xc016, 29},
- {0x8001, 30},
- {0xc016, 30},
- {0x8001, 31},
- {0xc016, 31},
- {0x8001, 127},
- {0xc016, 127},
- {0x8001, 220},
- {0xc016, 220},
- {0x8001, 249},
- {0xc016, 249},
- {0xfe, 0},
- {0xff, 0},
- },
- /* 247 */
- {
- {0x8002, 28},
- {0x8009, 28},
- {0x8017, 28},
- {0xc028, 28},
- {0x8002, 29},
- {0x8009, 29},
- {0x8017, 29},
- {0xc028, 29},
- {0x8002, 30},
- {0x8009, 30},
- {0x8017, 30},
- {0xc028, 30},
- {0x8002, 31},
- {0x8009, 31},
- {0x8017, 31},
- {0xc028, 31},
- },
- /* 248 */
- {
- {0x8003, 28},
- {0x8006, 28},
- {0x800a, 28},
- {0x800f, 28},
- {0x8018, 28},
- {0x801f, 28},
- {0x8029, 28},
- {0xc038, 28},
- {0x8003, 29},
- {0x8006, 29},
- {0x800a, 29},
- {0x800f, 29},
- {0x8018, 29},
- {0x801f, 29},
- {0x8029, 29},
- {0xc038, 29},
- },
- /* 249 */
- {
- {0x8003, 30},
- {0x8006, 30},
- {0x800a, 30},
- {0x800f, 30},
- {0x8018, 30},
- {0x801f, 30},
- {0x8029, 30},
- {0xc038, 30},
- {0x8003, 31},
- {0x8006, 31},
- {0x800a, 31},
- {0x800f, 31},
- {0x8018, 31},
- {0x801f, 31},
- {0x8029, 31},
- {0xc038, 31},
- },
- /* 250 */
- {
- {0x8002, 127},
- {0x8009, 127},
- {0x8017, 127},
- {0xc028, 127},
- {0x8002, 220},
- {0x8009, 220},
- {0x8017, 220},
- {0xc028, 220},
- {0x8002, 249},
- {0x8009, 249},
- {0x8017, 249},
- {0xc028, 249},
- {0xc000, 10},
- {0xc000, 13},
- {0xc000, 22},
- {0x100, 0},
- },
- /* 251 */
- {
- {0x8003, 127},
- {0x8006, 127},
- {0x800a, 127},
- {0x800f, 127},
- {0x8018, 127},
- {0x801f, 127},
- {0x8029, 127},
- {0xc038, 127},
- {0x8003, 220},
- {0x8006, 220},
- {0x800a, 220},
- {0x800f, 220},
- {0x8018, 220},
- {0x801f, 220},
- {0x8029, 220},
- {0xc038, 220},
- },
- /* 252 */
- {
- {0x8003, 249},
- {0x8006, 249},
- {0x800a, 249},
- {0x800f, 249},
- {0x8018, 249},
- {0x801f, 249},
- {0x8029, 249},
- {0xc038, 249},
- {0x8001, 10},
- {0xc016, 10},
- {0x8001, 13},
- {0xc016, 13},
- {0x8001, 22},
- {0xc016, 22},
- {0x100, 0},
- {0x100, 0},
- },
- /* 253 */
- {
- {0x8002, 10},
- {0x8009, 10},
- {0x8017, 10},
- {0xc028, 10},
- {0x8002, 13},
- {0x8009, 13},
- {0x8017, 13},
- {0xc028, 13},
- {0x8002, 22},
- {0x8009, 22},
- {0x8017, 22},
- {0xc028, 22},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- },
- /* 254 */
- {
- {0x8003, 10},
- {0x8006, 10},
- {0x800a, 10},
- {0x800f, 10},
- {0x8018, 10},
- {0x801f, 10},
- {0x8029, 10},
- {0xc038, 10},
- {0x8003, 13},
- {0x8006, 13},
- {0x800a, 13},
- {0x800f, 13},
- {0x8018, 13},
- {0x801f, 13},
- {0x8029, 13},
- {0xc038, 13},
- },
- /* 255 */
- {
- {0x8003, 22},
- {0x8006, 22},
- {0x800a, 22},
- {0x800f, 22},
- {0x8018, 22},
- {0x801f, 22},
- {0x8029, 22},
- {0xc038, 22},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- },
- /* 256 */
- {
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- {0x100, 0},
- },
-};
diff --git a/deps/nghttp3/lib/nghttp3_range.c b/deps/nghttp3/lib/nghttp3_range.c
deleted file mode 100644
index 0ce71480d7..0000000000
--- a/deps/nghttp3/lib/nghttp3_range.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_range.h"
-#include "nghttp3_macro.h"
-
-void nghttp3_range_init(nghttp3_range *r, uint64_t begin, uint64_t end) {
- r->begin = begin;
- r->end = end;
-}
-
-nghttp3_range nghttp3_range_intersect(const nghttp3_range *a,
- const nghttp3_range *b) {
- nghttp3_range r = {0, 0};
- uint64_t begin = nghttp3_max(a->begin, b->begin);
- uint64_t end = nghttp3_min(a->end, b->end);
- if (begin < end) {
- nghttp3_range_init(&r, begin, end);
- }
- return r;
-}
-
-uint64_t nghttp3_range_len(const nghttp3_range *r) { return r->end - r->begin; }
-
-int nghttp3_range_eq(const nghttp3_range *a, const nghttp3_range *b) {
- return a->begin == b->begin && a->end == b->end;
-}
-
-void nghttp3_range_cut(nghttp3_range *left, nghttp3_range *right,
- const nghttp3_range *a, const nghttp3_range *b) {
- /* Assume that b is included in a */
- left->begin = a->begin;
- left->end = b->begin;
- right->begin = b->end;
- right->end = a->end;
-}
-
-int nghttp3_range_not_after(const nghttp3_range *a, const nghttp3_range *b) {
- return a->end <= b->end;
-}
diff --git a/deps/nghttp3/lib/nghttp3_range.h b/deps/nghttp3/lib/nghttp3_range.h
deleted file mode 100644
index e65dd14835..0000000000
--- a/deps/nghttp3/lib/nghttp3_range.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_RANGE_H
-#define NGHTTP3_RANGE_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-/*
- * nghttp3_range represents half-closed range [begin, end).
- */
-typedef struct {
- uint64_t begin;
- uint64_t end;
-} nghttp3_range;
-
-/*
- * nghttp3_range_init initializes |r| with the range [|begin|, |end|).
- */
-void nghttp3_range_init(nghttp3_range *r, uint64_t begin, uint64_t end);
-
-/*
- * nghttp3_range_intersect returns the intersection of |a| and |b|.
- * If they do not overlap, it returns empty range.
- */
-nghttp3_range nghttp3_range_intersect(const nghttp3_range *a,
- const nghttp3_range *b);
-
-/*
- * nghttp3_range_len returns the length of |r|.
- */
-uint64_t nghttp3_range_len(const nghttp3_range *r);
-
-/*
- * nghttp3_range_eq returns nonzero if |a| equals |b|, such that
- * a->begin == b->begin, and a->end == b->end hold.
- */
-int nghttp3_range_eq(const nghttp3_range *a, const nghttp3_range *b);
-
-/*
- * nghttp3_range_cut returns the left and right range after removing
- * |b| from |a|. This function assumes that |a| completely includes
- * |b|. In other words, a->begin <= b->begin and b->end <= a->end
- * hold.
- */
-void nghttp3_range_cut(nghttp3_range *left, nghttp3_range *right,
- const nghttp3_range *a, const nghttp3_range *b);
-
-/*
- * nghttp3_range_not_after returns nonzero if the right edge of |a|
- * does not go beyond of the right edge of |b|.
- */
-int nghttp3_range_not_after(const nghttp3_range *a, const nghttp3_range *b);
-
-#endif /* NGHTTP3_RANGE_H */
diff --git a/deps/nghttp3/lib/nghttp3_rcbuf.c b/deps/nghttp3/lib/nghttp3_rcbuf.c
deleted file mode 100644
index 1c31ecebf6..0000000000
--- a/deps/nghttp3/lib/nghttp3_rcbuf.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2016 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_rcbuf.h"
-
-#include <assert.h>
-
-#include "nghttp3_mem.h"
-#include "nghttp3_str.h"
-
-int nghttp3_rcbuf_new(nghttp3_rcbuf **rcbuf_ptr, size_t size,
- const nghttp3_mem *mem) {
- uint8_t *p;
-
- p = nghttp3_mem_malloc(mem, sizeof(nghttp3_rcbuf) + size);
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- *rcbuf_ptr = (void *)p;
-
- (*rcbuf_ptr)->mem_user_data = mem->mem_user_data;
- (*rcbuf_ptr)->free = mem->free;
- (*rcbuf_ptr)->base = p + sizeof(nghttp3_rcbuf);
- (*rcbuf_ptr)->len = size;
- (*rcbuf_ptr)->ref = 1;
-
- return 0;
-}
-
-int nghttp3_rcbuf_new2(nghttp3_rcbuf **rcbuf_ptr, const uint8_t *src,
- size_t srclen, const nghttp3_mem *mem) {
- int rv;
- uint8_t *p;
-
- rv = nghttp3_rcbuf_new(rcbuf_ptr, srclen + 1, mem);
- if (rv != 0) {
- return rv;
- }
-
- (*rcbuf_ptr)->len = srclen;
- p = (*rcbuf_ptr)->base;
-
- if (srclen) {
- p = nghttp3_cpymem(p, src, srclen);
- }
-
- *p = '\0';
-
- return 0;
-}
-
-/*
- * Frees |rcbuf| itself, regardless of its reference cout.
- */
-void nghttp3_rcbuf_del(nghttp3_rcbuf *rcbuf) {
- nghttp3_mem_free2(rcbuf->free, rcbuf, rcbuf->mem_user_data);
-}
-
-void nghttp3_rcbuf_incref(nghttp3_rcbuf *rcbuf) {
- if (rcbuf->ref == -1) {
- return;
- }
-
- ++rcbuf->ref;
-}
-
-void nghttp3_rcbuf_decref(nghttp3_rcbuf *rcbuf) {
- if (rcbuf == NULL || rcbuf->ref == -1) {
- return;
- }
-
- assert(rcbuf->ref > 0);
-
- if (--rcbuf->ref == 0) {
- nghttp3_rcbuf_del(rcbuf);
- }
-}
-
-nghttp3_vec nghttp3_rcbuf_get_buf(const nghttp3_rcbuf *rcbuf) {
- nghttp3_vec res = {rcbuf->base, rcbuf->len};
- return res;
-}
-
-int nghttp3_rcbuf_is_static(const nghttp3_rcbuf *rcbuf) {
- return rcbuf->ref == -1;
-}
diff --git a/deps/nghttp3/lib/nghttp3_rcbuf.h b/deps/nghttp3/lib/nghttp3_rcbuf.h
deleted file mode 100644
index feea804000..0000000000
--- a/deps/nghttp3/lib/nghttp3_rcbuf.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2016 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_RCBUF_H
-#define NGHTTP3_RCBUF_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-struct nghttp3_rcbuf {
- /* custom memory allocator belongs to the mem parameter when
- creating this object. */
- void *mem_user_data;
- nghttp3_free free;
- /* The pointer to the underlying buffer */
- uint8_t *base;
- /* Size of buffer pointed by |base|. */
- size_t len;
- /* Reference count */
- int32_t ref;
-};
-
-/*
- * Allocates nghttp3_rcbuf object with |size| as initial buffer size.
- * When the function succeeds, the reference count becomes 1.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM:
- * Out of memory.
- */
-int nghttp3_rcbuf_new(nghttp3_rcbuf **rcbuf_ptr, size_t size,
- const nghttp3_mem *mem);
-
-/*
- * Like nghttp3_rcbuf_new(), but initializes the buffer with |src| of
- * length |srclen|. This function allocates additional byte at the
- * end and puts '\0' into it, so that the resulting buffer could be
- * used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to
- * |srclen|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM:
- * Out of memory.
- */
-int nghttp3_rcbuf_new2(nghttp3_rcbuf **rcbuf_ptr, const uint8_t *src,
- size_t srclen, const nghttp3_mem *mem);
-
-/*
- * Frees |rcbuf| itself, regardless of its reference cout.
- */
-void nghttp3_rcbuf_del(nghttp3_rcbuf *rcbuf);
-
-#endif /* NGHTTP3_RCBUF_H */
diff --git a/deps/nghttp3/lib/nghttp3_ringbuf.c b/deps/nghttp3/lib/nghttp3_ringbuf.c
deleted file mode 100644
index 9ea91c81c8..0000000000
--- a/deps/nghttp3/lib/nghttp3_ringbuf.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_ringbuf.h"
-
-#include <assert.h>
-#include <string.h>
-#ifdef WIN32
-# include <intrin.h>
-#endif
-
-#include "nghttp3_macro.h"
-
-#if defined(_MSC_VER) && defined(_M_ARM64)
-unsigned int __popcnt(unsigned int x) {
- unsigned int c = 0;
- for (; x; ++c) {
- x &= x - 1;
- }
- return c;
-}
-#endif
-
-int nghttp3_ringbuf_init(nghttp3_ringbuf *rb, size_t nmemb, size_t size,
- const nghttp3_mem *mem) {
- if (nmemb) {
-#ifdef WIN32
- assert(1 == __popcnt((unsigned int)nmemb));
-#else
- assert(1 == __builtin_popcount((unsigned int)nmemb));
-#endif
-
- rb->buf = nghttp3_mem_malloc(mem, nmemb * size);
- if (rb->buf == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
- } else {
- rb->buf = NULL;
- }
-
- rb->mem = mem;
- rb->nmemb = nmemb;
- rb->size = size;
- rb->first = 0;
- rb->len = 0;
-
- return 0;
-}
-
-void nghttp3_ringbuf_free(nghttp3_ringbuf *rb) {
- if (rb == NULL) {
- return;
- }
-
- nghttp3_mem_free(rb->mem, rb->buf);
-}
-
-void *nghttp3_ringbuf_push_front(nghttp3_ringbuf *rb) {
- rb->first = (rb->first - 1) & (rb->nmemb - 1);
- rb->len = nghttp3_min(rb->nmemb, rb->len + 1);
-
- return (void *)&rb->buf[rb->first * rb->size];
-}
-
-void *nghttp3_ringbuf_push_back(nghttp3_ringbuf *rb) {
- size_t offset = (rb->first + rb->len) & (rb->nmemb - 1);
-
- if (rb->len == rb->nmemb) {
- rb->first = (rb->first + 1) & (rb->nmemb - 1);
- } else {
- ++rb->len;
- }
-
- return (void *)&rb->buf[offset * rb->size];
-}
-
-void nghttp3_ringbuf_pop_front(nghttp3_ringbuf *rb) {
- rb->first = (rb->first + 1) & (rb->nmemb - 1);
- --rb->len;
-}
-
-void nghttp3_ringbuf_pop_back(nghttp3_ringbuf *rb) {
- assert(rb->len);
- --rb->len;
-}
-
-void nghttp3_ringbuf_resize(nghttp3_ringbuf *rb, size_t len) {
- assert(len <= rb->nmemb);
- rb->len = len;
-}
-
-void *nghttp3_ringbuf_get(nghttp3_ringbuf *rb, size_t offset) {
- assert(offset < rb->len);
- offset = (rb->first + offset) & (rb->nmemb - 1);
- return &rb->buf[offset * rb->size];
-}
-
-int nghttp3_ringbuf_full(nghttp3_ringbuf *rb) { return rb->len == rb->nmemb; }
-
-int nghttp3_ringbuf_reserve(nghttp3_ringbuf *rb, size_t nmemb) {
- uint8_t *buf;
-
- if (rb->nmemb >= nmemb) {
- return 0;
- }
-
-#ifdef WIN32
- assert(1 == __popcnt((unsigned int)nmemb));
-#else
- assert(1 == __builtin_popcount((unsigned int)nmemb));
-#endif
-
- buf = nghttp3_mem_malloc(rb->mem, nmemb * rb->size);
- if (buf == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- if (rb->buf != NULL) {
- if (rb->first + rb->len <= rb->nmemb) {
- memcpy(buf, rb->buf + rb->first * rb->size, rb->len * rb->size);
- rb->first = 0;
- } else {
- memcpy(buf, rb->buf + rb->first * rb->size,
- (rb->nmemb - rb->first) * rb->size);
- memcpy(buf + (rb->nmemb - rb->first) * rb->size, rb->buf,
- (rb->len - (rb->nmemb - rb->first)) * rb->size);
- rb->first = 0;
- }
-
- nghttp3_mem_free(rb->mem, rb->buf);
- }
-
- rb->buf = buf;
- rb->nmemb = nmemb;
-
- return 0;
-}
diff --git a/deps/nghttp3/lib/nghttp3_ringbuf.h b/deps/nghttp3/lib/nghttp3_ringbuf.h
deleted file mode 100644
index 51194bd635..0000000000
--- a/deps/nghttp3/lib/nghttp3_ringbuf.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_RINGBUF_H
-#define NGHTTP3_RINGBUF_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_mem.h"
-
-typedef struct {
- /* buf points to the underlying buffer. */
- uint8_t *buf;
- const nghttp3_mem *mem;
- /* nmemb is the number of elements that can be stored in this ring
- buffer. */
- size_t nmemb;
- /* size is the size of each element. */
- size_t size;
- /* first is the offset to the first element. */
- size_t first;
- /* len is the number of elements actually stored. */
- size_t len;
-} nghttp3_ringbuf;
-
-/*
- * nghttp3_ringbuf_init initializes |rb|. |nmemb| is the number of
- * elements that can be stored in this buffer. |size| is the size of
- * each element. |size| must be power of 2.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP3_ERR_NOMEM
- * Out of memory.
- */
-int nghttp3_ringbuf_init(nghttp3_ringbuf *rb, size_t nmemb, size_t size,
- const nghttp3_mem *mem);
-
-/*
- * nghttp3_ringbuf_free frees resources allocated for |rb|. This
- * function does not free the memory pointed by |rb|.
- */
-void nghttp3_ringbuf_free(nghttp3_ringbuf *rb);
-
-/* nghttp3_ringbuf_push_front moves the offset to the first element in
- the buffer backward, and returns the pointer to the element.
- Caller can store data to the buffer pointed by the returned
- pointer. If this action exceeds the capacity of the ring buffer,
- the last element is silently overwritten, and rb->len remains
- unchanged. */
-void *nghttp3_ringbuf_push_front(nghttp3_ringbuf *rb);
-
-/* nghttp3_ringbuf_push_back moves the offset to the last element in
- the buffer forward, and returns the pointer to the element. Caller
- can store data to the buffer pointed by the returned pointer. If
- this action exceeds the capacity of the ring buffer, the first
- element is silently overwritten, and rb->len remains unchanged. */
-void *nghttp3_ringbuf_push_back(nghttp3_ringbuf *rb);
-
-/*
- * nghttp3_ringbuf_pop_front removes first element in |rb|.
- */
-void nghttp3_ringbuf_pop_front(nghttp3_ringbuf *rb);
-
-/*
- * nghttp3_ringbuf_pop_back removes the last element in |rb|.
- */
-void nghttp3_ringbuf_pop_back(nghttp3_ringbuf *rb);
-
-/* nghttp3_ringbuf_resize changes the number of elements stored. This
- does not change the capacity of the underlying buffer. */
-void nghttp3_ringbuf_resize(nghttp3_ringbuf *rb, size_t len);
-
-/* nghttp3_ringbuf_get returns the pointer to the element at
- |offset|. */
-void *nghttp3_ringbuf_get(nghttp3_ringbuf *rb, size_t offset);
-
-/* nghttp3_ringbuf_len returns the number of elements stored. */
-#define nghttp3_ringbuf_len(RB) ((RB)->len)
-
-/* nghttp3_ringbuf_full returns nonzero if |rb| is full. */
-int nghttp3_ringbuf_full(nghttp3_ringbuf *rb);
-
-int nghttp3_ringbuf_reserve(nghttp3_ringbuf *rb, size_t nmemb);
-
-#endif /* NGHTTP3_RINGBUF_H */
diff --git a/deps/nghttp3/lib/nghttp3_str.c b/deps/nghttp3/lib/nghttp3_str.c
deleted file mode 100644
index 3782aa72cd..0000000000
--- a/deps/nghttp3/lib/nghttp3_str.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_str.h"
-
-#include <string.h>
-#include <assert.h>
-
-uint8_t *nghttp3_cpymem(uint8_t *dest, const uint8_t *src, size_t n) {
- memcpy(dest, src, n);
- return dest + n;
-}
-
-/* Generated by gendowncasetbl.py */
-static const uint8_t DOWNCASE_TBL[] = {
- 0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
- 4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
- 8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
- 12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
- 16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
- 20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
- 24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
- 28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
- 32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
- 36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
- 40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
- 44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
- 48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
- 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
- 56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
- 60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
- 64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
- 100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
- 104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
- 108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
- 112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
- 116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
- 120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
- 92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
- 96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
- 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
- 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
- 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
- 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
- 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
- 120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
- 124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
- 128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
- 132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
- 136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
- 140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
- 144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
- 148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
- 152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
- 156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
- 160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
- 164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
- 168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
- 172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
- 176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
- 180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
- 184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
- 188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
- 192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
- 196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
- 200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
- 204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
- 208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
- 212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
- 216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
- 220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
- 224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
- 228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
- 232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
- 236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
- 240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
- 244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
- 248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
- 252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
-};
-
-void nghttp3_downcase(uint8_t *s, size_t len) {
- size_t i;
- for (i = 0; i < len; ++i) {
- s[i] = DOWNCASE_TBL[s[i]];
- }
-}
diff --git a/deps/nghttp3/lib/nghttp3_str.h b/deps/nghttp3/lib/nghttp3_str.h
deleted file mode 100644
index 19c1d2c71b..0000000000
--- a/deps/nghttp3/lib/nghttp3_str.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_STR_H
-#define NGHTTP3_STR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-uint8_t *nghttp3_cpymem(uint8_t *dest, const uint8_t *src, size_t n);
-
-void nghttp3_downcase(uint8_t *s, size_t len);
-
-#endif /* NGHTTP3_STR_H */
diff --git a/deps/nghttp3/lib/nghttp3_stream.c b/deps/nghttp3/lib/nghttp3_stream.c
deleted file mode 100644
index bf66d738d7..0000000000
--- a/deps/nghttp3/lib/nghttp3_stream.c
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_stream.h"
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "nghttp3_conv.h"
-#include "nghttp3_macro.h"
-#include "nghttp3_frame.h"
-#include "nghttp3_conn.h"
-#include "nghttp3_str.h"
-#include "nghttp3_http.h"
-
-/* NGHTTP3_STREAM_MAX_COPY_THRES is the maximum size of buffer which
- makes a copy to outq. */
-#define NGHTTP3_STREAM_MAX_COPY_THRES 128
-
-/* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */
-#define NGHTTP3_MIN_RBLEN 4
-
-int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
- uint64_t seq, const nghttp3_stream_callbacks *callbacks,
- const nghttp3_mem *mem) {
- int rv;
- nghttp3_stream *stream = nghttp3_mem_calloc(mem, 1, sizeof(nghttp3_stream));
- nghttp3_node_id nid;
-
- if (stream == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- nghttp3_tnode_init(
- &stream->node,
- nghttp3_node_id_init(&nid, NGHTTP3_NODE_ID_TYPE_STREAM, stream_id), seq,
- NGHTTP3_DEFAULT_URGENCY);
-
- rv = nghttp3_ringbuf_init(&stream->frq, 0, sizeof(nghttp3_frame_entry), mem);
- if (rv != 0) {
- goto frq_init_fail;
- }
-
- rv = nghttp3_ringbuf_init(&stream->chunks, 0, sizeof(nghttp3_buf), mem);
- if (rv != 0) {
- goto chunks_init_fail;
- }
-
- rv = nghttp3_ringbuf_init(&stream->outq, 0, sizeof(nghttp3_typed_buf), mem);
- if (rv != 0) {
- goto outq_init_fail;
- }
-
- rv = nghttp3_ringbuf_init(&stream->inq, 0, sizeof(nghttp3_buf), mem);
- if (rv != 0) {
- goto inq_init_fail;
- }
-
- nghttp3_qpack_stream_context_init(&stream->qpack_sctx, stream_id, mem);
-
- stream->me.key = (key_type)stream_id;
- stream->qpack_blocked_pe.index = NGHTTP3_PQ_BAD_INDEX;
- stream->mem = mem;
- stream->rx.http.status_code = -1;
- stream->rx.http.content_length = -1;
- stream->rx.http.pri = NGHTTP3_DEFAULT_URGENCY;
- stream->error_code = NGHTTP3_H3_NO_ERROR;
-
- if (callbacks) {
- stream->callbacks = *callbacks;
- }
-
- *pstream = stream;
-
- return 0;
-
-inq_init_fail:
- nghttp3_ringbuf_free(&stream->outq);
-outq_init_fail:
- nghttp3_ringbuf_free(&stream->chunks);
-chunks_init_fail:
- nghttp3_ringbuf_free(&stream->frq);
-frq_init_fail:
- nghttp3_mem_free(mem, stream);
-
- return rv;
-}
-
-static void delete_outq(nghttp3_ringbuf *outq, const nghttp3_mem *mem) {
- nghttp3_typed_buf *tbuf;
- size_t i, len = nghttp3_ringbuf_len(outq);
-
- for (i = 0; i < len; ++i) {
- tbuf = nghttp3_ringbuf_get(outq, i);
- if (tbuf->type == NGHTTP3_BUF_TYPE_PRIVATE) {
- nghttp3_buf_free(&tbuf->buf, mem);
- }
- }
-
- nghttp3_ringbuf_free(outq);
-}
-
-static void delete_chunks(nghttp3_ringbuf *chunks, const nghttp3_mem *mem) {
- nghttp3_buf *buf;
- size_t i, len = nghttp3_ringbuf_len(chunks);
-
- for (i = 0; i < len; ++i) {
- buf = nghttp3_ringbuf_get(chunks, i);
- nghttp3_buf_free(buf, mem);
- }
-
- nghttp3_ringbuf_free(chunks);
-}
-
-static void delete_frq(nghttp3_ringbuf *frq, const nghttp3_mem *mem) {
- nghttp3_frame_entry *frent;
- size_t i, len = nghttp3_ringbuf_len(frq);
-
- for (i = 0; i < len; ++i) {
- frent = nghttp3_ringbuf_get(frq, i);
- switch (frent->fr.hd.type) {
- case NGHTTP3_FRAME_HEADERS:
- nghttp3_frame_headers_free(&frent->fr.headers, mem);
- break;
- case NGHTTP3_FRAME_PUSH_PROMISE:
- nghttp3_frame_push_promise_free(&frent->fr.push_promise, mem);
- break;
- default:
- break;
- }
- }
-
- nghttp3_ringbuf_free(frq);
-}
-
-void nghttp3_stream_del(nghttp3_stream *stream) {
- if (stream == NULL) {
- return;
- }
-
- nghttp3_qpack_stream_context_free(&stream->qpack_sctx);
- delete_chunks(&stream->inq, stream->mem);
- delete_outq(&stream->outq, stream->mem);
- delete_chunks(&stream->chunks, stream->mem);
- delete_frq(&stream->frq, stream->mem);
- nghttp3_tnode_free(&stream->node);
-
- nghttp3_mem_free(stream->mem, stream);
-}
-
-void nghttp3_varint_read_state_reset(nghttp3_varint_read_state *rvint) {
- memset(rvint, 0, sizeof(*rvint));
-}
-
-void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate) {
- memset(rstate, 0, sizeof(*rstate));
-}
-
-nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
- const uint8_t *src, size_t srclen, int fin) {
- size_t nread = 0;
- size_t n;
- size_t i;
-
- assert(srclen > 0);
-
- if (rvint->left == 0) {
- assert(rvint->acc == 0);
-
- rvint->left = nghttp3_get_varint_len(src);
- if (rvint->left <= srclen) {
- rvint->acc = nghttp3_get_varint(&nread, src);
- rvint->left = 0;
- return (nghttp3_ssize)nread;
- }
-
- if (fin) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- rvint->acc = nghttp3_get_varint_fb(src);
- nread = 1;
- ++src;
- --srclen;
- --rvint->left;
- }
-
- n = nghttp3_min(rvint->left, srclen);
-
- for (i = 0; i < n; ++i) {
- rvint->acc = (rvint->acc << 8) + src[i];
- }
-
- rvint->left -= n;
- nread += n;
-
- if (fin && rvint->left) {
- return NGHTTP3_ERR_INVALID_ARGUMENT;
- }
-
- return (nghttp3_ssize)nread;
-}
-
-int nghttp3_stream_frq_add(nghttp3_stream *stream,
- const nghttp3_frame_entry *frent) {
- nghttp3_ringbuf *frq = &stream->frq;
- nghttp3_frame_entry *dest;
- int rv;
-
- if (nghttp3_ringbuf_full(frq)) {
- size_t nlen = nghttp3_max(NGHTTP3_MIN_RBLEN, nghttp3_ringbuf_len(frq) * 2);
- rv = nghttp3_ringbuf_reserve(frq, nlen);
- if (rv != 0) {
- return rv;
- }
- }
-
- dest = nghttp3_ringbuf_push_back(frq);
- *dest = *frent;
-
- return 0;
-}
-
-int nghttp3_stream_fill_outq(nghttp3_stream *stream) {
- nghttp3_ringbuf *frq = &stream->frq;
- nghttp3_frame_entry *frent;
- int data_eof;
- int rv;
-
- for (; nghttp3_ringbuf_len(frq) && !nghttp3_stream_outq_is_full(stream) &&
- stream->unsent_bytes < NGHTTP3_MIN_UNSENT_BYTES;) {
- frent = nghttp3_ringbuf_get(frq, 0);
-
- switch (frent->fr.hd.type) {
- case NGHTTP3_FRAME_SETTINGS:
- rv = nghttp3_stream_write_settings(stream, frent);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGHTTP3_FRAME_HEADERS:
- rv = nghttp3_stream_write_headers(stream, frent);
- if (rv != 0) {
- return rv;
- }
- nghttp3_frame_headers_free(&frent->fr.headers, stream->mem);
- break;
- case NGHTTP3_FRAME_PUSH_PROMISE:
- rv = nghttp3_stream_write_push_promise(stream, frent);
- if (rv != 0) {
- return rv;
- }
- nghttp3_frame_push_promise_free(&frent->fr.push_promise, stream->mem);
- break;
- case NGHTTP3_FRAME_CANCEL_PUSH:
- rv = nghttp3_stream_write_cancel_push(stream, frent);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGHTTP3_FRAME_DATA:
- rv = nghttp3_stream_write_data(stream, &data_eof, frent);
- if (rv != 0) {
- return rv;
- }
- if (stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED) {
- return 0;
- }
- if (!data_eof) {
- return 0;
- }
- break;
- case NGHTTP3_FRAME_MAX_PUSH_ID:
- rv = nghttp3_stream_write_max_push_id(stream, frent);
- if (rv != 0) {
- return rv;
- }
- break;
- default:
- /* TODO Not implemented */
- break;
- }
-
- nghttp3_ringbuf_pop_front(frq);
- }
-
- return 0;
-}
-
-static void typed_buf_shared_init(nghttp3_typed_buf *tbuf,
- const nghttp3_buf *chunk) {
- nghttp3_typed_buf_init(tbuf, chunk, NGHTTP3_BUF_TYPE_SHARED);
- tbuf->buf.pos = tbuf->buf.last;
-}
-
-int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
- size_t len = nghttp3_put_varint_len((int64_t)stream->type);
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
- int rv;
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_write_stream_type_push_id(nghttp3_stream *stream) {
- size_t len;
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
- int rv;
- nghttp3_push_promise *pp = stream->pp;
-
- assert(stream->type == NGHTTP3_STREAM_TYPE_PUSH);
- assert(pp);
-
- len = nghttp3_put_varint_len((int64_t)stream->type) +
- nghttp3_put_varint_len(pp->node.nid.id);
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
- chunk->last = nghttp3_put_varint(chunk->last, pp->node.nid.id);
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_write_settings(nghttp3_stream *stream,
- nghttp3_frame_entry *frent) {
- size_t len;
- int rv;
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
- struct {
- nghttp3_frame_settings settings;
- nghttp3_settings_entry iv[15];
- } fr;
- nghttp3_settings_entry *iv;
- nghttp3_conn_settings *local_settings = frent->aux.settings.local_settings;
-
- fr.settings.hd.type = NGHTTP3_FRAME_SETTINGS;
- fr.settings.niv = 3;
- iv = &fr.settings.iv[0];
-
- iv[0].id = NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE;
- iv[0].value = local_settings->max_field_section_size;
- iv[1].id = NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY;
- iv[1].value = local_settings->qpack_max_table_capacity;
- iv[2].id = NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS;
- iv[2].value = local_settings->qpack_blocked_streams;
-
- len = nghttp3_frame_write_settings_len(&fr.settings.hd.length, &fr.settings);
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings);
-
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_write_cancel_push(nghttp3_stream *stream,
- nghttp3_frame_entry *frent) {
- nghttp3_frame_cancel_push *fr = &frent->fr.cancel_push;
- size_t len;
- int rv;
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
-
- len = nghttp3_frame_write_cancel_push_len(&fr->hd.length, fr);
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_frame_write_cancel_push(chunk->last, fr);
-
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_write_max_push_id(nghttp3_stream *stream,
- nghttp3_frame_entry *frent) {
- nghttp3_frame_max_push_id *fr = &frent->fr.max_push_id;
- nghttp3_conn *conn = stream->conn;
- size_t len;
- int rv;
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
-
- assert(conn);
- assert(conn->flags & NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED);
-
- fr->push_id = (int64_t)conn->remote.uni.unsent_max_pushes - 1;
- conn->remote.uni.max_pushes = conn->remote.uni.unsent_max_pushes;
- conn->flags &= (uint16_t)~NGHTTP3_CONN_FLAG_MAX_PUSH_ID_QUEUED;
-
- len = nghttp3_frame_write_max_push_id_len(&fr->hd.length, fr);
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_frame_write_max_push_id(chunk->last, fr);
-
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_write_headers(nghttp3_stream *stream,
- nghttp3_frame_entry *frent) {
- nghttp3_frame_headers *fr = &frent->fr.headers;
- nghttp3_conn *conn = stream->conn;
-
- assert(conn);
-
- return nghttp3_stream_write_header_block(
- stream, &conn->qenc, conn->tx.qenc, &conn->tx.qpack.rbuf,
- &conn->tx.qpack.ebuf, NGHTTP3_FRAME_HEADERS, 0, fr->nva, fr->nvlen);
-}
-
-int nghttp3_stream_write_push_promise(nghttp3_stream *stream,
- nghttp3_frame_entry *frent) {
- nghttp3_frame_push_promise *fr = &frent->fr.push_promise;
- nghttp3_conn *conn = stream->conn;
-
- assert(conn);
-
- return nghttp3_stream_write_header_block(
- stream, &conn->qenc, conn->tx.qenc, &conn->tx.qpack.rbuf,
- &conn->tx.qpack.ebuf, NGHTTP3_FRAME_PUSH_PROMISE, fr->push_id, fr->nva,
- fr->nvlen);
-}
-
-int nghttp3_stream_write_header_block(nghttp3_stream *stream,
- nghttp3_qpack_encoder *qenc,
- nghttp3_stream *qenc_stream,
- nghttp3_buf *rbuf, nghttp3_buf *ebuf,
- int64_t frame_type, int64_t push_id,
- const nghttp3_nv *nva, size_t nvlen) {
- nghttp3_buf pbuf;
- int rv;
- size_t len;
- nghttp3_buf *chunk;
- nghttp3_typed_buf tbuf;
- nghttp3_frame_hd hd;
- size_t push_idlen = 0;
- uint8_t raw_pbuf[16];
- size_t pbuflen, rbuflen, ebuflen;
-
- nghttp3_buf_wrap_init(&pbuf, raw_pbuf, sizeof(raw_pbuf));
-
- rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf,
- stream->node.nid.id, nva, nvlen);
- if (rv != 0) {
- goto fail;
- }
-
- pbuflen = nghttp3_buf_len(&pbuf);
- rbuflen = nghttp3_buf_len(rbuf);
- ebuflen = nghttp3_buf_len(ebuf);
-
- if (frame_type == NGHTTP3_FRAME_PUSH_PROMISE) {
- push_idlen = nghttp3_put_varint_len(push_id);
- }
-
- hd.type = frame_type;
- hd.length = (int64_t)(pbuflen + rbuflen + push_idlen);
-
- len = nghttp3_frame_write_hd_len(&hd) + push_idlen + pbuflen;
-
- if (rbuflen <= NGHTTP3_STREAM_MAX_COPY_THRES) {
- len += rbuflen;
- }
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- goto fail;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
-
- if (push_idlen) {
- chunk->last = nghttp3_put_varint(chunk->last, push_id);
- }
-
- chunk->last = nghttp3_cpymem(chunk->last, pbuf.pos, pbuflen);
- nghttp3_buf_init(&pbuf);
-
- if (rbuflen > NGHTTP3_STREAM_MAX_COPY_THRES) {
- tbuf.buf.last = chunk->last;
-
- rv = nghttp3_stream_outq_add(stream, &tbuf);
- if (rv != 0) {
- goto fail;
- }
-
- nghttp3_typed_buf_init(&tbuf, rbuf, NGHTTP3_BUF_TYPE_PRIVATE);
- rv = nghttp3_stream_outq_add(stream, &tbuf);
- if (rv != 0) {
- goto fail;
- }
- nghttp3_buf_init(rbuf);
- } else if (rbuflen) {
- chunk->last = nghttp3_cpymem(chunk->last, rbuf->pos, rbuflen);
- tbuf.buf.last = chunk->last;
-
- rv = nghttp3_stream_outq_add(stream, &tbuf);
- if (rv != 0) {
- goto fail;
- }
- nghttp3_buf_reset(rbuf);
- }
-
- if (ebuflen > NGHTTP3_STREAM_MAX_COPY_THRES) {
- assert(qenc_stream);
-
- nghttp3_typed_buf_init(&tbuf, ebuf, NGHTTP3_BUF_TYPE_PRIVATE);
- rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
- if (rv != 0) {
- return rv;
- }
- nghttp3_buf_init(ebuf);
- } else if (ebuflen) {
- assert(qenc_stream);
-
- rv = nghttp3_stream_ensure_chunk(qenc_stream, ebuflen);
- if (rv != 0) {
- goto fail;
- }
-
- chunk = nghttp3_stream_get_chunk(qenc_stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_cpymem(chunk->last, ebuf->pos, ebuflen);
- tbuf.buf.last = chunk->last;
-
- rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
- if (rv != 0) {
- goto fail;
- }
- nghttp3_buf_reset(ebuf);
- }
-
- assert(0 == nghttp3_buf_len(&pbuf));
- assert(0 == nghttp3_buf_len(rbuf));
- assert(0 == nghttp3_buf_len(ebuf));
-
- return 0;
-
-fail:
-
- return rv;
-}
-
-int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
- nghttp3_frame_entry *frent) {
- int rv;
- size_t len;
- nghttp3_typed_buf tbuf;
- nghttp3_buf buf;
- nghttp3_buf *chunk;
- nghttp3_read_data_callback read_data = frent->aux.data.dr.read_data;
- nghttp3_conn *conn = stream->conn;
- size_t datalen;
- uint32_t flags = 0;
- nghttp3_frame_hd hd;
- nghttp3_vec vec[8];
- nghttp3_vec *v;
- nghttp3_ssize sveccnt;
- size_t i;
-
- assert(!(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED));
- assert(read_data);
- assert(conn);
-
- *peof = 0;
-
- sveccnt = read_data(conn, stream->node.nid.id, vec, nghttp3_arraylen(vec),
- &flags, conn->user_data, stream->user_data);
- if (sveccnt < 0) {
- if (sveccnt == NGHTTP3_ERR_WOULDBLOCK) {
- stream->flags |= NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED;
- return 0;
- }
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
-
- datalen = nghttp3_vec_len(vec, (size_t)sveccnt);
-
- assert(datalen || flags & NGHTTP3_DATA_FLAG_EOF);
-
- if (flags & NGHTTP3_DATA_FLAG_EOF) {
- *peof = 1;
- if (!(flags & NGHTTP3_DATA_FLAG_NO_END_STREAM)) {
- stream->flags |= NGHTTP3_STREAM_FLAG_WRITE_END_STREAM;
- if (datalen == 0) {
- if (nghttp3_stream_outq_write_done(stream)) {
- /* If this is the last data and its is 0 length, we don't
- need send DATA frame. We rely on the non-emptiness of
- outq to schedule stream, so add empty tbuf to outq to
- just send fin. */
- nghttp3_buf_init(&buf);
- nghttp3_typed_buf_init(&tbuf, &buf, NGHTTP3_BUF_TYPE_PRIVATE);
- return nghttp3_stream_outq_add(stream, &tbuf);
- }
- return 0;
- }
- }
-
- if (datalen == 0) {
- /* We are going to send more frames, but no DATA frame this
- time. */
- return 0;
- }
- }
-
- hd.type = NGHTTP3_FRAME_DATA;
- hd.length = (int64_t)datalen;
-
- len = nghttp3_frame_write_hd_len(&hd);
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
-
- tbuf.buf.last = chunk->last;
-
- rv = nghttp3_stream_outq_add(stream, &tbuf);
- if (rv != 0) {
- return rv;
- }
-
- if (datalen) {
- for (i = 0; i < (size_t)sveccnt; ++i) {
- v = &vec[i];
- if (v->len == 0) {
- continue;
- }
- nghttp3_buf_wrap_init(&buf, v->base, v->len);
- buf.last = buf.end;
- nghttp3_typed_buf_init(&tbuf, &buf, NGHTTP3_BUF_TYPE_ALIEN);
- rv = nghttp3_stream_outq_add(stream, &tbuf);
- if (rv != 0) {
- return rv;
- }
- }
- }
-
- return 0;
-}
-
-int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream) {
- nghttp3_qpack_decoder *qdec;
- nghttp3_buf *chunk;
- int rv;
- nghttp3_typed_buf tbuf;
- size_t len;
-
- assert(stream->conn);
- assert(stream->conn->tx.qdec == stream);
-
- qdec = &stream->conn->qdec;
-
- assert(qdec);
-
- len = nghttp3_qpack_decoder_get_decoder_streamlen(qdec);
- if (len == 0) {
- return 0;
- }
-
- rv = nghttp3_stream_ensure_chunk(stream, len);
- if (rv != 0) {
- return rv;
- }
-
- chunk = nghttp3_stream_get_chunk(stream);
- typed_buf_shared_init(&tbuf, chunk);
-
- nghttp3_qpack_decoder_write_decoder(qdec, chunk);
-
- tbuf.buf.last = chunk->last;
-
- return nghttp3_stream_outq_add(stream, &tbuf);
-}
-
-int nghttp3_stream_outq_is_full(nghttp3_stream *stream) {
- /* TODO Verify that the limit is reasonable. */
- return nghttp3_ringbuf_len(&stream->outq) >= 1024;
-}
-
-int nghttp3_stream_outq_add(nghttp3_stream *stream,
- const nghttp3_typed_buf *tbuf) {
- nghttp3_ringbuf *outq = &stream->outq;
- int rv;
- nghttp3_typed_buf *dest;
- size_t len = nghttp3_ringbuf_len(outq);
-
- stream->unsent_bytes += nghttp3_buf_len(&tbuf->buf);
-
- if (len) {
- dest = nghttp3_ringbuf_get(outq, len - 1);
- if (dest->type == tbuf->type && dest->type == NGHTTP3_BUF_TYPE_SHARED &&
- dest->buf.begin == tbuf->buf.begin && dest->buf.last == tbuf->buf.pos) {
- /* If we have already written last entry, adjust outq_idx and
- offset so that this entry is eligible to send. */
- if (len == stream->outq_idx) {
- --stream->outq_idx;
- stream->outq_offset = nghttp3_buf_len(&dest->buf);
- }
-
- dest->buf.last = tbuf->buf.last;
- /* TODO Is this required? */
- dest->buf.end = tbuf->buf.end;
-
- return 0;
- }
- }
-
- if (nghttp3_ringbuf_full(outq)) {
- size_t nlen = nghttp3_max(NGHTTP3_MIN_RBLEN, len * 2);
- rv = nghttp3_ringbuf_reserve(outq, nlen);
- if (rv != 0) {
- return rv;
- }
- }
-
- dest = nghttp3_ringbuf_push_back(outq);
- *dest = *tbuf;
-
- return 0;
-}
-
-int nghttp3_stream_ensure_chunk(nghttp3_stream *stream, size_t need) {
- nghttp3_ringbuf *chunks = &stream->chunks;
- nghttp3_buf *chunk;
- size_t len = nghttp3_ringbuf_len(chunks);
- uint8_t *p;
- int rv;
- size_t n = NGHTTP3_STREAM_MIN_CHUNK_SIZE;
-
- if (len) {
- chunk = nghttp3_ringbuf_get(chunks, len - 1);
- if (nghttp3_buf_left(chunk) >= need) {
- return 0;
- }
- }
-
- for (; n < need; n *= 2)
- ;
-
- p = nghttp3_mem_malloc(stream->mem, n);
- if (p == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- if (nghttp3_ringbuf_full(chunks)) {
- size_t nlen = nghttp3_max(NGHTTP3_MIN_RBLEN, len * 2);
- rv = nghttp3_ringbuf_reserve(chunks, nlen);
- if (rv != 0) {
- return rv;
- }
- }
-
- chunk = nghttp3_ringbuf_push_back(chunks);
- nghttp3_buf_wrap_init(chunk, p, n);
-
- return 0;
-}
-
-nghttp3_buf *nghttp3_stream_get_chunk(nghttp3_stream *stream) {
- nghttp3_ringbuf *chunks = &stream->chunks;
- size_t len = nghttp3_ringbuf_len(chunks);
-
- assert(len);
-
- return nghttp3_ringbuf_get(chunks, len - 1);
-}
-
-int nghttp3_stream_is_blocked(nghttp3_stream *stream) {
- return (stream->flags & NGHTTP3_STREAM_FLAG_FC_BLOCKED) ||
- (stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED);
-}
-
-int nghttp3_stream_require_schedule(nghttp3_stream *stream) {
- return (!nghttp3_stream_outq_write_done(stream) &&
- !(stream->flags & NGHTTP3_STREAM_FLAG_FC_BLOCKED)) ||
- (nghttp3_ringbuf_len(&stream->frq) &&
- !(stream->flags & NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED));
-}
-
-nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin,
- nghttp3_vec *vec, size_t veccnt) {
- nghttp3_ringbuf *outq = &stream->outq;
- size_t len = nghttp3_ringbuf_len(outq);
- size_t i;
- size_t offset = stream->outq_offset;
- size_t buflen;
- nghttp3_vec *vbegin = vec, *vend = vec + veccnt;
- nghttp3_typed_buf *tbuf;
-
- assert(veccnt > 0);
-
- for (i = stream->outq_idx; i < len; ++i) {
- tbuf = nghttp3_ringbuf_get(outq, i);
- buflen = nghttp3_buf_len(&tbuf->buf);
- if (offset >= buflen) {
- offset -= buflen;
- continue;
- }
-
- vec->base = tbuf->buf.pos + offset;
- vec->len = buflen - offset;
- ++vec;
- ++i;
- break;
- }
-
- for (; i < len && vec != vend; ++i, ++vec) {
- tbuf = nghttp3_ringbuf_get(outq, i);
- vec->base = tbuf->buf.pos;
- vec->len = nghttp3_buf_len(&tbuf->buf);
- }
-
- /* TODO Rework this if we have finished implementing HTTP
- messaging */
- *pfin = nghttp3_ringbuf_len(&stream->frq) == 0 && i == len &&
- (stream->flags & NGHTTP3_STREAM_FLAG_WRITE_END_STREAM);
-
- return vec - vbegin;
-}
-
-int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) {
- nghttp3_ringbuf *outq = &stream->outq;
- size_t i;
- size_t len = nghttp3_ringbuf_len(outq);
- size_t offset = stream->outq_offset + n;
- size_t buflen;
- nghttp3_typed_buf *tbuf;
-
- for (i = stream->outq_idx; i < len; ++i) {
- tbuf = nghttp3_ringbuf_get(outq, i);
- buflen = nghttp3_buf_len(&tbuf->buf);
- if (offset >= buflen) {
- offset -= buflen;
- continue;
- }
-
- break;
- }
-
- assert(i < len || offset == 0);
-
- stream->unsent_bytes -= n;
- stream->outq_idx = i;
- stream->outq_offset = offset;
-
- return 0;
-}
-
-int nghttp3_stream_outq_write_done(nghttp3_stream *stream) {
- nghttp3_ringbuf *outq = &stream->outq;
- size_t len = nghttp3_ringbuf_len(outq);
-
- return len == 0 || stream->outq_idx >= len;
-}
-
-static int stream_pop_outq_entry(nghttp3_stream *stream,
- nghttp3_typed_buf *tbuf) {
- nghttp3_ringbuf *chunks = &stream->chunks;
- nghttp3_buf *chunk;
-
- switch (tbuf->type) {
- case NGHTTP3_BUF_TYPE_PRIVATE:
- nghttp3_buf_free(&tbuf->buf, stream->mem);
- break;
- case NGHTTP3_BUF_TYPE_ALIEN:
- break;
- default:
- assert(nghttp3_ringbuf_len(chunks));
-
- chunk = nghttp3_ringbuf_get(chunks, 0);
-
- assert(chunk->begin == tbuf->buf.begin);
- assert(chunk->end == tbuf->buf.end);
-
- if (chunk->last == tbuf->buf.last) {
- nghttp3_buf_free(chunk, stream->mem);
- nghttp3_ringbuf_pop_front(chunks);
- }
- };
-
- nghttp3_ringbuf_pop_front(&stream->outq);
-
- return 0;
-}
-
-int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n) {
- nghttp3_ringbuf *outq = &stream->outq;
- uint64_t offset = stream->ack_offset + n;
- size_t buflen;
- size_t npopped = 0;
- size_t nack;
- nghttp3_typed_buf *tbuf;
- int rv;
-
- for (; nghttp3_ringbuf_len(outq);) {
- tbuf = nghttp3_ringbuf_get(outq, 0);
- buflen = nghttp3_buf_len(&tbuf->buf);
-
- if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN) {
- nack = (size_t)nghttp3_min(offset, (uint64_t)buflen) - stream->ack_done;
- if (stream->callbacks.acked_data) {
- rv = stream->callbacks.acked_data(stream, stream->node.nid.id, nack,
- stream->user_data);
- if (rv != 0) {
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- }
- }
- stream->ack_done += nack;
- }
-
- if (offset >= buflen) {
- rv = stream_pop_outq_entry(stream, tbuf);
- if (rv != 0) {
- return rv;
- }
-
- offset -= buflen;
- ++npopped;
- stream->ack_done = 0;
-
- if (stream->outq_idx + 1 == npopped) {
- stream->outq_offset = 0;
- break;
- }
-
- continue;
- }
-
- break;
- }
-
- assert(stream->outq_idx + 1 >= npopped);
- if (stream->outq_idx >= npopped) {
- stream->outq_idx -= npopped;
- } else {
- stream->outq_idx = 0;
- }
-
- stream->ack_offset = offset;
-
- return 0;
-}
-
-int nghttp3_stream_buffer_data(nghttp3_stream *stream, const uint8_t *data,
- size_t datalen) {
- nghttp3_ringbuf *inq = &stream->inq;
- size_t len = nghttp3_ringbuf_len(inq);
- nghttp3_buf *buf;
- size_t nwrite;
- uint8_t *rawbuf;
- size_t bufleft;
- int rv;
-
- if (len) {
- buf = nghttp3_ringbuf_get(inq, len - 1);
- bufleft = nghttp3_buf_left(buf);
- nwrite = nghttp3_min(datalen, bufleft);
- buf->last = nghttp3_cpymem(buf->last, data, nwrite);
- data += nwrite;
- datalen -= nwrite;
- }
-
- for (; datalen;) {
- if (nghttp3_ringbuf_full(inq)) {
- size_t nlen =
- nghttp3_max(NGHTTP3_MIN_RBLEN, nghttp3_ringbuf_len(inq) * 2);
- rv = nghttp3_ringbuf_reserve(inq, nlen);
- if (rv != 0) {
- return rv;
- }
- }
-
- rawbuf = nghttp3_mem_malloc(stream->mem, 16384);
- if (rawbuf == NULL) {
- return NGHTTP3_ERR_NOMEM;
- }
-
- buf = nghttp3_ringbuf_push_back(inq);
- nghttp3_buf_wrap_init(buf, rawbuf, 16384);
- bufleft = nghttp3_buf_left(buf);
- nwrite = nghttp3_min(datalen, bufleft);
- buf->last = nghttp3_cpymem(buf->last, data, nwrite);
- data += nwrite;
- datalen -= nwrite;
- }
-
- return 0;
-}
-
-size_t nghttp3_stream_get_buffered_datalen(nghttp3_stream *stream) {
- nghttp3_ringbuf *inq = &stream->inq;
- size_t len = nghttp3_ringbuf_len(inq);
- size_t i, n = 0;
- nghttp3_buf *buf;
-
- for (i = 0; i < len; ++i) {
- buf = nghttp3_ringbuf_get(inq, i);
- n += nghttp3_buf_len(buf);
- }
-
- return n;
-}
-
-int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
- nghttp3_stream_http_event event) {
- int rv;
-
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_NONE:
- return NGHTTP3_ERR_H3_INTERNAL_ERROR;
- case NGHTTP3_HTTP_STATE_REQ_INITIAL:
- switch (event) {
- case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
- return 0;
- default:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_END;
- return 0;
- case NGHTTP3_HTTP_STATE_REQ_HEADERS_END:
- switch (event) {
- case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
- /* TODO Better to check status code */
- if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- rv = nghttp3_http_on_remote_end_stream(stream);
- if (rv != 0) {
- return rv;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_MSG_END:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
- return 0;
- default:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- case NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_END;
- return 0;
- case NGHTTP3_HTTP_STATE_REQ_DATA_END:
- switch (event) {
- case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
- /* TODO Better to check status code */
- if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- rv = nghttp3_http_on_remote_end_stream(stream);
- if (rv != 0) {
- return rv;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_MSG_END:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
- return 0;
- default:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_END;
- return 0;
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_END:
- if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
- /* TODO Should ignore unexpected frame in this state as per
- spec. */
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
- return 0;
- case NGHTTP3_HTTP_STATE_REQ_END:
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- case NGHTTP3_HTTP_STATE_RESP_INITIAL:
- if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
- return 0;
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_END;
- return 0;
- case NGHTTP3_HTTP_STATE_RESP_HEADERS_END:
- switch (event) {
- case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
- if (stream->rx.http.status_code == -1) {
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
- return 0;
- }
- if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) &&
- stream->rx.http.status_code / 100 == 2) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- rv = nghttp3_http_on_remote_end_stream(stream);
- if (rv != 0) {
- return rv;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
- if (stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_MSG_END:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
- return 0;
- default:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- case NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_END;
- return 0;
- case NGHTTP3_HTTP_STATE_RESP_DATA_END:
- switch (event) {
- case NGHTTP3_HTTP_EVENT_DATA_BEGIN:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
- if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) &&
- stream->rx.http.status_code / 100 == 2) {
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- rv = nghttp3_http_on_remote_end_stream(stream);
- if (rv != 0) {
- return rv;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN;
- return 0;
- case NGHTTP3_HTTP_EVENT_MSG_END:
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
- return 0;
- default:
- return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
- }
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_END;
- return 0;
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_END:
- if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
- stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
- return 0;
- case NGHTTP3_HTTP_STATE_RESP_END:
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- default:
- assert(0);
- }
-}
-
-int nghttp3_stream_empty_headers_allowed(nghttp3_stream *stream) {
- switch (stream->rx.hstate) {
- case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
- case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
- return 0;
- default:
- return NGHTTP3_ERR_H3_GENERAL_PROTOCOL_ERROR;
- }
-}
-
-int nghttp3_stream_bidi_or_push(nghttp3_stream *stream) {
- return (!nghttp3_stream_uni(stream->node.nid.id) ||
- stream->type == NGHTTP3_STREAM_TYPE_PUSH);
-}
-
-int nghttp3_stream_uni(int64_t stream_id) { return (stream_id & 0x2) != 0; }
-
-int nghttp3_client_stream_bidi(int64_t stream_id) {
- return (stream_id & 0x3) == 0;
-}
-
-int nghttp3_client_stream_uni(int64_t stream_id) {
- return (stream_id & 0x3) == 0x2;
-}
-
-int nghttp3_server_stream_uni(int64_t stream_id) {
- return (stream_id & 0x3) == 0x3;
-}
diff --git a/deps/nghttp3/lib/nghttp3_stream.h b/deps/nghttp3/lib/nghttp3_stream.h
deleted file mode 100644
index 1dcc421123..0000000000
--- a/deps/nghttp3/lib/nghttp3_stream.h
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_STREAM_H
-#define NGHTTP3_STREAM_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_map.h"
-#include "nghttp3_tnode.h"
-#include "nghttp3_ringbuf.h"
-#include "nghttp3_buf.h"
-#include "nghttp3_frame.h"
-#include "nghttp3_qpack.h"
-
-#define NGHTTP3_STREAM_MIN_CHUNK_SIZE 256
-
-/* NGHTTP3_MIN_UNSENT_BYTES is the minimum unsent bytes which is large
- enough to fill outgoing single QUIC packet. */
-#define NGHTTP3_MIN_UNSENT_BYTES 4096
-
-/* NGHTTP3_STREAM_MIN_WRITELEN is the minimum length of write to cause
- the stream to reschedule. */
-#define NGHTTP3_STREAM_MIN_WRITELEN 800
-
-/* nghttp3_stream_type is unidirectional stream type. */
-typedef enum {
- NGHTTP3_STREAM_TYPE_CONTROL = 0x00,
- NGHTTP3_STREAM_TYPE_PUSH = 0x01,
- NGHTTP3_STREAM_TYPE_QPACK_ENCODER = 0x02,
- NGHTTP3_STREAM_TYPE_QPACK_DECODER = 0x03,
- NGHTTP3_STREAM_TYPE_UNKNOWN = UINT64_MAX,
-} nghttp3_stream_type;
-
-typedef enum {
- NGHTTP3_CTRL_STREAM_STATE_FRAME_TYPE,
- NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH,
- NGHTTP3_CTRL_STREAM_STATE_CANCEL_PUSH,
- NGHTTP3_CTRL_STREAM_STATE_SETTINGS,
- NGHTTP3_CTRL_STREAM_STATE_GOAWAY,
- NGHTTP3_CTRL_STREAM_STATE_MAX_PUSH_ID,
- NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME,
- NGHTTP3_CTRL_STREAM_STATE_SETTINGS_ID,
- NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE,
-} nghttp3_ctrl_stream_state;
-
-typedef enum {
- NGHTTP3_REQ_STREAM_STATE_FRAME_TYPE,
- NGHTTP3_REQ_STREAM_STATE_FRAME_LENGTH,
- NGHTTP3_REQ_STREAM_STATE_DATA,
- NGHTTP3_REQ_STREAM_STATE_HEADERS,
- NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE_PUSH_ID,
- NGHTTP3_REQ_STREAM_STATE_PUSH_PROMISE,
- NGHTTP3_REQ_STREAM_STATE_IGN_PUSH_PROMISE,
- NGHTTP3_REQ_STREAM_STATE_IGN_FRAME,
-} nghttp3_req_stream_state;
-
-typedef enum {
- NGHTTP3_PUSH_STREAM_STATE_FRAME_TYPE,
- NGHTTP3_PUSH_STREAM_STATE_FRAME_LENGTH,
- NGHTTP3_PUSH_STREAM_STATE_DATA,
- NGHTTP3_PUSH_STREAM_STATE_HEADERS,
- NGHTTP3_PUSH_STREAM_STATE_IGN_FRAME,
- NGHTTP3_PUSH_STREAM_STATE_PUSH_ID,
- NGHTTP3_PUSH_STREAM_STATE_IGN_REST,
-} nghttp3_push_stream_state;
-
-typedef struct {
- int64_t acc;
- size_t left;
-} nghttp3_varint_read_state;
-
-typedef struct {
- nghttp3_varint_read_state rvint;
- nghttp3_frame fr;
- int state;
- int64_t left;
-} nghttp3_stream_read_state;
-
-typedef enum {
- NGHTTP3_STREAM_FLAG_NONE = 0x0000,
- NGHTTP3_STREAM_FLAG_TYPE_IDENTIFIED = 0x0001,
- /* NGHTTP3_STREAM_FLAG_FC_BLOCKED indicates that stream is
- blocked by QUIC flow control. */
- NGHTTP3_STREAM_FLAG_FC_BLOCKED = 0x0002,
- /* NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED indicates that application
- is temporarily unable to provide data. */
- NGHTTP3_STREAM_FLAG_READ_DATA_BLOCKED = 0x0004,
- /* NGHTTP3_STREAM_FLAG_WRITE_END_STREAM indicates that application
- finished to feed outgoing data. */
- NGHTTP3_STREAM_FLAG_WRITE_END_STREAM = 0x0008,
- /* NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED indicates that stream is
- blocked due to QPACK decoding. */
- NGHTTP3_STREAM_FLAG_QPACK_DECODE_BLOCKED = 0x0010,
- /* NGHTTP3_STREAM_FLAG_READ_EOF indicates that remote endpoint sent
- fin. */
- NGHTTP3_STREAM_FLAG_READ_EOF = 0x0020,
- /* NGHTTP3_STREAM_FLAG_CLOSED indicates that QUIC stream was closed.
- nghttp3_stream object can still alive because it might be blocked
- by QPACK decoder. */
- NGHTTP3_STREAM_FLAG_CLOSED = 0x0040,
- /* NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED indicates that stream is
- blocked because the corresponding PUSH_PROMISE has not been
- received yet. */
- NGHTTP3_STREAM_FLAG_PUSH_PROMISE_BLOCKED = 0x0080,
- /* NGHTTP3_STREAM_FLAG_RESET indicates that stream is reset. */
- NGHTTP3_STREAM_FLAG_RESET = 0x0200,
-} nghttp3_stream_flag;
-
-typedef enum {
- NGHTTP3_HTTP_STATE_NONE,
- NGHTTP3_HTTP_STATE_REQ_INITIAL,
- NGHTTP3_HTTP_STATE_REQ_BEGIN,
- NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN,
- NGHTTP3_HTTP_STATE_REQ_HEADERS_END,
- NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN,
- NGHTTP3_HTTP_STATE_REQ_DATA_END,
- NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN,
- NGHTTP3_HTTP_STATE_REQ_TRAILERS_END,
- NGHTTP3_HTTP_STATE_REQ_END,
- NGHTTP3_HTTP_STATE_RESP_INITIAL,
- NGHTTP3_HTTP_STATE_RESP_BEGIN,
- NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN,
- NGHTTP3_HTTP_STATE_RESP_HEADERS_END,
- NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN,
- NGHTTP3_HTTP_STATE_RESP_DATA_END,
- NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN,
- NGHTTP3_HTTP_STATE_RESP_TRAILERS_END,
- NGHTTP3_HTTP_STATE_RESP_END,
-} nghttp3_stream_http_state;
-
-typedef enum {
- NGHTTP3_HTTP_EVENT_DATA_BEGIN,
- NGHTTP3_HTTP_EVENT_DATA_END,
- NGHTTP3_HTTP_EVENT_HEADERS_BEGIN,
- NGHTTP3_HTTP_EVENT_HEADERS_END,
- NGHTTP3_HTTP_EVENT_PUSH_PROMISE_BEGIN,
- NGHTTP3_HTTP_EVENT_PUSH_PROMISE_END,
- NGHTTP3_HTTP_EVENT_MSG_END,
-} nghttp3_stream_http_event;
-
-struct nghttp3_stream;
-typedef struct nghttp3_stream nghttp3_stream;
-
-struct nghttp3_push_promise;
-typedef struct nghttp3_push_promise nghttp3_push_promise;
-
-/*
- * nghttp3_stream_acked_data is a callback function which is invoked
- * when data sent on stream denoted by |stream_id| supplied from
- * application is acknowledged by remote endpoint. The number of
- * bytes acknowledged is given in |datalen|.
- *
- * The implementation of this callback must return 0 if it succeeds.
- * Returning NGHTTP3_ERR_CALLBACK_FAILURE will return to the caller
- * immediately. Any values other than 0 is treated as
- * NGHTTP3_ERR_CALLBACK_FAILURE.
- */
-typedef int (*nghttp3_stream_acked_data)(nghttp3_stream *stream,
- int64_t stream_id, size_t datalen,
- void *user_data);
-
-typedef struct {
- nghttp3_stream_acked_data acked_data;
-} nghttp3_stream_callbacks;
-
-struct nghttp3_http_state {
- /* status_code is HTTP status code received. This field is used
- if connection is initialized as client. */
- int32_t status_code;
- /* content_length is the value of received content-length header
- field. */
- int64_t content_length;
- /* recv_content_length is the number of body bytes received so
- far. */
- int64_t recv_content_length;
- uint16_t flags;
- /* pri is a stream priority produced by nghttp3_pri_to_uint8. */
- uint8_t pri;
-};
-
-typedef struct nghttp3_http_state nghttp3_http_state;
-
-struct nghttp3_stream {
- const nghttp3_mem *mem;
- nghttp3_map_entry me;
- /* node is a node in dependency tree. For server initiated
- unidirectional stream (push), scheduling is done via
- corresponding nghttp3_push_promise object pointed by pp. */
- nghttp3_tnode node;
- nghttp3_pq_entry qpack_blocked_pe;
- nghttp3_stream_callbacks callbacks;
- nghttp3_ringbuf frq;
- nghttp3_ringbuf chunks;
- nghttp3_ringbuf outq;
- /* inq stores the stream raw data which cannot be read because
- stream is blocked by QPACK decoder. */
- nghttp3_ringbuf inq;
- nghttp3_qpack_stream_context qpack_sctx;
- /* conn is a reference to underlying connection. It could be NULL
- if stream is not a request/push stream. */
- nghttp3_conn *conn;
- void *user_data;
- /* unsent_bytes is the number of bytes in outq not written yet */
- size_t unsent_bytes;
- /* outq_idx is an index into outq where next write is made. */
- size_t outq_idx;
- /* outq_offset is write offset relative to the element at outq_idx
- in outq. */
- size_t outq_offset;
- /* ack_offset is offset acknowledged by peer relative to the first
- element in outq. */
- uint64_t ack_offset;
- /* ack_done is the number of bytes notified to an application that
- they are acknowledged inside the first outq element if it is of
- type NGHTTP3_BUF_TYPE_ALIEN. */
- size_t ack_done;
- size_t unscheduled_nwrite;
- nghttp3_stream_type type;
- nghttp3_stream_read_state rstate;
- /* pp is nghttp3_push_promise that this stream fulfills. */
- nghttp3_push_promise *pp;
- /* error_code indicates the reason of closure of this stream. */
- uint64_t error_code;
-
- struct {
- nghttp3_stream_http_state hstate;
- } tx;
-
- struct {
- nghttp3_stream_http_state hstate;
- nghttp3_http_state http;
- } rx;
-
- uint16_t flags;
-};
-
-typedef struct {
- nghttp3_frame fr;
- union {
- struct {
- nghttp3_conn_settings *local_settings;
- } settings;
- struct {
- nghttp3_data_reader dr;
- } data;
- } aux;
-} nghttp3_frame_entry;
-
-int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
- uint64_t seq, const nghttp3_stream_callbacks *callbacks,
- const nghttp3_mem *mem);
-
-void nghttp3_stream_del(nghttp3_stream *stream);
-
-void nghttp3_varint_read_state_reset(nghttp3_varint_read_state *rvint);
-
-void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate);
-
-nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
- const uint8_t *src, size_t srclen, int fin);
-
-int nghttp3_stream_frq_add(nghttp3_stream *stream,
- const nghttp3_frame_entry *frent);
-
-int nghttp3_stream_fill_outq(nghttp3_stream *stream);
-
-int nghttp3_stream_write_stream_type(nghttp3_stream *stream);
-
-int nghttp3_stream_write_stream_type_push_id(nghttp3_stream *stream);
-
-nghttp3_ssize nghttp3_stream_writev(nghttp3_stream *stream, int *pfin,
- nghttp3_vec *vec, size_t veccnt);
-
-int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream);
-
-int nghttp3_stream_outq_is_full(nghttp3_stream *stream);
-
-int nghttp3_stream_outq_add(nghttp3_stream *stream,
- const nghttp3_typed_buf *tbuf);
-
-int nghttp3_stream_write_headers(nghttp3_stream *stream,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_write_push_promise(nghttp3_stream *stream,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_write_header_block(nghttp3_stream *stream,
- nghttp3_qpack_encoder *qenc,
- nghttp3_stream *qenc_stream,
- nghttp3_buf *rbuf, nghttp3_buf *ebuf,
- int64_t frame_type, int64_t push_id,
- const nghttp3_nv *nva, size_t nvlen);
-
-int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_write_settings(nghttp3_stream *stream,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_write_cancel_push(nghttp3_stream *stream,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_write_max_push_id(nghttp3_stream *stream,
- nghttp3_frame_entry *frent);
-
-int nghttp3_stream_ensure_chunk(nghttp3_stream *stream, size_t need);
-
-nghttp3_buf *nghttp3_stream_get_chunk(nghttp3_stream *stream);
-
-int nghttp3_stream_is_blocked(nghttp3_stream *stream);
-
-int nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n);
-
-/*
- * nghttp3_stream_outq_write_done returns nonzero if all contents in
- * outq have been written.
- */
-int nghttp3_stream_outq_write_done(nghttp3_stream *stream);
-
-int nghttp3_stream_add_ack_offset(nghttp3_stream *stream, uint64_t n);
-
-/*
- * nghttp3_stream_is_active returns nonzero if |stream| is active. In
- * other words, it has something to send. This function does not take
- * into account its descendants.
- */
-int nghttp3_stream_is_active(nghttp3_stream *stream);
-
-/*
- * nghttp3_stream_require_schedule returns nonzero if |stream| should
- * be scheduled. In other words, |stream| or its descendants have
- * something to send.
- */
-int nghttp3_stream_require_schedule(nghttp3_stream *stream);
-
-int nghttp3_stream_buffer_data(nghttp3_stream *stream, const uint8_t *src,
- size_t srclen);
-
-size_t nghttp3_stream_get_buffered_datalen(nghttp3_stream *stream);
-
-int nghttp3_stream_ensure_qpack_stream_context(nghttp3_stream *stream);
-
-void nghttp3_stream_delete_qpack_stream_context(nghttp3_stream *stream);
-
-int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
- nghttp3_stream_http_event event);
-
-int nghttp3_stream_empty_headers_allowed(nghttp3_stream *stream);
-
-/*
- * nghttp3_stream_bidi_or_push returns nonzero if |stream| is
- * bidirectional or push stream.
- */
-int nghttp3_stream_bidi_or_push(nghttp3_stream *stream);
-
-/*
- * nghttp3_stream_uni returns nonzero if stream identified by
- * |stream_id| is unidirectional.
- */
-int nghttp3_stream_uni(int64_t stream_id);
-
-/*
- * nghttp3_client_stream_bidi returns nonzero if stream identified by
- * |stream_id| is client initiated bidirectional stream.
- */
-int nghttp3_client_stream_bidi(int64_t stream_id);
-
-/*
- * nghttp3_client_stream_uni returns nonzero if stream identified by
- * |stream_id| is client initiated unidirectional stream.
- */
-int nghttp3_client_stream_uni(int64_t stream_id);
-
-/*
- * nghttp3_server_stream_uni returns nonzero if stream identified by
- * |stream_id| is server initiated unidirectional stream.
- */
-int nghttp3_server_stream_uni(int64_t stream_id);
-
-#endif /* NGHTTP3_STREAM_H */
diff --git a/deps/nghttp3/lib/nghttp3_tnode.c b/deps/nghttp3/lib/nghttp3_tnode.c
deleted file mode 100644
index 94dca7dbf7..0000000000
--- a/deps/nghttp3/lib/nghttp3_tnode.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_tnode.h"
-
-#include <assert.h>
-
-#include "nghttp3_macro.h"
-#include "nghttp3_stream.h"
-#include "nghttp3_conn.h"
-#include "nghttp3_conv.h"
-
-nghttp3_node_id *nghttp3_node_id_init(nghttp3_node_id *nid,
- nghttp3_node_id_type type, int64_t id) {
- nid->type = type;
- nid->id = id;
- return nid;
-}
-
-int nghttp3_node_id_eq(const nghttp3_node_id *a, const nghttp3_node_id *b) {
- return a->type == b->type && a->id == b->id;
-}
-
-void nghttp3_tnode_init(nghttp3_tnode *tnode, const nghttp3_node_id *nid,
- uint64_t seq, uint8_t pri) {
- assert(nghttp3_pri_uint8_urgency(pri) < NGHTTP3_URGENCY_LEVELS);
-
- tnode->pe.index = NGHTTP3_PQ_BAD_INDEX;
- tnode->nid = *nid;
- tnode->seq = seq;
- tnode->cycle = 0;
- tnode->pri = pri;
-}
-
-void nghttp3_tnode_free(nghttp3_tnode *tnode) { (void)tnode; }
-
-static void tnode_unschedule(nghttp3_tnode *tnode, nghttp3_pq *pq) {
- assert(tnode->pe.index != NGHTTP3_PQ_BAD_INDEX);
-
- nghttp3_pq_remove(pq, &tnode->pe);
- tnode->pe.index = NGHTTP3_PQ_BAD_INDEX;
-}
-
-void nghttp3_tnode_unschedule(nghttp3_tnode *tnode, nghttp3_pq *pq) {
- if (tnode->pe.index == NGHTTP3_PQ_BAD_INDEX) {
- return;
- }
-
- tnode_unschedule(tnode, pq);
-}
-
-static uint64_t pq_get_first_cycle(nghttp3_pq *pq) {
- nghttp3_tnode *top;
-
- if (nghttp3_pq_empty(pq)) {
- return 0;
- }
-
- top = nghttp3_struct_of(nghttp3_pq_top(pq), nghttp3_tnode, pe);
- return top->cycle;
-}
-
-int nghttp3_tnode_schedule(nghttp3_tnode *tnode, nghttp3_pq *pq,
- size_t nwrite) {
- uint64_t penalty = nwrite / NGHTTP3_STREAM_MIN_WRITELEN;
-
- if (tnode->pe.index == NGHTTP3_PQ_BAD_INDEX) {
- tnode->cycle = pq_get_first_cycle(pq) +
- ((nwrite == 0 || !nghttp3_pri_uint8_inc(tnode->pri))
- ? 0
- : nghttp3_max(1, penalty));
- } else if (nwrite > 0) {
- if (!nghttp3_pri_uint8_inc(tnode->pri) || nghttp3_pq_size(pq) == 1) {
- return 0;
- }
-
- nghttp3_pq_remove(pq, &tnode->pe);
- tnode->pe.index = NGHTTP3_PQ_BAD_INDEX;
- tnode->cycle += nghttp3_max(1, penalty);
- } else {
- return 0;
- }
-
- return nghttp3_pq_push(pq, &tnode->pe);
-}
-
-int nghttp3_tnode_is_scheduled(nghttp3_tnode *tnode) {
- return tnode->pe.index != NGHTTP3_PQ_BAD_INDEX;
-}
diff --git a/deps/nghttp3/lib/nghttp3_tnode.h b/deps/nghttp3/lib/nghttp3_tnode.h
deleted file mode 100644
index bf861ed040..0000000000
--- a/deps/nghttp3/lib/nghttp3_tnode.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_TNODE_H
-#define NGHTTP3_TNODE_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#include "nghttp3_pq.h"
-
-#define NGHTTP3_TNODE_MAX_CYCLE_GAP (1llu << 24)
-
-typedef enum {
- NGHTTP3_NODE_ID_TYPE_STREAM = 0x00,
- NGHTTP3_NODE_ID_TYPE_PUSH = 0x01,
-} nghttp3_node_id_type;
-
-typedef struct {
- nghttp3_node_id_type type;
- int64_t id;
-} nghttp3_node_id;
-
-nghttp3_node_id *nghttp3_node_id_init(nghttp3_node_id *nid,
- nghttp3_node_id_type type, int64_t id);
-
-int nghttp3_node_id_eq(const nghttp3_node_id *a, const nghttp3_node_id *b);
-
-struct nghttp3_tnode;
-typedef struct nghttp3_tnode nghttp3_tnode;
-
-struct nghttp3_tnode {
- nghttp3_pq_entry pe;
- size_t num_children;
- nghttp3_node_id nid;
- uint64_t seq;
- uint64_t cycle;
- /* pri is a stream priority produced by nghttp3_pri_to_uint8. */
- uint8_t pri;
-};
-
-void nghttp3_tnode_init(nghttp3_tnode *tnode, const nghttp3_node_id *nid,
- uint64_t seq, uint8_t pri);
-
-void nghttp3_tnode_free(nghttp3_tnode *tnode);
-
-void nghttp3_tnode_unschedule(nghttp3_tnode *tnode, nghttp3_pq *pq);
-
-/*
- * nghttp3_tnode_schedule schedules |tnode| using |nwrite| as penalty.
- * If |tnode| has already been scheduled, it is rescheduled by the
- * amount of |nwrite|.
- */
-int nghttp3_tnode_schedule(nghttp3_tnode *tnode, nghttp3_pq *pq, size_t nwrite);
-
-/*
- * nghttp3_tnode_is_scheduled returns nonzero if |tnode| is scheduled.
- */
-int nghttp3_tnode_is_scheduled(nghttp3_tnode *tnode);
-
-#endif /* NGHTTP3_TNODE_H */
diff --git a/deps/nghttp3/lib/nghttp3_vec.c b/deps/nghttp3/lib/nghttp3_vec.c
deleted file mode 100644
index 8d530a060d..0000000000
--- a/deps/nghttp3/lib/nghttp3_vec.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "nghttp3_vec.h"
-#include "nghttp3_macro.h"
-
-size_t nghttp3_vec_len(const nghttp3_vec *vec, size_t n) {
- size_t i;
- size_t res = 0;
-
- for (i = 0; i < n; ++i) {
- res += vec[i].len;
- }
-
- return res;
-}
-
-int nghttp3_vec_empty(const nghttp3_vec *vec, size_t cnt) {
- size_t i;
-
- for (i = 0; i < cnt && vec[i].len == 0; ++i)
- ;
-
- return i == cnt;
-}
-
-void nghttp3_vec_consume(nghttp3_vec **pvec, size_t *pcnt, size_t len) {
- nghttp3_vec *v = *pvec;
- size_t cnt = *pcnt;
-
- for (; cnt > 0; --cnt, ++v) {
- if (v->len > len) {
- v->len -= len;
- v->base += len;
- break;
- }
- len -= v->len;
- }
-
- *pvec = v;
- *pcnt = cnt;
-}
diff --git a/deps/nghttp3/lib/nghttp3_vec.h b/deps/nghttp3/lib/nghttp3_vec.h
deleted file mode 100644
index c1a928e3e1..0000000000
--- a/deps/nghttp3/lib/nghttp3_vec.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGHTTP3_VEC_H
-#define NGHTTP3_VEC_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-#endif /* NGHTTP3_VEC_H */
diff --git a/deps/nghttp3/lib/nghttp3_version.c b/deps/nghttp3/lib/nghttp3_version.c
deleted file mode 100644
index dfad4793c4..0000000000
--- a/deps/nghttp3/lib/nghttp3_version.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * nghttp3
- *
- * Copyright (c) 2019 nghttp3 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <nghttp3/nghttp3.h>
-
-static nghttp3_info version = {NGHTTP3_VERSION_AGE, NGHTTP3_VERSION_NUM,
- NGHTTP3_VERSION};
-
-nghttp3_info *nghttp3_version(int least_version) {
- if (least_version > NGHTTP3_VERSION_NUM) {
- return NULL;
- }
- return &version;
-}
diff --git a/deps/nghttp3/nghttp3.gyp b/deps/nghttp3/nghttp3.gyp
deleted file mode 100644
index 85ca26cbc8..0000000000
--- a/deps/nghttp3/nghttp3.gyp
+++ /dev/null
@@ -1,67 +0,0 @@
-{
- 'target_defaults': {
- 'defines': [
- '_U_='
- ]
- },
- 'targets': [
- {
- 'target_name': 'nghttp3',
- 'type': 'static_library',
- 'include_dirs': ['lib/includes'],
- 'defines': [
- 'BUILDING_NGHTTP3',
- 'NGHTTP3_STATICLIB',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'defines': [
- 'WIN32',
- '_WINDOWS',
- 'HAVE_CONFIG_H',
- ],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'CompileAs': '1'
- },
- },
- }],
- ['OS=="linux"', {
- 'defines': [
- 'HAVE_ARPA_INET_H',
- ],
- }],
- ],
- 'direct_dependent_settings': {
- 'defines': [ 'NGHTTP3_STATICLIB' ],
- 'include_dirs': [ 'lib/includes' ]
- },
- 'sources': [
- 'lib/nghttp3_buf.c',
- 'lib/nghttp3_conv.c',
- 'lib/nghttp3_err.c',
- 'lib/nghttp3_gaptr.c',
- 'lib/nghttp3_idtr.c',
- 'lib/nghttp3_map.c',
- 'lib/nghttp3_pq.c',
- 'lib/nghttp3_qpack_huffman.c',
- 'lib/nghttp3_range.c',
- 'lib/nghttp3_ringbuf.c',
- 'lib/nghttp3_stream.c',
- 'lib/nghttp3_vec.c',
- 'lib/nghttp3_conn.c',
- 'lib/nghttp3_debug.c',
- 'lib/nghttp3_frame.c',
- 'lib/nghttp3_http.c',
- 'lib/nghttp3_ksl.c',
- 'lib/nghttp3_mem.c',
- 'lib/nghttp3_qpack.c',
- 'lib/nghttp3_qpack_huffman_data.c',
- 'lib/nghttp3_rcbuf.c',
- 'lib/nghttp3_str.c',
- 'lib/nghttp3_tnode.c',
- 'lib/nghttp3_version.c'
- ]
- }
- ]
-}
diff --git a/deps/ngtcp2/.gitignore b/deps/ngtcp2/.gitignore
deleted file mode 100644
index 118f239603..0000000000
--- a/deps/ngtcp2/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-**/*/CMakeLists.txt
-**/*/*.am
-**/*/*.h.in
-**/*/*.pc.in
diff --git a/deps/ngtcp2/COPYING b/deps/ngtcp2/COPYING
deleted file mode 100644
index 9b367cdce7..0000000000
--- a/deps/ngtcp2/COPYING
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License
-
-Copyright (c) 2016 ngtcp2 contributors
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h b/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
deleted file mode 100644
index 4b6885a08e..0000000000
--- a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto.h
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CRYPTO_H
-#define NGTCP2_CRYPTO_H
-
-#include <ngtcp2/ngtcp2.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32
-#define NGTCP2_CRYPTO_INITIAL_KEYLEN 16
-#define NGTCP2_CRYPTO_INITIAL_IVLEN 12
-
-/**
- * @function
- *
- * `ngtcp2_crypto_ctx_initial` initializes |ctx| for Initial packet
- * encryption and decryption.
- */
-NGTCP2_EXTERN ngtcp2_crypto_ctx *
-ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_ctx_tls` initializes |ctx| by extracting negotiated
- * ciphers and message digests from native TLS session
- * |tls_native_handle|. This is used for encrypting/decrypting
- * Handshake and Short packets.
- *
- * If libngtcp2_crypto_openssl is linked, |tls_native_handle| must be
- * a pointer to SSL object.
- */
-NGTCP2_EXTERN ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx,
- void *tls_native_handle);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_retry` initializes |aead| with the AEAD cipher
- * AEAD_AES_128_GCM for Retry packet integrity protection.
- */
-NGTCP2_EXTERN ngtcp2_crypto_aead *
-ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_md_hashlen` returns the length of |md| output.
- */
-NGTCP2_EXTERN size_t ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md *md);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_keylen` returns the length of key for |aead|.
- */
-NGTCP2_EXTERN size_t ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead *aead);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_noncelen` returns the length of nonce for
- * |aead|.
- */
-NGTCP2_EXTERN size_t
-ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_taglen` returns the length of tag for |aead|.
- */
-NGTCP2_EXTERN size_t ngtcp2_crypto_aead_taglen(const ngtcp2_crypto_aead *aead);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_hkdf_extract` performs HKDF extract operation. The
- * result is the length of |md| and is stored to the buffer pointed by
- * |dest|. The caller is responsible to specify the buffer that can
- * store the output.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
- const uint8_t *secret, size_t secretlen,
- const uint8_t *salt, size_t saltlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_hkdf_expand` performs HKDF expand operation. The
- * result is |destlen| bytes long and is stored to the buffer pointed
- * by |dest|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret,
- size_t secretlen,
- const uint8_t *info,
- size_t infolen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_hkdf_expand_label` performs HKDF expand label. The
- * result is |destlen| bytes long and is stored to the buffer pointed
- * by |dest|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret,
- size_t secretlen,
- const uint8_t *label,
- size_t labellen);
-
-/**
- * @enum
- *
- * `ngtcp2_crypto_side` indicates which side the application
- * implements; client or server.
- */
-typedef enum ngtcp2_crypto_side {
- /**
- * ``NGTCP2_CRYPTO_SIDE_CLIENT`` indicates that the application is
- * client.
- */
- NGTCP2_CRYPTO_SIDE_CLIENT,
- /**
- * ``NGTCP2_CRYPTO_SIDE_SERVER`` indicates that the application is
- * server.
- */
- NGTCP2_CRYPTO_SIDE_SERVER
-} ngtcp2_crypto_side;
-
-/**
- * @function
- *
- * `ngtcp2_crypto_packet_protection_ivlen` returns the length of IV
- * used to encrypt QUIC packet.
- */
-NGTCP2_EXTERN size_t
-ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_derive_packet_protection_key` derives packet
- * protection key. This function writes packet protection key into
- * the buffer pointed by |key|. |key| must point to the buffer which
- * is at least ngtcp2_crypto_aead_keylen(aead) bytes long. This
- * function writes packet protection IV into |iv|. |iv| must point to
- * the buffer which is at least
- * ngtcp2_crypto_packet_protection_ivlen(aead). |key| is
- * ngtcp2_crypto_aead_keylen(aead) bytes long. |iv| is
- * ngtcp2_crypto_packet_protection_ivlen(aead) bytes long.
- *
- * If |hp| is not NULL, this function also derives packet header
- * protection key and writes the key into the buffer pointed by |hp|.
- * The length of key is ngtcp2_crypto_aead_keylen(aead) bytes long.
- * |hp|, if not NULL, must have enough capacity to store the key.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_derive_packet_protection_key(
- uint8_t *key, uint8_t *iv, uint8_t *hp, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_md *md, const uint8_t *secret, size_t secretlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_encrypt` encrypts |plaintext| of length
- * |plaintextlen| and writes the ciphertext into the buffer pointed by
- * |dest|. The length of ciphertext is plaintextlen +
- * ngtcp2_crypto_aead_taglen(aead) bytes long. |dest| must have
- * enough capacity to store the ciphertext. It is allowed to specify
- * the same value to |dest| and |plaintext|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_encrypt(uint8_t *dest,
- const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *plaintext,
- size_t plaintextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_encrypt_cb` is a wrapper function around
- * `ngtcp2_crypto_encrypt`. It can be directly passed to encrypt
- * callback to ngtcp2_callbacks.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *plaintext, size_t plaintextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_decrypt` decrypts |ciphertext| of length
- * |ciphertextlen| and writes the plaintext into the buffer pointed by
- * |dest|. The length of plaintext is ciphertextlen -
- * ngtcp2_crypto_aead_taglen(aead) bytes long. |dest| must have enough
- * capacity to store the plaintext. It is allowed to specify the same
- * value to |dest| and |ciphertext|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_decrypt(uint8_t *dest,
- const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *ciphertext,
- size_t ciphertextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_decrypt_cb` is a wrapper function around
- * `ngtcp2_crypto_decrypt`. It can be directly passed to decrypt
- * callback to ngtcp2_callbacks.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_TLS_DECRYPT`.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *ciphertext, size_t ciphertextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_hp_mask` generates mask which is used in packet
- * header encryption. The mask is written to the buffer pointed by
- * |dest|. The length of mask is 5 bytes. |dest| must have enough
- * capacity to store the mask.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_hp_mask(uint8_t *dest,
- const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- const uint8_t *sample);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_hp_mask_cb` is a wrapper function around
- * `ngtcp2_crypto_hp_mask`. It can be directly passed to hp_mask
- * callback to ngtcp2_callbacks.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- const uint8_t *sample);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_derive_and_install_rx_key` derives the rx keys from
- * |secret| and installs new keys to |conn|.
- *
- * If |key| is not NULL, the derived packet protection key for
- * decryption is written to the buffer pointed by |key|. If |iv| is
- * not NULL, the derived packet protection IV for decryption is
- * written to the buffer pointed by |iv|. If |hp| is not NULL, the
- * derived header protection key for decryption is written to the
- * buffer pointed by |hp|.
- *
- * |secretlen| specifies the length of |secret|.
- *
- * The length of packet protection key and header protection key is
- * ngtcp2_crypto_aead(ctx->aead), and the length of packet protection
- * IV is ngtcp2_crypto_packet_protection_ivlen(ctx->aead) where ctx
- * can be obtained by `ngtcp2_crypto_ctx_tls`.
- *
- * In the first call of this function, it calls
- * `ngtcp2_conn_set_crypto_ctx` to set negotiated AEAD and message
- * digest algorithm. After the successful call of this function,
- * application can use `ngtcp2_conn_get_crypto_ctx` to get the object.
- * It also calls `ngtcp2_conn_set_aead_overhead` to set AEAD tag
- * length.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_rx_key(
- ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp,
- ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_derive_and_install_tx_key` derives the tx keys from
- * |secret| and installs new keys to |conn|.
- *
- * If |key| is not NULL, the derived packet protection key for
- * encryption is written to the buffer pointed by |key|. If |iv| is
- * not NULL, the derived packet protection IV for encryption is
- * written to the buffer pointed by |iv|. If |hp| is not NULL, the
- * derived header protection key for encryption is written to the
- * buffer pointed by |hp|.
- *
- * |secretlen| specifies the length of |secret|.
- *
- * The length of packet protection key and header protection key is
- * ngtcp2_crypto_aead(ctx->aead), and the length of packet protection
- * IV is ngtcp2_crypto_packet_protection_ivlen(ctx->aead) where ctx
- * can be obtained by `ngtcp2_crypto_ctx_tls`.
- *
- * In the first call of this function, it calls
- * `ngtcp2_conn_set_crypto_ctx` to set negotiated AEAD and message
- * digest algorithm. After the successful call of this function,
- * application can use `ngtcp2_conn_get_crypto_ctx` to get the object.
- * It also calls `ngtcp2_conn_set_aead_overhead` to set AEAD tag
- * length.
- *
- * If |level| is NGTCP2_CRYPTO_LEVEL_APP, this function retrieves a
- * remote QUIC transport parameters extension from |tls| and sets it
- * to |conn|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_derive_and_install_tx_key(
- ngtcp2_conn *conn, uint8_t *key, uint8_t *iv, uint8_t *hp,
- ngtcp2_crypto_level level, const uint8_t *secret, size_t secretlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_update_key` updates traffic keying materials.
- *
- * The new traffic secret for decryption is written to the buffer
- * pointed by |rx_secret|. The length of secret is |secretlen| bytes,
- * and |rx_secret| must point to the buffer which has enough capacity.
- *
- * The new traffic secret for encryption is written to the buffer
- * pointed by |tx_secret|. The length of secret is |secretlen| bytes,
- * and |tx_secret| must point to the buffer which has enough capacity.
- *
- * The derived packet protection key for decryption is written to the
- * buffer pointed by |rx_key|. The derived packet protection IV for
- * decryption is written to the buffer pointed by |rx_iv|.
- * |rx_aead_ctx| must be constructed with |rx_key|.
- *
- * The derived packet protection key for encryption is written to the
- * buffer pointed by |tx_key|. The derived packet protection IV for
- * encryption is written to the buffer pointed by |tx_iv|.
- * |tx_aead_ctx| must be constructed with |rx_key|.
- *
- * |current_rx_secret| and |current_tx_secret| are the current traffic
- * secrets for decryption and encryption. |secretlen| specifies the
- * length of |rx_secret| and |tx_secret|.
- *
- * The length of packet protection key and header protection key is
- * ngtcp2_crypto_aead(ctx->aead), and the length of packet protection
- * IV is ngtcp2_crypto_packet_protection_ivlen(ctx->aead) where ctx
- * can be obtained by `ngtcp2_conn_get_crypto_ctx`.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_update_key(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv,
- ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv,
- const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
- size_t secretlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_update_key_cb` is a wrapper function around
- * `ngtcp2_crypto_update_key`. It can be directly passed to
- * update_key field in ngtcp2_callbacks.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_update_key_cb(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
- ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
- const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
- size_t secretlen, void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_client_initial_cb` installs initial secrets and
- * encryption keys and sets QUIC transport parameters.
- *
- * This function can be directly passed to client_initial field in
- * ngtcp2_callbacks. It is only used by client.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn,
- void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_recv_retry_cb` re-installs initial secrets in
- * response to incoming Retry packet.
- *
- * This function can be directly passed to recv_retry field in
- * ngtcp2_callbacks. It is only used by client.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn,
- const ngtcp2_pkt_hd *hd,
- void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_recv_client_initial_cb` installs initial secrets in
- * response to an incoming Initial packet from client, and sets QUIC
- * transport parameters.
- *
- * This function can be directly passed to recv_client_initial field
- * in ngtcp2_callbacks. It is only used by server.
- *
- * This function returns 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn,
- const ngtcp2_cid *dcid,
- void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_read_write_crypto_data` reads CRYPTO data |data| of
- * length |datalen| in encryption level |crypto_level| and may feed
- * outgoing CRYPTO data to |conn|. This function can drive handshake.
- * This function can be also used after handshake completes. It is
- * allowed to call this function with datalen == 0. In this case, no
- * additional read operation is done.
- *
- * This function returns 0 if it succeeds, or a negative error code.
- * The generic error code is -1 if a specific error code is not
- * suitable. The error codes less than -10000 are specific to
- * underlying TLS implementation. For OpenSSL, the error codes are
- * defined in ngtcp2_crypto_openssl.h.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- const uint8_t *data, size_t datalen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_generate_stateless_reset_token` generates a
- * stateless reset token using HKDF extraction with |md| using the
- * given |cid| and static key |secret| as input. The token will be
- * written to the buffer pointed by |token| and it must have a
- * capacity of at least NGTCP2_STATELESS_RESET_TOKENLEN bytes.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token(
- uint8_t *token, const ngtcp2_crypto_md *md, const uint8_t *secret,
- size_t secretlen, const ngtcp2_cid *cid);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_write_connection_close` writes Initial packet
- * containing CONNECTION_CLOSE with the given |error_code| to the
- * buffer pointed by |dest| of length |destlen|. This function is
- * designed for server to close connection without committing the
- * state when validating Retry token fails. This function must not be
- * used by client. The |dcid| must be the Source Connection ID in
- * Initial packet from client. The |scid| must be the Destination
- * Connection ID in Initial packet from client. |scid| is used to
- * derive initial keying materials.
- *
- * This function wraps around `ngtcp2_pkt_write_connection_close` for
- * easier use.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_crypto_write_connection_close(
- uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, uint64_t error_code);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_write_retry` writes Retry packet to the buffer
- * pointed by |dest| of length |destlen|. |odcid| specifies Original
- * Destination Connection ID. |token| specifies Retry Token, and
- * |tokenlen| specifies its length.
- *
- * This function wraps around `ngtcp2_pkt_write_retry` for easier use.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN ngtcp2_ssize
-ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
- const uint8_t *token, size_t tokenlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_ctx_encrypt_init` initializes |aead_ctx| with
- * new AEAD cipher context object for encryption which is constructed
- * to use |key| as encryption key. |aead| specifies AEAD cipher to
- * use. |noncelen| is the length of nonce.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
- const ngtcp2_crypto_aead *aead,
- const uint8_t *key, size_t noncelen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_ctx_decrypt_init` initializes |aead_ctx| with
- * new AEAD cipher context object for decryption which is constructed
- * to use |key| as encryption key. |aead| specifies AEAD cipher to
- * use. |noncelen| is the length of nonce.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-NGTCP2_EXTERN int
-ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
- const ngtcp2_crypto_aead *aead,
- const uint8_t *key, size_t noncelen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_aead_ctx_free` frees up resources used by
- * |aead_ctx|. This function does not free the memory pointed by
- * |aead_ctx| itself.
- */
-NGTCP2_EXTERN void
-ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_delete_crypto_aead_ctx_cb` deletes the given |aead_ctx|.
- *
- * This function can be directly passed to delete_crypto_aead_ctx
- * field in ngtcp2_callbacks.
- */
-NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_aead_ctx_cb(
- ngtcp2_conn *conn, ngtcp2_crypto_aead_ctx *aead_ctx, void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_delete_crypto_cipher_ctx_cb` deletes the given
- * |cipher_ctx|.
- *
- * This function can be directly passed to delete_crypto_cipher_ctx
- * field in ngtcp2_callbacks.
- */
-NGTCP2_EXTERN void ngtcp2_crypto_delete_crypto_cipher_ctx_cb(
- ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* NGTCP2_CRYPTO_H */
diff --git a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h b/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h
deleted file mode 100644
index 7ccb383e3c..0000000000
--- a/deps/ngtcp2/crypto/includes/ngtcp2/ngtcp2_crypto_openssl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CRYPTO_OPENSSL_H
-#define NGTCP2_CRYPTO_OPENSSL_H
-
-#include <ngtcp2/ngtcp2.h>
-
-/* OpenSSL specific error codes */
-#define NGTCP2_CRYPTO_ERR_TLS_WANT_X509_LOOKUP -10001
-#define NGTCP2_CRYPTO_ERR_TLS_WANT_CLIENT_HELLO_CB -10002
-
-#endif /* NGTCP2_CRYPTO_OPENSSL_H */
diff --git a/deps/ngtcp2/crypto/openssl/openssl.c b/deps/ngtcp2/crypto/openssl/openssl.c
deleted file mode 100644
index d1937441ef..0000000000
--- a/deps/ngtcp2/crypto/openssl/openssl.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <assert.h>
-
-#include <ngtcp2/ngtcp2_crypto.h>
-#include <ngtcp2/ngtcp2_crypto_openssl.h>
-
-#include <openssl/ssl.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-
-#include "shared.h"
-
-ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) {
- ctx->aead.native_handle = (void *)EVP_aes_128_gcm();
- ctx->md.native_handle = (void *)EVP_sha256();
- ctx->hp.native_handle = (void *)EVP_aes_128_ctr();
- ctx->max_encryption = 0;
- ctx->max_decryption_failure = 0;
- return ctx;
-}
-
-ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) {
- aead->native_handle = (void *)EVP_aes_128_gcm();
- return aead;
-}
-
-static const EVP_CIPHER *crypto_ssl_get_aead(SSL *ssl) {
- switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
- case TLS1_3_CK_AES_128_GCM_SHA256:
- return EVP_aes_128_gcm();
- case TLS1_3_CK_AES_256_GCM_SHA384:
- return EVP_aes_256_gcm();
- case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
- return EVP_chacha20_poly1305();
- case TLS1_3_CK_AES_128_CCM_SHA256:
- return EVP_aes_128_ccm();
- default:
- return NULL;
- }
-}
-
-static uint64_t crypto_ssl_get_aead_max_encryption(SSL *ssl) {
- switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
- case TLS1_3_CK_AES_128_GCM_SHA256:
- case TLS1_3_CK_AES_256_GCM_SHA384:
- return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM;
- case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
- return NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305;
- case TLS1_3_CK_AES_128_CCM_SHA256:
- return NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM;
- default:
- return 0;
- }
-}
-
-static uint64_t crypto_ssl_get_aead_max_decryption_failure(SSL *ssl) {
- switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
- case TLS1_3_CK_AES_128_GCM_SHA256:
- case TLS1_3_CK_AES_256_GCM_SHA384:
- return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM;
- case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
- return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305;
- case TLS1_3_CK_AES_128_CCM_SHA256:
- return NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM;
- default:
- return 0;
- }
-}
-
-static const EVP_CIPHER *crypto_ssl_get_hp(SSL *ssl) {
- switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
- case TLS1_3_CK_AES_128_GCM_SHA256:
- case TLS1_3_CK_AES_128_CCM_SHA256:
- return EVP_aes_128_ctr();
- case TLS1_3_CK_AES_256_GCM_SHA384:
- return EVP_aes_256_ctr();
- case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
- return EVP_chacha20();
- default:
- return NULL;
- }
-}
-
-static const EVP_MD *crypto_ssl_get_md(SSL *ssl) {
- switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
- case TLS1_3_CK_AES_128_GCM_SHA256:
- case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
- case TLS1_3_CK_AES_128_CCM_SHA256:
- return EVP_sha256();
- case TLS1_3_CK_AES_256_GCM_SHA384:
- return EVP_sha384();
- default:
- return NULL;
- }
-}
-
-ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx,
- void *tls_native_handle) {
- SSL *ssl = tls_native_handle;
- ctx->aead.native_handle = (void *)crypto_ssl_get_aead(ssl);
- ctx->md.native_handle = (void *)crypto_ssl_get_md(ssl);
- ctx->hp.native_handle = (void *)crypto_ssl_get_hp(ssl);
- ctx->max_encryption = crypto_ssl_get_aead_max_encryption(ssl);
- ctx->max_decryption_failure = crypto_ssl_get_aead_max_decryption_failure(ssl);
- return ctx;
-}
-
-static size_t crypto_md_hashlen(const EVP_MD *md) {
- return (size_t)EVP_MD_size(md);
-}
-
-size_t ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md *md) {
- return crypto_md_hashlen(md->native_handle);
-}
-
-static size_t crypto_aead_keylen(const EVP_CIPHER *aead) {
- return (size_t)EVP_CIPHER_key_length(aead);
-}
-
-size_t ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead *aead) {
- return crypto_aead_keylen(aead->native_handle);
-}
-
-static size_t crypto_aead_noncelen(const EVP_CIPHER *aead) {
- return (size_t)EVP_CIPHER_iv_length(aead);
-}
-
-size_t ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead) {
- return crypto_aead_noncelen(aead->native_handle);
-}
-
-static size_t crypto_aead_taglen(const EVP_CIPHER *aead) {
- if (aead == EVP_aes_128_gcm() || aead == EVP_aes_256_gcm()) {
- return EVP_GCM_TLS_TAG_LEN;
- }
- if (aead == EVP_chacha20_poly1305()) {
- return EVP_CHACHAPOLY_TLS_TAG_LEN;
- }
- if (aead == EVP_aes_128_ccm()) {
- return EVP_CCM_TLS_TAG_LEN;
- }
- return 0;
-}
-
-size_t ngtcp2_crypto_aead_taglen(const ngtcp2_crypto_aead *aead) {
- return crypto_aead_taglen(aead->native_handle);
-}
-
-int ngtcp2_crypto_aead_ctx_encrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
- const ngtcp2_crypto_aead *aead,
- const uint8_t *key, size_t noncelen) {
- const EVP_CIPHER *cipher = aead->native_handle;
- EVP_CIPHER_CTX *actx;
-
- actx = EVP_CIPHER_CTX_new();
- if (actx == NULL) {
- return -1;
- }
-
- if (!EVP_EncryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
- NULL) ||
- (cipher == EVP_aes_128_ccm() &&
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG,
- (int)crypto_aead_taglen(cipher), NULL)) ||
- !EVP_EncryptInit_ex(actx, NULL, NULL, key, NULL)) {
- EVP_CIPHER_CTX_free(actx);
- return -1;
- }
-
- aead_ctx->native_handle = actx;
-
- return 0;
-}
-
-int ngtcp2_crypto_aead_ctx_decrypt_init(ngtcp2_crypto_aead_ctx *aead_ctx,
- const ngtcp2_crypto_aead *aead,
- const uint8_t *key, size_t noncelen) {
- const EVP_CIPHER *cipher = aead->native_handle;
- EVP_CIPHER_CTX *actx;
-
- actx = EVP_CIPHER_CTX_new();
- if (actx == NULL) {
- return -1;
- }
-
- if (!EVP_DecryptInit_ex(actx, cipher, NULL, NULL, NULL) ||
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, (int)noncelen,
- NULL) ||
- (cipher == EVP_aes_128_ccm() &&
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG,
- (int)crypto_aead_taglen(cipher), NULL)) ||
- !EVP_DecryptInit_ex(actx, NULL, NULL, key, NULL)) {
- EVP_CIPHER_CTX_free(actx);
- return -1;
- }
-
- aead_ctx->native_handle = actx;
-
- return 0;
-}
-
-void ngtcp2_crypto_aead_ctx_free(ngtcp2_crypto_aead_ctx *aead_ctx) {
- if (aead_ctx->native_handle) {
- EVP_CIPHER_CTX_free(aead_ctx->native_handle);
- }
-}
-
-int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx,
- const ngtcp2_crypto_cipher *cipher,
- const uint8_t *key) {
- EVP_CIPHER_CTX *actx;
-
- actx = EVP_CIPHER_CTX_new();
- if (actx == NULL) {
- return -1;
- }
-
- if (!EVP_EncryptInit_ex(actx, cipher->native_handle, NULL, key, NULL)) {
- EVP_CIPHER_CTX_free(actx);
- return -1;
- }
-
- cipher_ctx->native_handle = actx;
-
- return 0;
-}
-
-void ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx *cipher_ctx) {
- if (cipher_ctx->native_handle) {
- EVP_CIPHER_CTX_free(cipher_ctx->native_handle);
- }
-}
-
-int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md,
- const uint8_t *secret, size_t secretlen,
- const uint8_t *salt, size_t saltlen) {
- const EVP_MD *prf = md->native_handle;
- int rv = 0;
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
- size_t destlen = (size_t)EVP_MD_size(prf);
-
- if (pctx == NULL) {
- return -1;
- }
-
- if (EVP_PKEY_derive_init(pctx) != 1 ||
- EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) != 1 ||
- EVP_PKEY_CTX_set_hkdf_md(pctx, prf) != 1 ||
- EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, (int)saltlen) != 1 ||
- EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, (int)secretlen) != 1 ||
- EVP_PKEY_derive(pctx, dest, &destlen) != 1) {
- rv = -1;
- }
-
- EVP_PKEY_CTX_free(pctx);
-
- return rv;
-}
-
-int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen,
- const ngtcp2_crypto_md *md, const uint8_t *secret,
- size_t secretlen, const uint8_t *info,
- size_t infolen) {
- const EVP_MD *prf = md->native_handle;
- int rv = 0;
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
- if (pctx == NULL) {
- return -1;
- }
-
- if (EVP_PKEY_derive_init(pctx) != 1 ||
- EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != 1 ||
- EVP_PKEY_CTX_set_hkdf_md(pctx, prf) != 1 ||
- EVP_PKEY_CTX_set1_hkdf_salt(pctx, "", 0) != 1 ||
- EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, (int)secretlen) != 1 ||
- EVP_PKEY_CTX_add1_hkdf_info(pctx, info, (int)infolen) != 1 ||
- EVP_PKEY_derive(pctx, dest, &destlen) != 1) {
- rv = -1;
- }
-
- EVP_PKEY_CTX_free(pctx);
-
- return rv;
-}
-
-int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *plaintext, size_t plaintextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen) {
- const EVP_CIPHER *cipher = aead->native_handle;
- size_t taglen = crypto_aead_taglen(cipher);
- EVP_CIPHER_CTX *actx = aead_ctx->native_handle;
- int len;
-
- (void)noncelen;
-
- if (!EVP_EncryptInit_ex(actx, NULL, NULL, NULL, nonce) ||
- (cipher == EVP_aes_128_ccm() &&
- !EVP_EncryptUpdate(actx, NULL, &len, NULL, (int)plaintextlen)) ||
- !EVP_EncryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
- !EVP_EncryptUpdate(actx, dest, &len, plaintext, (int)plaintextlen) ||
- !EVP_EncryptFinal_ex(actx, dest + len, &len) ||
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_GET_TAG, (int)taglen,
- dest + plaintextlen)) {
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *ciphertext, size_t ciphertextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen) {
- const EVP_CIPHER *cipher = aead->native_handle;
- size_t taglen = crypto_aead_taglen(cipher);
- EVP_CIPHER_CTX *actx = aead_ctx->native_handle;
- int len;
- const uint8_t *tag;
-
- (void)noncelen;
-
- if (taglen > ciphertextlen) {
- return -1;
- }
-
- ciphertextlen -= taglen;
- tag = ciphertext + ciphertextlen;
-
- if (!EVP_DecryptInit_ex(actx, NULL, NULL, NULL, nonce) ||
- !EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, (int)taglen,
- (uint8_t *)tag) ||
- (cipher == EVP_aes_128_ccm() &&
- !EVP_DecryptUpdate(actx, NULL, &len, NULL, (int)ciphertextlen)) ||
- !EVP_DecryptUpdate(actx, NULL, &len, ad, (int)adlen) ||
- !EVP_DecryptUpdate(actx, dest, &len, ciphertext, (int)ciphertextlen) ||
- (cipher != EVP_aes_128_ccm() &&
- !EVP_DecryptFinal_ex(actx, dest + ciphertextlen, &len))) {
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- const uint8_t *sample) {
- static const uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00";
- EVP_CIPHER_CTX *actx = hp_ctx->native_handle;
- int len;
-
- (void)hp;
-
- if (!EVP_EncryptInit_ex(actx, NULL, NULL, NULL, sample) ||
- !EVP_EncryptUpdate(actx, dest, &len, PLAINTEXT, sizeof(PLAINTEXT) - 1) ||
- !EVP_EncryptFinal_ex(actx, dest + sizeof(PLAINTEXT) - 1, &len)) {
- return -1;
- }
-
- return 0;
-}
-
-static OSSL_ENCRYPTION_LEVEL
-from_ngtcp2_level(ngtcp2_crypto_level crypto_level) {
- switch (crypto_level) {
- case NGTCP2_CRYPTO_LEVEL_INITIAL:
- return ssl_encryption_initial;
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- return ssl_encryption_handshake;
- case NGTCP2_CRYPTO_LEVEL_APP:
- return ssl_encryption_application;
- case NGTCP2_CRYPTO_LEVEL_EARLY:
- return ssl_encryption_early_data;
- default:
- assert(0);
- }
-}
-
-int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- const uint8_t *data, size_t datalen) {
- SSL *ssl = ngtcp2_conn_get_tls_native_handle(conn);
- int rv;
- int err;
-
- if (SSL_provide_quic_data(ssl, from_ngtcp2_level(crypto_level), data,
- datalen) != 1) {
- return -1;
- }
-
- if (!ngtcp2_conn_get_handshake_completed(conn)) {
- rv = SSL_do_handshake(ssl);
- if (rv <= 0) {
- err = SSL_get_error(ssl, rv);
- switch (err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- return 0;
- case SSL_ERROR_WANT_CLIENT_HELLO_CB:
- return NGTCP2_CRYPTO_ERR_TLS_WANT_CLIENT_HELLO_CB;
- case SSL_ERROR_WANT_X509_LOOKUP:
- return NGTCP2_CRYPTO_ERR_TLS_WANT_X509_LOOKUP;
- case SSL_ERROR_SSL:
- return -1;
- default:
- return -1;
- }
- }
-
- ngtcp2_conn_handshake_completed(conn);
- }
-
- rv = SSL_process_quic_post_handshake(ssl);
- if (rv != 1) {
- err = SSL_get_error(ssl, rv);
- switch (err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- return 0;
- case SSL_ERROR_SSL:
- case SSL_ERROR_ZERO_RETURN:
- return -1;
- default:
- return -1;
- }
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) {
- SSL *ssl = tls;
- ngtcp2_transport_params_type exttype =
- ngtcp2_conn_is_server(conn)
- ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO
- : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS;
- const uint8_t *tp;
- size_t tplen;
- ngtcp2_transport_params params;
- int rv;
-
- SSL_get_peer_quic_transport_params(ssl, &tp, &tplen);
-
- rv = ngtcp2_decode_transport_params(&params, exttype, tp, tplen);
- if (rv != 0) {
- ngtcp2_conn_set_tls_error(conn, rv);
- return -1;
- }
-
- rv = ngtcp2_conn_set_remote_transport_params(conn, &params);
- if (rv != 0) {
- ngtcp2_conn_set_tls_error(conn, rv);
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
- size_t len) {
- if (SSL_set_quic_transport_params(tls, buf, len) != 1) {
- return -1;
- }
-
- return 0;
-}
diff --git a/deps/ngtcp2/crypto/shared.c b/deps/ngtcp2/crypto/shared.c
deleted file mode 100644
index 7e5219c52f..0000000000
--- a/deps/ngtcp2/crypto/shared.c
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "shared.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_macro.h"
-
-int ngtcp2_crypto_hkdf_expand_label(uint8_t *dest, size_t destlen,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret, size_t secretlen,
- const uint8_t *label, size_t labellen) {
- static const uint8_t LABEL[] = "tls13 ";
- uint8_t info[256];
- uint8_t *p = info;
-
- *p++ = (uint8_t)(destlen / 256);
- *p++ = (uint8_t)(destlen % 256);
- *p++ = (uint8_t)(sizeof(LABEL) - 1 + labellen);
- memcpy(p, LABEL, sizeof(LABEL) - 1);
- p += sizeof(LABEL) - 1;
- memcpy(p, label, labellen);
- p += labellen;
- *p++ = 0;
-
- return ngtcp2_crypto_hkdf_expand(dest, destlen, md, secret, secretlen, info,
- (size_t)(p - info));
-}
-
-#define NGTCP2_CRYPTO_INITIAL_SECRETLEN 32
-
-int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret,
- uint8_t *initial_secret,
- const ngtcp2_cid *client_dcid,
- ngtcp2_crypto_side side) {
- static const uint8_t CLABEL[] = "client in";
- static const uint8_t SLABEL[] = "server in";
- uint8_t initial_secret_buf[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t *client_secret;
- uint8_t *server_secret;
- ngtcp2_crypto_ctx ctx;
-
- if (!initial_secret) {
- initial_secret = initial_secret_buf;
- }
-
- ngtcp2_crypto_ctx_initial(&ctx);
-
- if (ngtcp2_crypto_hkdf_extract(initial_secret, &ctx.md, client_dcid->data,
- client_dcid->datalen,
- (const uint8_t *)NGTCP2_INITIAL_SALT,
- sizeof(NGTCP2_INITIAL_SALT) - 1) != 0) {
- return -1;
- }
-
- if (side == NGTCP2_CRYPTO_SIDE_SERVER) {
- client_secret = rx_secret;
- server_secret = tx_secret;
- } else {
- client_secret = tx_secret;
- server_secret = rx_secret;
- }
-
- if (ngtcp2_crypto_hkdf_expand_label(
- client_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md,
- initial_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, CLABEL,
- sizeof(CLABEL) - 1) != 0 ||
- ngtcp2_crypto_hkdf_expand_label(
- server_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, &ctx.md,
- initial_secret, NGTCP2_CRYPTO_INITIAL_SECRETLEN, SLABEL,
- sizeof(SLABEL) - 1) != 0) {
- return -1;
- }
-
- return 0;
-}
-
-size_t ngtcp2_crypto_packet_protection_ivlen(const ngtcp2_crypto_aead *aead) {
- size_t noncelen = ngtcp2_crypto_aead_noncelen(aead);
- return ngtcp2_max(8, noncelen);
-}
-
-int ngtcp2_crypto_derive_packet_protection_key(
- uint8_t *key, uint8_t *iv, uint8_t *hp_key, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_md *md, const uint8_t *secret, size_t secretlen) {
- static const uint8_t KEY_LABEL[] = "quic key";
- static const uint8_t IV_LABEL[] = "quic iv";
- static const uint8_t HP_KEY_LABEL[] = "quic hp";
- size_t keylen = ngtcp2_crypto_aead_keylen(aead);
- size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
-
- if (ngtcp2_crypto_hkdf_expand_label(key, keylen, md, secret, secretlen,
- KEY_LABEL, sizeof(KEY_LABEL) - 1) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_hkdf_expand_label(iv, ivlen, md, secret, secretlen,
- IV_LABEL, sizeof(IV_LABEL) - 1) != 0) {
- return -1;
- }
-
- if (hp_key != NULL && ngtcp2_crypto_hkdf_expand_label(
- hp_key, keylen, md, secret, secretlen, HP_KEY_LABEL,
- sizeof(HP_KEY_LABEL) - 1) != 0) {
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_update_traffic_secret(uint8_t *dest,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret,
- size_t secretlen) {
- static const uint8_t LABEL[] = "quic ku";
-
- if (ngtcp2_crypto_hkdf_expand_label(dest, secretlen, md, secret, secretlen,
- LABEL, sizeof(LABEL) - 1) != 0) {
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
- uint8_t *iv, uint8_t *hp_key,
- ngtcp2_crypto_level level,
- const uint8_t *secret,
- size_t secretlen) {
- const ngtcp2_crypto_ctx *ctx;
- const ngtcp2_crypto_aead *aead;
- const ngtcp2_crypto_md *md;
- const ngtcp2_crypto_cipher *hp;
- ngtcp2_crypto_aead_ctx aead_ctx = {0};
- ngtcp2_crypto_cipher_ctx hp_ctx = {0};
- void *tls = ngtcp2_conn_get_tls_native_handle(conn);
- uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
- size_t ivlen;
- int rv;
-
- if (level == NGTCP2_CRYPTO_LEVEL_EARLY && !ngtcp2_conn_is_server(conn)) {
- return 0;
- }
-
- if (!key) {
- key = keybuf;
- }
- if (!iv) {
- iv = ivbuf;
- }
- if (!hp_key) {
- hp_key = hp_keybuf;
- }
-
- ctx = ngtcp2_conn_get_crypto_ctx(conn);
-
- if (!ctx->aead.native_handle) {
- ngtcp2_crypto_ctx cctx;
- ngtcp2_crypto_ctx_tls(&cctx, tls);
- ngtcp2_conn_set_aead_overhead(conn, ngtcp2_crypto_aead_taglen(&cctx.aead));
- ngtcp2_conn_set_crypto_ctx(conn, &cctx);
- ctx = ngtcp2_conn_get_crypto_ctx(conn);
- }
-
- aead = &ctx->aead;
- md = &ctx->md;
- hp = &ctx->hp;
- ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
-
- if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
- secret, secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_decrypt_init(&aead_ctx, aead, key, ivlen) != 0) {
- goto fail;
- }
-
- if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, hp, hp_key) != 0) {
- goto fail;
- }
-
- switch (level) {
- case NGTCP2_CRYPTO_LEVEL_EARLY:
- rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
- break;
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- rv = ngtcp2_conn_install_rx_handshake_key(conn, &aead_ctx, iv, ivlen,
- &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
- break;
- case NGTCP2_CRYPTO_LEVEL_APP:
- if (!ngtcp2_conn_is_server(conn)) {
- rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
- if (rv != 0) {
- goto fail;
- }
- }
-
- rv = ngtcp2_conn_install_rx_key(conn, secret, secretlen, &aead_ctx, iv,
- ivlen, &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
-
- break;
- default:
- goto fail;
- }
-
- return 0;
-
-fail:
- ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
- ngtcp2_crypto_aead_ctx_free(&aead_ctx);
-
- return -1;
-}
-
-/*
- * crypto_set_local_transport_params gets local QUIC transport
- * parameters from |conn| and sets it to |tls|.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-static int crypto_set_local_transport_params(ngtcp2_conn *conn, void *tls) {
- ngtcp2_transport_params_type exttype =
- ngtcp2_conn_is_server(conn)
- ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS
- : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO;
- ngtcp2_transport_params params;
- ngtcp2_ssize nwrite;
- uint8_t buf[256];
-
- ngtcp2_conn_get_local_transport_params(conn, &params);
-
- nwrite = ngtcp2_encode_transport_params(buf, sizeof(buf), exttype, &params);
- if (nwrite < 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_set_local_transport_params(tls, buf, (size_t)nwrite) != 0) {
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
- uint8_t *iv, uint8_t *hp_key,
- ngtcp2_crypto_level level,
- const uint8_t *secret,
- size_t secretlen) {
- const ngtcp2_crypto_ctx *ctx;
- const ngtcp2_crypto_aead *aead;
- const ngtcp2_crypto_md *md;
- const ngtcp2_crypto_cipher *hp;
- ngtcp2_crypto_aead_ctx aead_ctx = {0};
- ngtcp2_crypto_cipher_ctx hp_ctx = {0};
- void *tls = ngtcp2_conn_get_tls_native_handle(conn);
- uint8_t keybuf[64], ivbuf[64], hp_keybuf[64];
- size_t ivlen;
- int rv;
-
- if (level == NGTCP2_CRYPTO_LEVEL_EARLY && ngtcp2_conn_is_server(conn)) {
- return 0;
- }
-
- if (!key) {
- key = keybuf;
- }
- if (!iv) {
- iv = ivbuf;
- }
- if (!hp_key) {
- hp_key = hp_keybuf;
- }
-
- ctx = ngtcp2_conn_get_crypto_ctx(conn);
-
- if (!ctx->aead.native_handle) {
- ngtcp2_crypto_ctx cctx;
- ngtcp2_crypto_ctx_tls(&cctx, tls);
- ngtcp2_conn_set_aead_overhead(conn, ngtcp2_crypto_aead_taglen(&cctx.aead));
- ngtcp2_conn_set_crypto_ctx(conn, &cctx);
- ctx = ngtcp2_conn_get_crypto_ctx(conn);
- }
-
- aead = &ctx->aead;
- md = &ctx->md;
- hp = &ctx->hp;
- ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
-
- if (ngtcp2_crypto_derive_packet_protection_key(key, iv, hp_key, aead, md,
- secret, secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, aead, key, ivlen) != 0) {
- goto fail;
- }
-
- if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, hp, hp_key) != 0) {
- goto fail;
- }
-
- switch (level) {
- case NGTCP2_CRYPTO_LEVEL_EARLY:
- rv = ngtcp2_conn_install_early_key(conn, &aead_ctx, iv, ivlen, &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
- break;
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- rv = ngtcp2_conn_install_tx_handshake_key(conn, &aead_ctx, iv, ivlen,
- &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
-
- if (ngtcp2_conn_is_server(conn)) {
- rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
- if (rv != 0) {
- goto fail;
- }
-
- if (crypto_set_local_transport_params(conn, tls) != 0) {
- goto fail;
- }
- }
-
- break;
- case NGTCP2_CRYPTO_LEVEL_APP:
- rv = ngtcp2_conn_install_tx_key(conn, secret, secretlen, &aead_ctx, iv,
- ivlen, &hp_ctx);
- if (rv != 0) {
- goto fail;
- }
-
- break;
- default:
- goto fail;
- }
-
- return 0;
-
-fail:
- ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
- ngtcp2_crypto_aead_ctx_free(&aead_ctx);
-
- return -1;
-}
-
-int ngtcp2_crypto_derive_and_install_initial_key(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv,
- uint8_t *rx_hp_key, uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp_key,
- const ngtcp2_cid *client_dcid) {
- uint8_t rx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t tx_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t initial_secretbuf[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t rx_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- uint8_t rx_ivbuf[NGTCP2_CRYPTO_INITIAL_IVLEN];
- uint8_t rx_hp_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- uint8_t tx_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- uint8_t tx_ivbuf[NGTCP2_CRYPTO_INITIAL_IVLEN];
- uint8_t tx_hp_keybuf[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- ngtcp2_crypto_ctx ctx;
- ngtcp2_crypto_aead retry_aead;
- ngtcp2_crypto_aead_ctx rx_aead_ctx = {0};
- ngtcp2_crypto_cipher_ctx rx_hp_ctx = {0};
- ngtcp2_crypto_aead_ctx tx_aead_ctx = {0};
- ngtcp2_crypto_cipher_ctx tx_hp_ctx = {0};
- ngtcp2_crypto_aead_ctx retry_aead_ctx = {0};
- int rv;
- int server = ngtcp2_conn_is_server(conn);
-
- ngtcp2_crypto_ctx_initial(&ctx);
-
- if (!rx_secret) {
- rx_secret = rx_secretbuf;
- }
- if (!tx_secret) {
- tx_secret = tx_secretbuf;
- }
- if (!initial_secret) {
- initial_secret = initial_secretbuf;
- }
-
- if (!rx_key) {
- rx_key = rx_keybuf;
- }
- if (!rx_iv) {
- rx_iv = rx_ivbuf;
- }
- if (!rx_hp_key) {
- rx_hp_key = rx_hp_keybuf;
- }
- if (!tx_key) {
- tx_key = tx_keybuf;
- }
- if (!tx_iv) {
- tx_iv = tx_ivbuf;
- }
- if (!tx_hp_key) {
- tx_hp_key = tx_hp_keybuf;
- }
-
- ngtcp2_conn_set_initial_crypto_ctx(conn, &ctx);
-
- if (ngtcp2_crypto_derive_initial_secrets(
- rx_secret, tx_secret, initial_secret, client_dcid,
- server ? NGTCP2_CRYPTO_SIDE_SERVER : NGTCP2_CRYPTO_SIDE_CLIENT) !=
- 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_derive_packet_protection_key(
- rx_key, rx_iv, rx_hp_key, &ctx.aead, &ctx.md, rx_secret,
- NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_derive_packet_protection_key(
- tx_key, tx_iv, tx_hp_key, &ctx.aead, &ctx.md, tx_secret,
- NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_decrypt_init(&rx_aead_ctx, &ctx.aead, rx_key,
- NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
- goto fail;
- }
-
- if (ngtcp2_crypto_cipher_ctx_encrypt_init(&rx_hp_ctx, &ctx.hp, rx_hp_key) !=
- 0) {
- goto fail;
- }
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(&tx_aead_ctx, &ctx.aead, tx_key,
- NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
- goto fail;
- }
-
- if (ngtcp2_crypto_cipher_ctx_encrypt_init(&tx_hp_ctx, &ctx.hp, tx_hp_key) !=
- 0) {
- goto fail;
- }
-
- if (!server && !ngtcp2_conn_after_retry(conn)) {
- ngtcp2_crypto_aead_retry(&retry_aead);
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(
- &retry_aead_ctx, &retry_aead, (const uint8_t *)NGTCP2_RETRY_KEY,
- sizeof(NGTCP2_RETRY_NONCE) - 1) != 0) {
- goto fail;
- }
- }
-
- rv = ngtcp2_conn_install_initial_key(conn, &rx_aead_ctx, rx_iv, &rx_hp_ctx,
- &tx_aead_ctx, tx_iv, &tx_hp_ctx,
- NGTCP2_CRYPTO_INITIAL_IVLEN);
- if (rv != 0) {
- goto fail;
- }
-
- if (retry_aead_ctx.native_handle) {
- ngtcp2_conn_set_retry_aead(conn, &retry_aead, &retry_aead_ctx);
- }
-
- return 0;
-
-fail:
- ngtcp2_crypto_aead_ctx_free(&retry_aead_ctx);
- ngtcp2_crypto_cipher_ctx_free(&tx_hp_ctx);
- ngtcp2_crypto_aead_ctx_free(&tx_aead_ctx);
- ngtcp2_crypto_cipher_ctx_free(&rx_hp_ctx);
- ngtcp2_crypto_aead_ctx_free(&rx_aead_ctx);
-
- return -1;
-}
-
-int ngtcp2_crypto_update_key(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_key, uint8_t *rx_iv,
- ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_key, uint8_t *tx_iv,
- const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
- size_t secretlen) {
- const ngtcp2_crypto_ctx *ctx = ngtcp2_conn_get_crypto_ctx(conn);
- const ngtcp2_crypto_aead *aead = &ctx->aead;
- const ngtcp2_crypto_md *md = &ctx->md;
- size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
-
- if (ngtcp2_crypto_update_traffic_secret(rx_secret, md, current_rx_secret,
- secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_derive_packet_protection_key(rx_key, rx_iv, NULL, aead, md,
- rx_secret, secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_update_traffic_secret(tx_secret, md, current_tx_secret,
- secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_derive_packet_protection_key(tx_key, tx_iv, NULL, aead, md,
- tx_secret, secretlen) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_decrypt_init(rx_aead_ctx, aead, rx_key, ivlen) !=
- 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(tx_aead_ctx, aead, tx_key, ivlen) !=
- 0) {
- ngtcp2_crypto_aead_ctx_free(rx_aead_ctx);
- rx_aead_ctx->native_handle = NULL;
- return -1;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_encrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *plaintext, size_t plaintextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen) {
- if (ngtcp2_crypto_encrypt(dest, aead, aead_ctx, plaintext, plaintextlen,
- nonce, noncelen, ad, adlen) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- return 0;
-}
-
-int ngtcp2_crypto_decrypt_cb(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *ciphertext, size_t ciphertextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen) {
- if (ngtcp2_crypto_decrypt(dest, aead, aead_ctx, ciphertext, ciphertextlen,
- nonce, noncelen, ad, adlen) != 0) {
- return NGTCP2_ERR_TLS_DECRYPT;
- }
- return 0;
-}
-
-int ngtcp2_crypto_hp_mask_cb(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- const uint8_t *sample) {
- if (ngtcp2_crypto_hp_mask(dest, hp, hp_ctx, sample) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- return 0;
-}
-
-int ngtcp2_crypto_update_key_cb(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
- ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
- const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
- size_t secretlen, void *user_data) {
- uint8_t rx_key[64];
- uint8_t tx_key[64];
- (void)conn;
- (void)user_data;
-
- if (ngtcp2_crypto_update_key(conn, rx_secret, tx_secret, rx_aead_ctx, rx_key,
- rx_iv, tx_aead_ctx, tx_key, tx_iv,
- current_rx_secret, current_tx_secret,
- secretlen) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- return 0;
-}
-
-int ngtcp2_crypto_generate_stateless_reset_token(uint8_t *token,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret,
- size_t secretlen,
- const ngtcp2_cid *cid) {
- uint8_t buf[64];
- int rv;
-
- assert(ngtcp2_crypto_md_hashlen(md) <= sizeof(buf));
- assert(NGTCP2_STATELESS_RESET_TOKENLEN <= sizeof(buf));
-
- rv = ngtcp2_crypto_hkdf_extract(buf, md, secret, secretlen, cid->data,
- cid->datalen);
- if (rv != 0) {
- return -1;
- }
-
- memcpy(token, buf, NGTCP2_STATELESS_RESET_TOKENLEN);
-
- return 0;
-}
-
-ngtcp2_ssize ngtcp2_crypto_write_connection_close(uint8_t *dest, size_t destlen,
- const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid,
- uint64_t error_code) {
- uint8_t rx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t tx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t initial_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN];
- uint8_t tx_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- uint8_t tx_iv[NGTCP2_CRYPTO_INITIAL_IVLEN];
- uint8_t tx_hp_key[NGTCP2_CRYPTO_INITIAL_KEYLEN];
- ngtcp2_crypto_ctx ctx;
- ngtcp2_ssize spktlen;
- ngtcp2_crypto_aead_ctx aead_ctx = {0};
- ngtcp2_crypto_cipher_ctx hp_ctx = {0};
-
- ngtcp2_crypto_ctx_initial(&ctx);
-
- if (ngtcp2_crypto_derive_initial_secrets(rx_secret, tx_secret, initial_secret,
- scid,
- NGTCP2_CRYPTO_SIDE_SERVER) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_derive_packet_protection_key(
- tx_key, tx_iv, tx_hp_key, &ctx.aead, &ctx.md, tx_secret,
- NGTCP2_CRYPTO_INITIAL_SECRETLEN) != 0) {
- return -1;
- }
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &ctx.aead, tx_key,
- NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
- spktlen = -1;
- goto end;
- }
-
- if (ngtcp2_crypto_cipher_ctx_encrypt_init(&hp_ctx, &ctx.hp, tx_hp_key) != 0) {
- spktlen = -1;
- goto end;
- }
-
- spktlen = ngtcp2_pkt_write_connection_close(
- dest, destlen, dcid, scid, error_code, ngtcp2_crypto_encrypt_cb,
- &ctx.aead, &aead_ctx, tx_iv, ngtcp2_crypto_hp_mask_cb, &ctx.hp, &hp_ctx);
- if (spktlen < 0) {
- spktlen = -1;
- }
-
-end:
- ngtcp2_crypto_cipher_ctx_free(&hp_ctx);
- ngtcp2_crypto_aead_ctx_free(&aead_ctx);
-
- return spktlen;
-}
-
-ngtcp2_ssize ngtcp2_crypto_write_retry(uint8_t *dest, size_t destlen,
- const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid,
- const ngtcp2_cid *odcid,
- const uint8_t *token, size_t tokenlen) {
- ngtcp2_crypto_aead aead;
- ngtcp2_ssize spktlen;
- ngtcp2_crypto_aead_ctx aead_ctx = {0};
-
- ngtcp2_crypto_aead_retry(&aead);
-
- if (ngtcp2_crypto_aead_ctx_encrypt_init(&aead_ctx, &aead,
- (const uint8_t *)NGTCP2_RETRY_KEY,
- NGTCP2_CRYPTO_INITIAL_IVLEN) != 0) {
- return -1;
- }
-
- spktlen =
- ngtcp2_pkt_write_retry(dest, destlen, dcid, scid, odcid, token, tokenlen,
- ngtcp2_crypto_encrypt_cb, &aead, &aead_ctx);
- if (spktlen < 0) {
- spktlen = -1;
- }
-
- ngtcp2_crypto_aead_ctx_free(&aead_ctx);
-
- return spktlen;
-}
-
-/*
- * crypto_setup_initial_crypto establishes the initial secrets and
- * encryption keys, and prepares local QUIC transport parameters.
- */
-static int crypto_setup_initial_crypto(ngtcp2_conn *conn,
- const ngtcp2_cid *dcid) {
- return ngtcp2_crypto_derive_and_install_initial_key(
- conn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dcid);
-}
-
-int ngtcp2_crypto_client_initial_cb(ngtcp2_conn *conn, void *user_data) {
- const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(conn);
- void *tls = ngtcp2_conn_get_tls_native_handle(conn);
- (void)user_data;
-
- if (crypto_setup_initial_crypto(conn, dcid) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- if (crypto_set_local_transport_params(conn, tls) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- if (ngtcp2_crypto_read_write_crypto_data(conn, NGTCP2_CRYPTO_LEVEL_INITIAL,
- NULL, 0) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_recv_retry_cb(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
- void *user_data) {
- (void)user_data;
-
- if (ngtcp2_crypto_derive_and_install_initial_key(conn, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- &hd->scid) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-int ngtcp2_crypto_recv_client_initial_cb(ngtcp2_conn *conn,
- const ngtcp2_cid *dcid,
- void *user_data) {
- (void)user_data;
-
- if (crypto_setup_initial_crypto(conn, dcid) != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-void ngtcp2_crypto_delete_crypto_aead_ctx_cb(ngtcp2_conn *conn,
- ngtcp2_crypto_aead_ctx *aead_ctx,
- void *user_data) {
- (void)conn;
- (void)user_data;
-
- ngtcp2_crypto_aead_ctx_free(aead_ctx);
-}
-
-void ngtcp2_crypto_delete_crypto_cipher_ctx_cb(
- ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data) {
- (void)conn;
- (void)user_data;
-
- ngtcp2_crypto_cipher_ctx_free(cipher_ctx);
-}
diff --git a/deps/ngtcp2/crypto/shared.h b/deps/ngtcp2/crypto/shared.h
deleted file mode 100644
index b70513afb3..0000000000
--- a/deps/ngtcp2/crypto/shared.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_SHARED_H
-#define NGTCP2_SHARED_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2_crypto.h>
-
-/* Maximum key usage (encryption) limits */
-#define NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_GCM (23726566ULL)
-#define NGTCP2_CRYPTO_MAX_ENCRYPTION_CHACHA20_POLY1305 (1ULL << 62)
-#define NGTCP2_CRYPTO_MAX_ENCRYPTION_AES_CCM (1ULL << 23)
-
-/* Maximum authentication failure (decryption) limits */
-#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_GCM (1ULL << 36)
-#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_CHACHA20_POLY1305 (1ULL << 36)
-#define NGTCP2_CRYPTO_MAX_DECRYPTION_FAILURE_AES_CCM (11863283ULL)
-
-/**
- * @function
- *
- * `ngtcp2_crypto_derive_initial_secrets` derives initial secrets.
- * |rx_secret| and |tx_secret| must point to the buffer of at least 32
- * bytes capacity. rx for read and tx for write. This function
- * writes rx and tx secrets into |rx_secret| and |tx_secret|
- * respectively. The length of secret is 32 bytes long.
- * |client_dcid| is the destination connection ID in first Initial
- * packet of client. If |initial_secret| is not NULL, the initial
- * secret is written to it. It must point to the buffer which has at
- * least 32 bytes capacity. The initial secret is 32 bytes long.
- * |side| specifies the side of application.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_derive_initial_secrets(uint8_t *rx_secret, uint8_t *tx_secret,
- uint8_t *initial_secret,
- const ngtcp2_cid *client_dcid,
- ngtcp2_crypto_side side);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_update_traffic_secret` derives the next generation
- * of the traffic secret. |secret| specifies the current secret and
- * its length is given in |secretlen|. The length of new key is the
- * same as the current key. This function writes new key into the
- * buffer pointed by |dest|. |dest| must have the enough capacity to
- * store the new key.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_update_traffic_secret(uint8_t *dest,
- const ngtcp2_crypto_md *md,
- const uint8_t *secret,
- size_t secretlen);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_set_local_transport_params` sets QUIC transport
- * parameter, which is encoded in wire format and stored in the buffer
- * pointed by |buf| of length |len|, to the native handle |tls|.
- *
- * |tls| points to a implementation dependent TLS session object. If
- * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
- * object.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_set_local_transport_params(void *tls, const uint8_t *buf,
- size_t len);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_set_remote_transport_params` retrieves a remote QUIC
- * transport parameters from |tls| and sets it to |conn| using
- * `ngtcp2_conn_set_remote_transport_params`.
- *
- * |tls| points to a implementation dependent TLS session object. If
- * libngtcp2_crypto_openssl is linked, |tls| must be a pointer to SSL
- * object.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_derive_and_install_initial_key` derives initial
- * keying materials and installs keys to |conn|.
- *
- * If |rx_secret| is not NULL, the secret for decryption is written to
- * the buffer pointed by |rx_secret|. The length of secret is 32
- * bytes, and |rx_secret| must point to the buffer which has enough
- * capacity.
- *
- * If |tx_secret| is not NULL, the secret for encryption is written to
- * the buffer pointed by |tx_secret|. The length of secret is 32
- * bytes, and |tx_secret| must point to the buffer which has enough
- * capacity.
- *
- * If |initial_secret| is not NULL, the initial secret is written to
- * the buffer pointed by |initial_secret|. The length of secret is 32
- * bytes, and |initial_secret| must point to the buffer which has
- * enough capacity.
- *
- * |client_dcid| is the destination connection ID in first Initial
- * packet of client.
- *
- * If |rx_key| is not NULL, the derived packet protection key for
- * decryption is written to the buffer pointed by |rx_key|. If
- * |rx_iv| is not NULL, the derived packet protection IV for
- * decryption is written to the buffer pointed by |rx_iv|. If |rx_hp|
- * is not NULL, the derived header protection key for decryption is
- * written to the buffer pointed by |rx_hp|.
- *
- * If |tx_key| is not NULL, the derived packet protection key for
- * encryption is written to the buffer pointed by |tx_key|. If
- * |tx_iv| is not NULL, the derived packet protection IV for
- * encryption is written to the buffer pointed by |tx_iv|. If |tx_hp|
- * is not NULL, the derived header protection key for encryption is
- * written to the buffer pointed by |tx_hp|.
- *
- * The length of packet protection key and header protection key is 16
- * bytes long. The length of packet protection IV is 12 bytes long.
- *
- * This function calls `ngtcp2_conn_set_initial_crypto_ctx` to set
- * initial AEAD and message digest algorithm. After the successful
- * call of this function, application can use
- * `ngtcp2_conn_get_initial_crypto_ctx` to get the object.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_derive_and_install_initial_key(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- uint8_t *initial_secret, uint8_t *rx_key, uint8_t *rx_iv, uint8_t *rx_hp,
- uint8_t *tx_key, uint8_t *tx_iv, uint8_t *tx_hp,
- const ngtcp2_cid *client_dcid);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_cipher_ctx_encrypt_init` initializes |cipher_ctx|
- * with new cipher context object for encryption which is constructed
- * to use |key| as encryption key. |cipher| specifies cipher to use.
- *
- * This function returns 0 if it succeeds, or -1.
- */
-int ngtcp2_crypto_cipher_ctx_encrypt_init(ngtcp2_crypto_cipher_ctx *cipher_ctx,
- const ngtcp2_crypto_cipher *cipher,
- const uint8_t *key);
-
-/**
- * @function
- *
- * `ngtcp2_crypto_cipher_ctx_free` frees up resources used by
- * |cipher_ctx|. This function does not free the memory pointed by
- * |cipher_ctx| itself.
- */
-void ngtcp2_crypto_cipher_ctx_free(ngtcp2_crypto_cipher_ctx *cipher_ctx);
-
-#endif /* NGTCP2_SHARED_H */
diff --git a/deps/ngtcp2/lib/includes/config.h b/deps/ngtcp2/lib/includes/config.h
deleted file mode 100644
index 0aee7749ba..0000000000
--- a/deps/ngtcp2/lib/includes/config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-/* Edited to match src/node.h. */
-#include <stdint.h>
-
-#ifdef _WIN32
-#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
-typedef intptr_t ssize_t;
-# define _SSIZE_T_
-# define _SSIZE_T_DEFINED
-#endif
-#else // !_WIN32
-# include <sys/types.h> // size_t, ssize_t
-#endif // _WIN32
-
-#ifdef _MSC_VER
-# include <intrin.h>
-# define __builtin_popcount __popcnt
-#endif
-
-/* Define to 1 to enable debug output. */
-/* #undef DEBUGBUILD */
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-/* #undef HAVE_ARPA_INET_H */
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
diff --git a/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
deleted file mode 100644
index 3373adb9f9..0000000000
--- a/deps/ngtcp2/lib/includes/ngtcp2/ngtcp2.h
+++ /dev/null
@@ -1,3396 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2017 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_H
-#define NGTCP2_H
-
-/* Define WIN32 when build target is Win32 API (borrowed from
- libcurl) */
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-/* MSVC < 2013 does not have inttypes.h because it is not C99
- compliant. See compiler macros and version number in
- https://sourceforge.net/p/predef/wiki/Compilers/ */
-# include <stdint.h>
-#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
-# include <inttypes.h>
-#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
-#include <sys/types.h>
-#include <stdarg.h>
-#include <stddef.h>
-
-#ifdef WIN32
-# include <winsock2.h>
-#else
-# include <sys/socket.h>
-#endif
-
-#include <ngtcp2/version.h>
-
-#ifdef NGTCP2_STATICLIB
-# define NGTCP2_EXTERN
-#elif defined(WIN32)
-# ifdef BUILDING_NGTCP2
-# define NGTCP2_EXTERN __declspec(dllexport)
-# else /* !BUILDING_NGTCP2 */
-# define NGTCP2_EXTERN __declspec(dllimport)
-# endif /* !BUILDING_NGTCP2 */
-#else /* !defined(WIN32) */
-# ifdef BUILDING_NGTCP2
-# define NGTCP2_EXTERN __attribute__((visibility("default")))
-# else /* !BUILDING_NGTCP2 */
-# define NGTCP2_EXTERN
-# endif /* !BUILDING_NGTCP2 */
-#endif /* !defined(WIN32) */
-
-typedef ptrdiff_t ngtcp2_ssize;
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace malloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`ngtcp2_mem` structure.
- */
-typedef void *(*ngtcp2_malloc)(size_t size, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace free(). The |mem_user_data| is
- * the mem_user_data member of :type:`ngtcp2_mem` structure.
- */
-typedef void (*ngtcp2_free)(void *ptr, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace calloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`ngtcp2_mem` structure.
- */
-typedef void *(*ngtcp2_calloc)(size_t nmemb, size_t size, void *mem_user_data);
-
-/**
- * @functypedef
- *
- * Custom memory allocator to replace realloc(). The |mem_user_data|
- * is the mem_user_data member of :type:`ngtcp2_mem` structure.
- */
-typedef void *(*ngtcp2_realloc)(void *ptr, size_t size, void *mem_user_data);
-
-/**
- * @struct
- *
- * Custom memory allocator functions and user defined pointer. The
- * |mem_user_data| member is passed to each allocator function. This
- * can be used, for example, to achieve per-session memory pool.
- *
- * In the following example code, ``my_malloc``, ``my_free``,
- * ``my_calloc`` and ``my_realloc`` are the replacement of the
- * standard allocators ``malloc``, ``free``, ``calloc`` and
- * ``realloc`` respectively::
- *
- * void *my_malloc_cb(size_t size, void *mem_user_data) {
- * return my_malloc(size);
- * }
- *
- * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); }
- *
- * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) {
- * return my_calloc(nmemb, size);
- * }
- *
- * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) {
- * return my_realloc(ptr, size);
- * }
- *
- * void conn_new() {
- * ngtcp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb,
- * my_realloc_cb};
- *
- * ...
- * }
- */
-typedef struct ngtcp2_mem {
- /**
- * An arbitrary user supplied data. This is passed to each
- * allocator function.
- */
- void *mem_user_data;
- /**
- * Custom allocator function to replace malloc().
- */
- ngtcp2_malloc malloc;
- /**
- * Custom allocator function to replace free().
- */
- ngtcp2_free free;
- /**
- * Custom allocator function to replace calloc().
- */
- ngtcp2_calloc calloc;
- /**
- * Custom allocator function to replace realloc().
- */
- ngtcp2_realloc realloc;
-} ngtcp2_mem;
-
-/* NGTCP2_PROTO_VER is the supported QUIC protocol version. */
-#define NGTCP2_PROTO_VER 0xff00001du
-/* NGTCP2_PROTO_VER_MAX is the highest QUIC version the library
- supports. */
-#define NGTCP2_PROTO_VER_MAX NGTCP2_PROTO_VER
-
-#define NGTCP2_MAX_PKTLEN_IPV4 1252
-#define NGTCP2_MAX_PKTLEN_IPV6 1232
-
-/* NGTCP2_MIN_INITIAL_PKTLEN is the minimum UDP packet size for a
- packet sent by client which contains its first Initial packet. */
-#define NGTCP2_MIN_INITIAL_PKTLEN 1200
-
-/* NGTCP2_DEFAULT_MAX_PKTLEN is the default maximum size of UDP
- datagram payload that this endpoint transmits. It is used by
- congestion controller to compute congestion window. */
-#define NGTCP2_DEFAULT_MAX_PKTLEN 1200
-
-/* NGTCP2_STATELESS_RESET_TOKENLEN is the length of Stateless Reset
- Token. */
-#define NGTCP2_STATELESS_RESET_TOKENLEN 16
-
-/* NGTCP2_MIN_STATELESS_RESET_RANDLEN is the minimum length of random
- bytes (Unpredictable Bits) in Stateless Retry packet */
-#define NGTCP2_MIN_STATELESS_RESET_RANDLEN 5
-
-/* NGTCP2_INITIAL_SALT is a salt value which is used to derive initial
- secret. */
-#define NGTCP2_INITIAL_SALT \
- "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97\x86\xf1\x9c\x61\x11\xe0\x43\x90" \
- "\xa8\x99"
-
-/* NGTCP2_RETRY_KEY is an encryption key to create integrity tag of
- Retry packet. */
-#define NGTCP2_RETRY_KEY \
- "\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1"
-
-/* NGTCP2_RETRY_NONCE is nonce used when generating integrity tag of
- Retry packet. */
-#define NGTCP2_RETRY_NONCE "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c"
-
-/* NGTCP2_HP_MASKLEN is the length of header protection mask. */
-#define NGTCP2_HP_MASKLEN 5
-
-/* NGTCP2_HP_SAMPLELEN is the number bytes sampled when encrypting a
- packet header. */
-#define NGTCP2_HP_SAMPLELEN 16
-
-/* NGTCP2_SECONDS is a count of tick which corresponds to 1 second. */
-#define NGTCP2_SECONDS ((uint64_t)1000000000ULL)
-
-/* NGTCP2_MILLISECONDS is a count of tick which corresponds to 1
- millisecond. */
-#define NGTCP2_MILLISECONDS ((uint64_t)1000000ULL)
-
-/* NGTCP2_MICROSECONDS is a count of tick which corresponds to 1
- microsecond. */
-#define NGTCP2_MICROSECONDS ((uint64_t)1000ULL)
-
-/* NGTCP2_NANOSECONDS is a count of tick which corresponds to 1
- nanosecond. */
-#define NGTCP2_NANOSECONDS ((uint64_t)1ULL)
-
-/* NGTCP2_DEFAULT_INITIAL_RTT is a default initial RTT. */
-#define NGTCP2_DEFAULT_INITIAL_RTT (333 * NGTCP2_MILLISECONDS)
-
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_lib_error : int {
-#else
-typedef enum ngtcp2_lib_error {
-#endif
- NGTCP2_ERR_INVALID_ARGUMENT = -201,
- NGTCP2_ERR_UNKNOWN_PKT_TYPE = -202,
- NGTCP2_ERR_NOBUF = -203,
- NGTCP2_ERR_PROTO = -205,
- NGTCP2_ERR_INVALID_STATE = -206,
- NGTCP2_ERR_ACK_FRAME = -207,
- NGTCP2_ERR_STREAM_ID_BLOCKED = -208,
- NGTCP2_ERR_STREAM_IN_USE = -209,
- NGTCP2_ERR_STREAM_DATA_BLOCKED = -210,
- NGTCP2_ERR_FLOW_CONTROL = -211,
- NGTCP2_ERR_CONNECTION_ID_LIMIT = -212,
- NGTCP2_ERR_STREAM_LIMIT = -213,
- NGTCP2_ERR_FINAL_SIZE = -214,
- NGTCP2_ERR_CRYPTO = -215,
- NGTCP2_ERR_PKT_NUM_EXHAUSTED = -216,
- NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM = -217,
- NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM = -218,
- NGTCP2_ERR_FRAME_ENCODING = -219,
- NGTCP2_ERR_TLS_DECRYPT = -220,
- NGTCP2_ERR_STREAM_SHUT_WR = -221,
- NGTCP2_ERR_STREAM_NOT_FOUND = -222,
- NGTCP2_ERR_STREAM_STATE = -226,
- NGTCP2_ERR_RECV_VERSION_NEGOTIATION = -229,
- NGTCP2_ERR_CLOSING = -230,
- NGTCP2_ERR_DRAINING = -231,
- NGTCP2_ERR_TRANSPORT_PARAM = -234,
- NGTCP2_ERR_DISCARD_PKT = -235,
- NGTCP2_ERR_PATH_VALIDATION_FAILED = -236,
- NGTCP2_ERR_CONN_ID_BLOCKED = -237,
- NGTCP2_ERR_INTERNAL = -238,
- NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED = -239,
- NGTCP2_ERR_WRITE_MORE = -240,
- NGTCP2_ERR_RETRY = -241,
- NGTCP2_ERR_DROP_CONN = -242,
- NGTCP2_ERR_FATAL = -500,
- NGTCP2_ERR_NOMEM = -501,
- NGTCP2_ERR_CALLBACK_FAILURE = -502,
-} ngtcp2_lib_error;
-
-typedef enum ngtcp2_pkt_flag {
- NGTCP2_PKT_FLAG_NONE = 0,
- NGTCP2_PKT_FLAG_LONG_FORM = 0x01,
- NGTCP2_PKT_FLAG_KEY_PHASE = 0x04
-} ngtcp2_pkt_flag;
-
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_pkt_type : int {
-#else
-typedef enum ngtcp2_pkt_type {
-#endif
- /* NGTCP2_PKT_VERSION_NEGOTIATION is defined by libngtcp2 for
- convenience. */
- NGTCP2_PKT_VERSION_NEGOTIATION = 0xf0,
- NGTCP2_PKT_INITIAL = 0x0,
- NGTCP2_PKT_0RTT = 0x1,
- NGTCP2_PKT_HANDSHAKE = 0x2,
- NGTCP2_PKT_RETRY = 0x3,
- /* NGTCP2_PKT_SHORT is defined by libngtcp2 for convenience. */
- NGTCP2_PKT_SHORT = 0x70
-} ngtcp2_pkt_type;
-
-/* QUIC transport error code. */
-#define NGTCP2_NO_ERROR 0x0u
-#define NGTCP2_INTERNAL_ERROR 0x1u
-#define NGTCP2_CONNECTION_REFUSED 0x2u
-#define NGTCP2_FLOW_CONTROL_ERROR 0x3u
-#define NGTCP2_STREAM_LIMIT_ERROR 0x4u
-#define NGTCP2_STREAM_STATE_ERROR 0x5u
-#define NGTCP2_FINAL_SIZE_ERROR 0x6u
-#define NGTCP2_FRAME_ENCODING_ERROR 0x7u
-#define NGTCP2_TRANSPORT_PARAMETER_ERROR 0x8u
-#define NGTCP2_CONNECTION_ID_LIMIT_ERROR 0x9u
-#define NGTCP2_PROTOCOL_VIOLATION 0xau
-#define NGTCP2_INVALID_TOKEN 0xbu
-#define NGTCP2_APPLICATION_ERROR 0xcu
-#define NGTCP2_CRYPTO_BUFFER_EXCEEDED 0xdu
-#define NGTCP2_KEY_UPDATE_ERROR 0xeu
-#define NGTCP2_CRYPTO_ERROR 0x100u
-
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_path_validation_result : int {
-#else
-typedef enum ngtcp2_path_validation_result {
-#endif
- NGTCP2_PATH_VALIDATION_RESULT_SUCCESS,
- NGTCP2_PATH_VALIDATION_RESULT_FAILURE,
-} ngtcp2_path_validation_result;
-
-/*
- * ngtcp2_tstamp is a timestamp with nanosecond resolution.
- */
-typedef uint64_t ngtcp2_tstamp;
-
-/*
- * ngtcp2_duration is a period of time in nanosecond resolution.
- */
-typedef uint64_t ngtcp2_duration;
-
-/* NGTCP2_MAX_CIDLEN is the maximum length of Connection ID. */
-#define NGTCP2_MAX_CIDLEN 20
-/* NGTCP2_MIN_CIDLEN is the minimum length of Connection ID. */
-#define NGTCP2_MIN_CIDLEN 1
-
-/* NGTCP2_MIN_INITIAL_DCIDLEN is the minimum length of Destination
- Connection ID in Client Initial packet if it does not bear token
- from Retry packet. */
-#define NGTCP2_MIN_INITIAL_DCIDLEN 8
-
-/**
- * @struct
- *
- * ngtcp2_cid holds a Connection ID.
- */
-typedef struct ngtcp2_cid {
- size_t datalen;
- uint8_t data[NGTCP2_MAX_CIDLEN];
-} ngtcp2_cid;
-
-/**
- * @struct
- *
- * ngtcp2_vec is struct iovec compatible structure to reference
- * arbitrary array of bytes.
- */
-typedef struct ngtcp2_vec {
- /* base points to the data. */
- uint8_t *base;
- /* len is the number of bytes which the buffer pointed by base
- contains. */
- size_t len;
-} ngtcp2_vec;
-
-/**
- * @function
- *
- * `ngtcp2_cid_init` initializes Connection ID |cid| with the byte
- * string pointed by |data| and its length is |datalen|. |datalen|
- * must be at least :enum:`NGTCP2_MIN_CIDLEN`, and at most
- * :enum:`NGTCP2_MAX_CIDLEN`.
- */
-NGTCP2_EXTERN void ngtcp2_cid_init(ngtcp2_cid *cid, const uint8_t *data,
- size_t datalen);
-
-typedef struct ngtcp2_pkt_hd {
- ngtcp2_cid dcid;
- ngtcp2_cid scid;
- int64_t pkt_num;
- ngtcp2_vec token;
- /**
- * pkt_numlen is the number of bytes spent to encode pkt_num.
- */
- size_t pkt_numlen;
- /**
- * len is the sum of pkt_numlen and the length of QUIC packet
- * payload.
- */
- size_t len;
- uint32_t version;
- uint8_t type;
- uint8_t flags;
-} ngtcp2_pkt_hd;
-
-typedef struct ngtcp2_pkt_stateless_reset {
- uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
- const uint8_t *rand;
- size_t randlen;
-} ngtcp2_pkt_stateless_reset;
-
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_transport_param_id : int {
-#else
-typedef enum ngtcp2_transport_param_id {
-#endif
- NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID = 0x0000,
- NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT = 0x0001,
- NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN = 0x0002,
- NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE = 0x0003,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA = 0x0004,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL = 0x0005,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE = 0x0006,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI = 0x0007,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI = 0x0008,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI = 0x0009,
- NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT = 0x000a,
- NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY = 0x000b,
- NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION = 0x000c,
- NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS = 0x000d,
- NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT = 0x000e,
- NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID = 0x000f,
- NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID = 0x0010
-} ngtcp2_transport_param_id;
-
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_transport_params_type : int {
-#else
-typedef enum ngtcp2_transport_params_type {
-#endif
- NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
- NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS
-} ngtcp2_transport_params_type;
-
-/**
- * @enum
- *
- * ngtcp2_rand_ctx is a context where generated random value is used.
- */
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_rand_ctx : int {
-#else
-typedef enum ngtcp2_rand_ctx {
-#endif
- NGTCP2_RAND_CTX_NONE,
- /**
- * NGTCP2_RAND_CTX_PATH_CHALLENGE indicates that random value is
- * used for PATH_CHALLENGE.
- */
- NGTCP2_RAND_CTX_PATH_CHALLENGE
-} ngtcp2_rand_ctx;
-
-/*
- * NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE is the default value of
- * max_udp_payload_size transport parameter.
- */
-#define NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE 65527
-
-/**
- * @macro
- *
- * NGTCP2_DEFAULT_ACK_DELAY_EXPONENT is a default value of scaling
- * factor of ACK Delay field in ACK frame.
- */
-#define NGTCP2_DEFAULT_ACK_DELAY_EXPONENT 3
-
-/**
- * @macro
- *
- * NGTCP2_DEFAULT_MAX_ACK_DELAY is a default value of the maximum
- * amount of time in nanoseconds by which endpoint delays sending
- * acknowledgement.
- */
-#define NGTCP2_DEFAULT_MAX_ACK_DELAY (25 * NGTCP2_MILLISECONDS)
-
-/**
- * @macro
- *
- * NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT is the default value of
- * active_connection_id_limit transport parameter value if omitted.
- */
-#define NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT 2
-
-/**
- * @macro
- *
- * NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS is TLS extension type of
- * quic_transport_parameters.
- */
-#define NGTCP2_TLSEXT_QUIC_TRANSPORT_PARAMETERS 0xffa5u
-
-typedef struct ngtcp2_preferred_addr {
- ngtcp2_cid cid;
- uint16_t ipv4_port;
- uint16_t ipv6_port;
- uint8_t ipv4_addr[4];
- uint8_t ipv6_addr[16];
- uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
-} ngtcp2_preferred_addr;
-
-typedef struct ngtcp2_transport_params {
- ngtcp2_preferred_addr preferred_address;
- /* original_dcid is the Destination Connection ID field from the
- first Initial packet from client. Server must specify this
- field. It is expected that application knows the original
- Destination Connection ID even if it sends Retry packet, for
- example, by including it in retry token. Otherwise, application
- should not specify this field. */
- ngtcp2_cid original_dcid;
- /* initial_scid is the Source Connection ID field from the first
- Initial packet the endpoint sends. Application should not
- specify this field. */
- ngtcp2_cid initial_scid;
- /* retry_scid is the Source Connection ID field from Retry packet.
- Only server uses this field. If server application received
- Initial packet with retry token from client and server verified
- its token, server application must set Destination Connection ID
- field from the Initial packet to this field and set
- retry_scid_present to nonzero. Server application must verify
- that the Destination Connection ID from Initial packet was sent
- in Retry packet by, for example, including the Connection ID in a
- token, or including it in AAD when encrypting a token. */
- ngtcp2_cid retry_scid;
- /* initial_max_stream_data_bidi_local is the size of flow control
- window of locally initiated stream. This is the number of bytes
- that the remote endpoint can send and the local endpoint must
- ensure that it has enough buffer to receive them. */
- uint64_t initial_max_stream_data_bidi_local;
- /* initial_max_stream_data_bidi_remote is the size of flow control
- window of remotely initiated stream. This is the number of bytes
- that the remote endpoint can send and the local endpoint must
- ensure that it has enough buffer to receive them. */
- uint64_t initial_max_stream_data_bidi_remote;
- /* initial_max_stream_data_uni is the size of flow control window of
- remotely initiated unidirectional stream. This is the number of
- bytes that the remote endpoint can send and the local endpoint
- must ensure that it has enough buffer to receive them. */
- uint64_t initial_max_stream_data_uni;
- /* initial_max_data is the connection level flow control window. */
- uint64_t initial_max_data;
- /* initial_max_streams_bidi is the number of concurrent streams that
- the remote endpoint can create. */
- uint64_t initial_max_streams_bidi;
- /* initial_max_streams_uni is the number of concurrent
- unidirectional streams that the remote endpoint can create. */
- uint64_t initial_max_streams_uni;
- /* max_idle_timeout is a duration during which sender allows
- quiescent. */
- ngtcp2_duration max_idle_timeout;
- uint64_t max_udp_payload_size;
- /* active_connection_id_limit is the maximum number of Connection ID
- that sender can store. */
- uint64_t active_connection_id_limit;
- uint64_t ack_delay_exponent;
- ngtcp2_duration max_ack_delay;
- uint8_t stateless_reset_token_present;
- uint8_t disable_active_migration;
- uint8_t retry_scid_present;
- uint8_t preferred_address_present;
- uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
-} ngtcp2_transport_params;
-
-typedef struct ngtcp2_log ngtcp2_log;
-
-typedef enum ngtcp2_pktns_id {
- /* NGTCP2_PKTNS_ID_INITIAL is the Initial packet number space. */
- NGTCP2_PKTNS_ID_INITIAL,
- /* NGTCP2_PKTNS_ID_INITIAL is the Handshake packet number space. */
- NGTCP2_PKTNS_ID_HANDSHAKE,
- /* NGTCP2_PKTNS_ID_INITIAL is the Application data packet number
- space. */
- NGTCP2_PKTNS_ID_APP,
- /* NGTCP2_PKTNS_ID_MAX is defined to get the number of packet number
- spaces. */
- NGTCP2_PKTNS_ID_MAX
-} ngtcp2_pktns_id;
-
-/**
- * @struct
- *
- * ngtcp2_conn_stat holds various connection statistics, and computed
- * data for recovery and congestion controller.
- */
-typedef struct ngtcp2_conn_stat {
- ngtcp2_duration latest_rtt;
- ngtcp2_duration min_rtt;
- ngtcp2_duration smoothed_rtt;
- ngtcp2_duration rttvar;
- ngtcp2_duration initial_rtt;
- size_t pto_count;
- ngtcp2_tstamp loss_detection_timer;
- /* last_tx_pkt_ts corresponds to
- time_of_last_sent_ack_eliciting_packet in
- draft-ietf-quic-recovery-25. */
- ngtcp2_tstamp last_tx_pkt_ts[NGTCP2_PKTNS_ID_MAX];
- ngtcp2_tstamp loss_time[NGTCP2_PKTNS_ID_MAX];
- uint64_t cwnd;
- uint64_t ssthresh;
- ngtcp2_tstamp congestion_recovery_start_ts;
- uint64_t bytes_in_flight;
- /* max_udp_payload_size is the maximum size of UDP datagram payload
- that this endpoint transmits. It is used by congestion
- controller to compute congestion window. */
- size_t max_udp_payload_size;
- /* bytes_sent is the number of bytes sent in this particular
- connection. It only includes data written by
- `ngtcp2_conn_writev_stream()` .*/
- uint64_t bytes_sent;
- /* bytes_recv is the number of bytes received in this particular
- connection, including discarded packets. */
- uint64_t bytes_recv;
- /* delivery_rate_sec is the current sending rate measured per
- second. */
- uint64_t delivery_rate_sec;
- /* recv_rate_sec is the current receiving rate of application data
- measured in per second. */
- uint64_t recv_rate_sec;
-} ngtcp2_conn_stat;
-
-typedef enum ngtcp2_cc_algo {
- NGTCP2_CC_ALGO_RENO = 0x00,
- NGTCP2_CC_ALGO_CUBIC = 0x01,
- NGTCP2_CC_ALGO_CUSTOM = 0xff
-} ngtcp2_cc_algo;
-
-typedef struct ngtcp2_cc_base {
- ngtcp2_log *log;
-} ngtcp2_cc_base;
-
-/* ngtcp2_cc_pkt is a convenient structure to include acked/lost/sent
- packet. */
-typedef struct {
- /* pkt_num is the packet number */
- int64_t pkt_num;
- /* pktlen is the length of packet. */
- size_t pktlen;
- /* pktns_id is the ID of packet number space which this packet
- belongs to. */
- ngtcp2_pktns_id pktns_id;
- /* ts_sent is the timestamp when packet is sent. */
- ngtcp2_tstamp ts_sent;
-} ngtcp2_cc_pkt;
-
-typedef struct ngtcp2_cc ngtcp2_cc;
-
-typedef void (*ngtcp2_cc_on_pkt_acked)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts);
-
-typedef void (*ngtcp2_cc_congestion_event)(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts_sent,
- ngtcp2_tstamp ts);
-
-typedef void (*ngtcp2_cc_on_persistent_congestion)(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-typedef void (*ngtcp2_cc_on_ack_recv)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-typedef void (*ngtcp2_cc_on_pkt_sent)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt);
-
-typedef void (*ngtcp2_cc_new_rtt_sample)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-typedef void (*ngtcp2_cc_reset)(ngtcp2_cc *cc);
-
-typedef enum ngtcp2_cc_event_type {
- /* NGTCP2_CC_EVENT_TX_START occurs when ack-eliciting packet is sent
- and no other ack-eliciting packet is present. */
- NGTCP2_CC_EVENT_TYPE_TX_START
-} ngtcp2_cc_event_type;
-
-typedef void (*ngtcp2_cc_event)(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
-
-typedef struct ngtcp2_cc {
- ngtcp2_cc_base *ccb;
- ngtcp2_cc_on_pkt_acked on_pkt_acked;
- ngtcp2_cc_congestion_event congestion_event;
- ngtcp2_cc_on_persistent_congestion on_persistent_congestion;
- ngtcp2_cc_on_ack_recv on_ack_recv;
- ngtcp2_cc_on_pkt_sent on_pkt_sent;
- ngtcp2_cc_new_rtt_sample new_rtt_sample;
- ngtcp2_cc_reset reset;
- ngtcp2_cc_event event;
-} ngtcp2_cc;
-
-/* user_data is the same object passed to ngtcp2_conn_client_new or
- ngtcp2_conn_server_new. */
-typedef void (*ngtcp2_printf)(void *user_data, const char *format, ...);
-
-/**
- * @enum
- *
- * :type:`ngtcp2_qlog_write_flag` defines the set of flags passed to
- * :type:`ngtcp2_qlog_write` callback.
- */
-typedef enum ngtcp2_qlog_write_flag {
- NGTCP2_QLOG_WRITE_FLAG_NONE = 0,
- /**
- * NGTCP2_QLOG_WRITE_FLAG_FIN indicates that this is the final call
- * to :type:`ngtcp2_qlog_write` in the current connection.
- */
- NGTCP2_QLOG_WRITE_FLAG_FIN = 0x01
-} ngtcp2_qlog_write_flag;
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_qlog_write` is a callback function which is called to
- * write qlog |data| of length |datalen| bytes. |flags| is bitwise OR
- * of zero or more of :type:`ngtcp2_qlog_write_flag`.
- */
-typedef void (*ngtcp2_qlog_write)(void *user_data, uint32_t flags,
- const void *data, size_t datalen);
-
-typedef struct ngtcp2_qlog_settings {
- /* odcid is Original Destination Connection ID sent by client. It
- is used as group_id and ODCID fields. Client ignores this field
- and uses dcid parameter passed to `ngtcp2_conn_client_new()`. */
- ngtcp2_cid odcid;
- /* write is a callback function to write qlog. Setting NULL
- disables qlog. */
- ngtcp2_qlog_write write;
-} ngtcp2_qlog_settings;
-
-typedef struct ngtcp2_settings {
- /* transport_params is the QUIC transport parameters to send. */
- ngtcp2_transport_params transport_params;
- ngtcp2_qlog_settings qlog;
- ngtcp2_cc_algo cc_algo;
- ngtcp2_cc *cc;
- /* initial_ts is an initial timestamp given to the library. */
- ngtcp2_tstamp initial_ts;
- /* initial_rtt is an initial RTT. */
- ngtcp2_duration initial_rtt;
- /* log_printf is a function that the library uses to write logs.
- NULL means no logging output. */
- ngtcp2_printf log_printf;
- /* max_udp_payload_size is the maximum size of UDP datagram payload
- that this endpoint transmits. It is used by congestion
- controller to compute congestion window. If it is set to 0, it
- defaults to NGTCP2_DEFAULT_MAX_PKTLEN. */
- size_t max_udp_payload_size;
- /**
- * token is a token from Retry packet or NEW_TOKEN frame.
- *
- * Server sets this field if it received the token in Client Initial
- * packet and successfully validated.
- *
- * Client sets this field if it intends to send token in its Initial
- * packet.
- *
- * `ngtcp2_conn_server_new` and `ngtcp2_conn_client_new` make a copy
- * of token.
- */
- ngtcp2_vec token;
-} ngtcp2_settings;
-
-/**
- * @struct
- *
- * ngtcp2_addr is the endpoint address.
- */
-typedef struct ngtcp2_addr {
- /* addrlen is the length of addr. */
- size_t addrlen;
- /* addr points to the buffer which contains endpoint address. It
- must not be NULL. */
- struct sockaddr *addr;
- /* user_data is an arbitrary data and opaque to the library. */
- void *user_data;
-} ngtcp2_addr;
-
-/**
- * @struct
- *
- * ngtcp2_path is the network endpoints where a packet is sent and
- * received.
- */
-typedef struct ngtcp2_path {
- /* local is the address of local endpoint. */
- ngtcp2_addr local;
- /* remote is the address of remote endpoint. */
- ngtcp2_addr remote;
-} ngtcp2_path;
-
-/**
- * @struct
- *
- * ngtcp2_path_storage is a convenient struct to have buffers to store
- * the longest addresses.
- */
-typedef struct ngtcp2_path_storage {
- struct sockaddr_storage local_addrbuf;
- struct sockaddr_storage remote_addrbuf;
- ngtcp2_path path;
-} ngtcp2_path_storage;
-
-/**
- * @struct
- *
- * `ngtcp2_crypto_md` is a wrapper around native message digest
- * object.
- *
- * If libngtcp2_crypto_openssl is linked, native_handle must be a
- * pointer to EVP_MD.
- */
-typedef struct ngtcp2_crypto_md {
- void *native_handle;
-} ngtcp2_crypto_md;
-
-/**
- * @struct
- *
- * `ngtcp2_crypto_aead` is a wrapper around native AEAD object.
- *
- * If libngtcp2_crypto_openssl is linked, native_handle must be a
- * pointer to EVP_CIPHER.
- */
-typedef struct ngtcp2_crypto_aead {
- void *native_handle;
-} ngtcp2_crypto_aead;
-
-/**
- * @struct
- *
- * `ngtcp2_crypto_cipher` is a wrapper around native cipher object.
- *
- * If libngtcp2_crypto_openssl is linked, native_handle must be a
- * pointer to EVP_CIPHER.
- */
-typedef struct ngtcp2_crypto_cipher {
- void *native_handle;
-} ngtcp2_crypto_cipher;
-
-/**
- * @struct
- *
- * `ngtcp2_crypto_aead_ctx` is a wrapper around native AEAD cipher
- * context object. It should be initialized with a specific key.
- * ngtcp2 library reuses this context object to encrypt or decrypt
- * multiple packets.
- */
-typedef struct ngtcp2_crypto_aead_ctx {
- void *native_handle;
-} ngtcp2_crypto_aead_ctx;
-
-/**
- * @struct
- *
- * `ngtcp2_crypto_cipher_ctx` is a wrapper around native cipher
- * context object. It should be initialized with a specific key.
- * ngtcp2 library reuses this context object to encrypt or decrypt
- * multiple packet headers.
- */
-typedef struct ngtcp2_crypto_cipher_ctx {
- void *native_handle;
-} ngtcp2_crypto_cipher_ctx;
-
-/**
- * @function
- *
- * `ngtcp2_crypto_ctx` is a convenient structure to bind all crypto
- * related objects in one place. Use `ngtcp2_crypto_ctx_initial` to
- * initialize this struct for Initial packet encryption. For
- * Handshake and Shortpackets, use `ngtcp2_crypto_ctx_tls`.
- */
-typedef struct ngtcp2_crypto_ctx {
- ngtcp2_crypto_aead aead;
- ngtcp2_crypto_md md;
- ngtcp2_crypto_cipher hp;
- /* max_encryption is the number of encryption which this key can be
- used with. */
- uint64_t max_encryption;
- /* max_decryption_failure is the number of decryption failure with
- this key. */
- uint64_t max_decryption_failure;
-} ngtcp2_crypto_ctx;
-
-/**
- * @function
- *
- * `ngtcp2_encode_transport_params` encodes |params| in |dest| of
- * length |destlen|.
- *
- * This function returns the number of written, or one of the
- * following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small.
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`:
- * |exttype| is invalid.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_encode_transport_params(
- uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype,
- const ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_decode_transport_params` decodes transport parameters in
- * |data| of length |datalen|, and stores the result in the object
- * pointed by |params|.
- *
- * If the optional parameters are missing, the default value is
- * assigned.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM`
- * The required parameter is missing.
- * :enum:`NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM`
- * The input is malformed.
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`:
- * |exttype| is invalid.
- */
-NGTCP2_EXTERN int
-ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
- ngtcp2_transport_params_type exttype,
- const uint8_t *data, size_t datalen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_decode_version_cid` extracts QUIC version, Destination
- * Connection ID and Source Connection ID from the packet pointed by
- * |data| of length |datalen|. This function can handle Connection ID
- * up to 255 bytes unlike `ngtcp2_pkt_decode_hd_long` or
- * `ngtcp2_pkt_decode_hd_short` which are only capable of handling
- * Connection ID less than or equal to :macro:`NGTCP2_MAX_CIDLEN`.
- * Longer Connection ID is only valid if the version is unsupported
- * QUIC version.
- *
- * If the given packet is Long packet, this function extracts the
- * version from the packet and assigns it to |*pversion|. It also
- * extracts the pointer to the Destination Connection ID and its
- * length and assigns them to |*pdcid| and |*pdcidlen| respectively.
- * Similarly, it extracts the pointer to the Source Connection ID and
- * its length and assigns them to |*pscid| and |*pscidlen|
- * respectively.
- *
- * If the given packet is Short packet, |*pversion| will be
- * :macro:`NGTCP2_PROTO_VER`, |*pscid| will be NULL, and |*pscidlen|
- * will be 0. Because the Short packet does not have the length of
- * Destination Connection ID, the caller has to pass the length in
- * |short_dcidlen|. This function extracts the pointer to the
- * Destination Connection ID and assigns it to |*pdcid|.
- * |short_dcidlen| is assigned to |*pdcidlen|.
- *
- * This function returns 0 or 1 if it succeeds. It returns 1 if
- * Version Negotiation packet should be sent. Otherwise, one of the
- * following negative error code:
- *
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`
- * The function could not decode the packet header.
- */
-NGTCP2_EXTERN int
-ngtcp2_pkt_decode_version_cid(uint32_t *pversion, const uint8_t **pdcid,
- size_t *pdcidlen, const uint8_t **pscid,
- size_t *pscidlen, const uint8_t *data,
- size_t datalen, size_t short_dcidlen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_decode_hd_long` decodes QUIC long packet header in
- * |pkt| of length |pktlen|. This function only parses the input just
- * before packet number field.
- *
- * This function does not verify that length field is correct. In
- * other words, this function succeeds even if length > |pktlen|.
- *
- * This function can handle Connection ID up to
- * :enum:`NGTCP2_MAX_CIDLEN`. Consider to use
- * `ngtcp2_pkt_decode_version_cid` to get longer Connection ID.
- *
- * This function handles Version Negotiation specially. If version
- * field is 0, |pkt| must contain Version Negotiation packet. Version
- * Negotiation packet has random type in wire format. For
- * convenience, this function sets
- * :enum:`NGTCP2_PKT_VERSION_NEGOTIATION` to dest->type, and set
- * dest->payloadlen and dest->pkt_num to 0. Version Negotiation
- * packet occupies a single packet.
- *
- * It stores the result in the object pointed by |dest|, and returns
- * the number of bytes decoded to read the packet header if it
- * succeeds, or one of the following error codes:
- *
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`
- * Packet is too short; or it is not a long header
- * :enum:`NGTCP2_ERR_UNKNOWN_PKT_TYPE`
- * Packet type is unknown
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest,
- const uint8_t *pkt,
- size_t pktlen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_decode_hd_short` decodes QUIC short packet header in
- * |pkt| of length |pktlen|. |dcidlen| is the length of DCID in
- * packet header. Short packet does not encode the length of
- * connection ID, thus we need the input from the outside. This
- * function only parses the input just before packet number field.
- * This function can handle Connection ID up to
- * :enum:`NGTCP2_MAX_CIDLEN`. Consider to use
- * `ngtcp2_pkt_decode_version_cid` to get longer Connection ID. It
- * stores the result in the object pointed by |dest|, and returns the
- * number of bytes decoded to read the packet header if it succeeds,
- * or one of the following error codes:
- *
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`
- * Packet is too short; or it is not a short header
- * :enum:`NGTCP2_ERR_UNKNOWN_PKT_TYPE`
- * Packet type is unknown
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest,
- const uint8_t *pkt,
- size_t pktlen,
- size_t dcidlen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_write_stateless_reset` writes Stateless Reset packet in
- * the buffer pointed by |dest| whose length is |destlen|.
- * |stateless_reset_token| is a pointer to the Stateless Reset Token,
- * and its length must be :macro:`NGTCP2_STATELESS_RESET_TOKENLEN`
- * bytes long. |rand| specifies the random octets preceding Stateless
- * Reset Token. The length of |rand| is specified by |randlen| which
- * must be at least :macro:`NGTCP2_MIN_STATELESS_RETRY_RANDLEN` bytes
- * long.
- *
- * If |randlen| is too long to write them all in the buffer, |rand| is
- * written to the buffer as much as possible, and is truncated.
- *
- * This function returns the number of bytes written to the buffer, or
- * one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small.
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`
- * |randlen| is strictly less than
- * :macro:`NGTCP2_MIN_STATELESS_RETRY_RANDLEN`.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_stateless_reset(
- uint8_t *dest, size_t destlen, const uint8_t *stateless_reset_token,
- const uint8_t *rand, size_t randlen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_write_version_negotiation` writes Version Negotiation
- * packet in the buffer pointed by |dest| whose length is |destlen|.
- * |unused_random| should be generated randomly. |dcid| is the
- * destination connection ID which appears in a packet as a source
- * connection ID sent by client which caused version negotiation.
- * Similarly, |scid| is the source connection ID which appears in a
- * packet as a destination connection ID sent by client. |sv| is a
- * list of supported versions, and |nsv| specifies the number of
- * supported versions included in |sv|.
- *
- * This function returns the number of bytes written to the buffer, or
- * one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_version_negotiation(
- uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid,
- size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv,
- size_t nsv);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_get_type_long` returns the long packet type. |c| is
- * the first byte of Long packet header.
- */
-NGTCP2_EXTERN uint8_t ngtcp2_pkt_get_type_long(uint8_t c);
-
-struct ngtcp2_conn;
-
-typedef struct ngtcp2_conn ngtcp2_conn;
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_client_initial` is invoked when client application
- * asks TLS stack to produce first TLS cryptographic handshake data.
- *
- * This implementation of this callback must get the first handshake
- * data from TLS stack and pass it to ngtcp2 library using
- * `ngtcp2_conn_submit_crypto_data` function. Make sure that before
- * calling `ngtcp2_conn_submit_crypto_data` function, client
- * application must create initial packet protection keys and IVs, and
- * provide them to ngtcp2 library using `ngtcp2_conn_set_initial_key`
- * and
- *
- * This callback function must return 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library call
- * return immediately.
- *
- * TODO: Define error code for TLS stack failure. Suggestion:
- * NGTCP2_ERR_CRYPTO.
- */
-typedef int (*ngtcp2_client_initial)(ngtcp2_conn *conn, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_client_initial` is invoked when server receives
- * Initial packet from client. An server application must implement
- * this callback, and generate initial keys and IVs for both
- * transmission and reception. Install them using
- * `ngtcp2_conn_set_initial_key`. |dcid| is the destination
- * connection ID which client generated randomly. It is used to
- * derive initial packet protection keys.
- *
- * The callback function must return 0 if it succeeds. If an error
- * occurs, return :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the
- * library call return immediately.
- *
- * TODO: Define error code for TLS stack failure. Suggestion:
- * NGTCP2_ERR_CRYPTO.
- */
-typedef int (*ngtcp2_recv_client_initial)(ngtcp2_conn *conn,
- const ngtcp2_cid *dcid,
- void *user_data);
-
-/**
- * @enum
- *
- * ngtcp2_crypto_level is encryption level.
- */
-#if defined(__cplusplus) && __cplusplus >= 201103L
-typedef enum ngtcp2_crypto_level : int {
-#else
-typedef enum ngtcp2_crypto_level {
-#endif
- /**
- * NGTCP2_CRYPTO_LEVEL_INITIAL is Initial Keys encryption level.
- */
- NGTCP2_CRYPTO_LEVEL_INITIAL,
- /**
- * NGTCP2_CRYPTO_LEVEL_HANDSHAKE is Handshake Keys encryption level.
- */
- NGTCP2_CRYPTO_LEVEL_HANDSHAKE,
- /**
- * NGTCP2_CRYPTO_LEVEL_APP is Application Data (1-RTT) Keys
- * encryption level.
- */
- NGTCP2_CRYPTO_LEVEL_APP,
- /**
- * NGTCP2_CRYPTO_LEVEL_EARLY is Early Data (0-RTT) Keys encryption
- * level.
- */
- NGTCP2_CRYPTO_LEVEL_EARLY
-} ngtcp2_crypto_level;
-
-/**
- * @functypedef
- *
- * :type`ngtcp2_recv_crypto_data` is invoked when crypto data is
- * received. The received data is pointed to by |data|, and its length
- * is |datalen|. The |offset| specifies the offset where |data| is
- * positioned. |user_data| is the arbitrary pointer passed to
- * `ngtcp2_conn_client_new` or `ngtcp2_conn_server_new`. The ngtcp2
- * library ensures that the crypto data is passed to the application
- * in the increasing order of |offset|. |datalen| is always strictly
- * greater than 0. |crypto_level| indicates the encryption level
- * where this data is received. Crypto data can never be received in
- * :enum:`NGTCP2_CRYPTO_LEVEL_EARLY`.
- *
- * The application should provide the given data to TLS stack.
- *
- * The callback function must return 0 if it succeeds. If TLS stack
- * reported error, return :enum:`NGTCP2_ERR_CRYPTO`. If application
- * encounters fatal error, return :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
- * which makes the library call return immediately. If the other
- * value is returned, it is treated as
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`.
- */
-typedef int (*ngtcp2_recv_crypto_data)(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset, const uint8_t *data,
- size_t datalen, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_handshake_completed` is invoked when QUIC
- * cryptographic handshake has completed.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_handshake_completed)(ngtcp2_conn *conn, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_handshake_confirmed` is invoked when QUIC
- * cryptographic handshake is confirmed. The handshake confirmation
- * means that both endpoints agree that handshake has finished.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_handshake_confirmed)(ngtcp2_conn *conn, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_version_negotiation` is invoked when Version
- * Negotiation packet is received. |hd| is the pointer to the QUIC
- * packet header object. The vector |sv| of |nsv| elements contains
- * the QUIC version the server supports. Since Version Negotiation is
- * only sent by server, this callback function is used by client only.
- *
- * The callback function must return 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library call
- * return immediately.
- */
-typedef int (*ngtcp2_recv_version_negotiation)(ngtcp2_conn *conn,
- const ngtcp2_pkt_hd *hd,
- const uint32_t *sv, size_t nsv,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_retry` is invoked when Retry packet is received.
- * This callback is client only.
- *
- * Application must regenerate packet protection key, IV, and header
- * protection key for Initial packets using the destination connection
- * ID obtained by `ngtcp2_conn_get_dcid()` and install them by calling
- * `ngtcp2_conn_install_initial_key()`.
- *
- * 0-RTT data accepted by the ngtcp2 library will be retransmitted by
- * the library automatically.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_recv_retry)(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_encrypt` is invoked when the ngtcp2 library asks the
- * application to encrypt packet payload. The packet payload to
- * encrypt is passed as |plaintext| of length |plaintextlen|. The
- * AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context
- * object which is initialized with encryption key. The nonce is
- * passed as |nonce| of length |noncelen|. The ad, Additional Data to
- * AEAD, is passed as |ad| of length |adlen|.
- *
- * The implementation of this callback must encrypt |plaintext| using
- * the negotiated cipher suite and write the ciphertext into the
- * buffer pointed by |dest|. |dest| has enough capacity to store the
- * ciphertext.
- *
- * |dest| and |plaintext| may point to the same buffer.
- *
- * The callback function must return 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library call
- * return immediately.
- */
-typedef int (*ngtcp2_encrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *plaintext, size_t plaintextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_decrypt` is invoked when the ngtcp2 library asks the
- * application to decrypt packet payload. The packet payload to
- * decrypt is passed as |ciphertext| of length |ciphertextlen|. The
- * AEAD cipher is |aead|. |aead_ctx| is the AEAD cipher context
- * object which is initialized with decryption key. The nonce is
- * passed as |nonce| of length |noncelen|. The ad, Additional Data to
- * AEAD, is passed as |ad| of length |adlen|.
- *
- * The implementation of this callback must decrypt |ciphertext| using
- * the negotiated cipher suite and write the ciphertext into the
- * buffer pointed by |dest|. |dest| has enough capacity to store the
- * cleartext.
- *
- * |dest| and |ciphertext| may point to the same buffer.
- *
- * The callback function must return 0 if it succeeds. If TLS stack
- * fails to decrypt data, return :enum:`NGTCP2_ERR_TLS_DECRYPT`. For
- * any other errors, return :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which
- * makes the library call return immediately.
- */
-typedef int (*ngtcp2_decrypt)(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *ciphertext, size_t ciphertextlen,
- const uint8_t *nonce, size_t noncelen,
- const uint8_t *ad, size_t adlen);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_hp_mask` is invoked when the ngtcp2 library asks the
- * application to produce mask to encrypt or decrypt packet header.
- * The encryption cipher is |hp|. |hp_ctx| is the cipher context
- * object which is initialized with header protection key. The sample
- * is passed as |sample|.
- *
- * The implementation of this callback must produce a mask using the
- * header protection cipher suite specified by QUIC specification and
- * write the result into the buffer pointed by |dest|. The length of
- * mask must be :macro:`NGTCP2_HP_MASKLEN`. The library ensures that
- * |dest| has enough capacity.
- *
- * The callback function must return 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library call
- * return immediately.
- */
-typedef int (*ngtcp2_hp_mask)(uint8_t *dest, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- const uint8_t *sample);
-
-/**
- * @enum
- *
- * ngtcp2_stream_data_flag defines the properties of the data emitted
- * via :type:`ngtcp2_recv_stream_data` callback function.
- */
-typedef enum ngtcp2_stream_data_flag {
- NGTCP2_STREAM_DATA_FLAG_NONE = 0x00,
- /**
- * NGTCP2_STREAM_DATA_FLAG_FIN indicates that this chunk of data is
- * final piece of an incoming stream.
- */
- NGTCP2_STREAM_DATA_FLAG_FIN = 0x01,
- /**
- * NGTCP2_STREAM_DATA_FLAG_0RTT indicates that this chunk of data
- * contains data received in 0RTT packet and the handshake has not
- * completed yet, which means that the data might be replayed.
- */
- NGTCP2_STREAM_DATA_FLAG_0RTT = 0x02
-} ngtcp2_stream_data_flag;
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_stream_data` is invoked when stream data is
- * received. The stream is specified by |stream_id|. |flags| is the
- * bitwise-OR of zero or more of ngtcp2_stream_data_flag. If |flags|
- * & :enum:`NGTCP2_STREAM_DATA_FLAG_FIN` is nonzero, this portion of
- * the data is the last data in this stream. |offset| is the offset
- * where this data begins. The library ensures that data is passed to
- * the application in the non-decreasing order of |offset|. The data
- * is passed as |data| of length |datalen|. |datalen| may be 0 if and
- * only if |fin| is nonzero.
- *
- * The callback function must return 0 if it succeeds, or
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` which makes the library return
- * immediately.
- */
-typedef int (*ngtcp2_recv_stream_data)(ngtcp2_conn *conn, uint32_t flags,
- int64_t stream_id, uint64_t offset,
- const uint8_t *data, size_t datalen,
- void *user_data, void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_stream_open` is a callback function which is called
- * when remote stream is opened by peer. This function is not called
- * if stream is opened by implicitly (we might reconsider this
- * behaviour).
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_stream_open)(ngtcp2_conn *conn, int64_t stream_id,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_stream_close` is invoked when a stream is closed.
- * This callback is not called when QUIC connection is closed before
- * existing streams are closed. |app_error_code| indicates the error
- * code of this closure.
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_stream_close)(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t app_error_code, void *user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_stream_reset` is invoked when a stream identified by
- * |stream_id| is reset by a remote endpoint.
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_stream_reset)(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t final_size, uint64_t app_error_code,
- void *user_data, void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_acked_stream_data_offset` is a callback function
- * which is called when stream data is acked, and application can free
- * the data. The acked range of data is [offset, offset + datalen).
- * For a given stream_id, this callback is called sequentially in
- * increasing order of |offset|. |datalen| is normally strictly
- * greater than 0. One exception is that when a packet which includes
- * STREAM frame which has fin flag set, and 0 length data, this
- * callback is invoked with 0 passed as |datalen|.
- *
- * If a stream is closed prematurely and stream data is still
- * in-flight, this callback function is not called for those data.
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_acked_stream_data_offset)(
- ngtcp2_conn *conn, int64_t stream_id, uint64_t offset, uint64_t datalen,
- void *user_data, void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_acked_crypto_offset` is a callback function which is
- * called when crypto stream data is acknowledged, and application can
- * free the data. |crypto_level| indicates the encryption level where
- * this data was sent. Crypto data never be sent in
- * :enum:`NGTCP2_CRYPTO_LEVEL_EARLY`. This works like
- * :type:`ngtcp2_acked_stream_data_offset` but crypto stream has no
- * stream_id and stream_user_data, and |datalen| never become 0.
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_acked_crypto_offset)(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset, uint64_t datalen,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_stateless_reset` is a callback function which is
- * called when Stateless Reset packet is received. The stateless
- * reset details are given in |sr|.
- *
- * The implementation of this callback should return 0 if it succeeds.
- * Returning :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library
- * call return immediately.
- */
-typedef int (*ngtcp2_recv_stateless_reset)(ngtcp2_conn *conn,
- const ngtcp2_pkt_stateless_reset *sr,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_extend_max_streams` is a callback function which is
- * called every time max stream ID is strictly extended.
- * |max_streams| is the cumulative number of streams which an endpoint
- * can open.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_extend_max_streams)(ngtcp2_conn *conn,
- uint64_t max_streams, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_extend_max_stream_data` is a callback function which
- * is invoked when max stream data is extended. |stream_id|
- * identifies the stream. |max_data| is a cumulative number of bytes
- * the endpoint can send on this stream.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_extend_max_stream_data)(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t max_data, void *user_data,
- void *stream_user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_rand` is a callback function to get randomized byte
- * string from application. Application must fill random |destlen|
- * bytes to the buffer pointed by |dest|. |ctx| provides the context
- * how the provided random byte string is used.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_rand)(uint8_t *dest, size_t destlen, ngtcp2_rand_ctx ctx);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_get_new_connection_id` is a callback function to ask
- * an application for new connection ID. Application must generate
- * new unused connection ID with the exact |cidlen| bytes and store it
- * in |cid|. It also has to generate stateless reset token into
- * |token|. The length of stateless reset token is
- * :macro:`NGTCP2_STATELESS_RESET_TOKENLEN` and it is guaranteed that
- * the buffer pointed by |cid| has the sufficient space to store the
- * token.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_get_new_connection_id)(ngtcp2_conn *conn, ngtcp2_cid *cid,
- uint8_t *token, size_t cidlen,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_remove_connection_id` is a callback function which
- * notifies the application that connection ID |cid| is no longer used
- * by remote endpoint.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_remove_connection_id)(ngtcp2_conn *conn,
- const ngtcp2_cid *cid,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_update_key` is a callback function which tells the
- * application that it must generate new packet protection keying
- * materials and AEAD cipher context objects with new keys. The
- * current set of secrets are given as |current_rx_secret| and
- * |current_tx_secret| of length |secretlen|. They are decryption and
- * encryption secrets respectively.
- *
- * The application has to generate new secrets and keys for both
- * encryption and decryption, and write decryption secret and IV to
- * the buffer pointed by |rx_secret| and |rx_iv| respectively. It
- * also has to create new AEAD cipher context object with new
- * decryption key and initialize |rx_aead_ctx| with it. Similarly,
- * write encryption secret and IV to the buffer pointed by |tx_secret|
- * and |tx_iv|. Create new AEAD cipher context object with new
- * encryption key and initialize |tx_aead_ctx| with it. All given
- * buffers have the enough capacity to store secret, key and IV.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_update_key)(
- ngtcp2_conn *conn, uint8_t *rx_secret, uint8_t *tx_secret,
- ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
- ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
- const uint8_t *current_rx_secret, const uint8_t *current_tx_secret,
- size_t secretlen, void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_path_validation` is a callback function which tells
- * the application the outcome of path validation. |path| is the path
- * that was validated. If |res| is
- * :enum:`NGTCP2_PATH_VALIDATION_RESULT_SUCCESS`, the path validation
- * succeeded. If |res| is
- * :enum:`NGTCP2_PATH_VALIDATION_RESULT_FAILURE`, the path validation
- * failed.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_path_validation)(ngtcp2_conn *conn,
- const ngtcp2_path *path,
- ngtcp2_path_validation_result res,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_select_preferred_addr` is a callback function which
- * asks a client application to choose server address from preferred
- * addresses |paddr| received from server. An application should
- * write preferred address in |dest|. If an application denies the
- * preferred addresses, just leave |dest| unmodified (or set dest->len
- * to 0) and return 0.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_select_preferred_addr)(ngtcp2_conn *conn,
- ngtcp2_addr *dest,
- const ngtcp2_preferred_addr *paddr,
- void *user_data);
-
-typedef enum ngtcp2_connection_id_status_type {
- /* NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE indicates that a local
- endpoint starts using new destination Connection ID. */
- NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE,
- /* NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE indicates that a
- local endpoint stops using a given destination Connection ID. */
- NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE
-} ngtcp2_connection_id_status_type;
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_connection_id_status` is a callback function which is
- * called when the status of Connection ID changes.
- *
- * |token| is the associated stateless reset token and it is NULL if
- * no token is present.
- *
- * |type| is the one of the value defined in
- * :enum:`ngtcp2_connection_id_status_type`. The new value might be
- * added in the future release.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_connection_id_status)(ngtcp2_conn *conn, int type,
- uint64_t seq, const ngtcp2_cid *cid,
- const uint8_t *token,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_recv_new_token` is a callback function which is
- * called when new token is received from server.
- *
- * |token| is the received token.
- *
- * The callback function must return 0 if it succeeds. Returning
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE` makes the library call return
- * immediately.
- */
-typedef int (*ngtcp2_recv_new_token)(ngtcp2_conn *conn, const ngtcp2_vec *token,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_delete_crypto_aead_ctx` is a callback function which
- * must delete the native object pointed by |aead_ctx|->native_handle.
- */
-typedef void (*ngtcp2_delete_crypto_aead_ctx)(ngtcp2_conn *conn,
- ngtcp2_crypto_aead_ctx *aead_ctx,
- void *user_data);
-
-/**
- * @functypedef
- *
- * :type:`ngtcp2_delete_crypto_cipher_ctx` is a callback function
- * which must delete the native object pointed by
- * |cipher_ctx|->native_handle.
- */
-typedef void (*ngtcp2_delete_crypto_cipher_ctx)(
- ngtcp2_conn *conn, ngtcp2_crypto_cipher_ctx *cipher_ctx, void *user_data);
-
-typedef struct ngtcp2_conn_callbacks {
- /**
- * client_initial is a callback function which is invoked when
- * client asks TLS stack to produce first TLS cryptographic
- * handshake message. This callback function must be specified.
- */
- ngtcp2_client_initial client_initial;
- /**
- * recv_client_initial is a callback function which is invoked when
- * a server receives the first packet from client. This callback
- * function must be specified.
- */
- ngtcp2_recv_client_initial recv_client_initial;
- /**
- * recv_crypto_data is a callback function which is invoked when
- * cryptographic data (CRYPTO frame, in other words, TLS message) is
- * received. This callback function must be specified.
- */
- ngtcp2_recv_crypto_data recv_crypto_data;
- /**
- * handshake_completed is a callback function which is invoked when
- * QUIC cryptographic handshake has completed. This callback
- * function is optional.
- */
- ngtcp2_handshake_completed handshake_completed;
- /**
- * recv_version_negotiation is a callback function which is invoked
- * when Version Negotiation packet is received by a client. This
- * callback function is optional.
- */
- ngtcp2_recv_version_negotiation recv_version_negotiation;
- /**
- * encrypt is a callback function which is invoked to encrypt a QUIC
- * packet. This callback function must be specified.
- */
- ngtcp2_encrypt encrypt;
- /**
- * decrypt is a callback function which is invoked to decrypt a QUIC
- * packet. This callback function must be specified.
- */
- ngtcp2_decrypt decrypt;
- /**
- * hp_mask is a callback function which is invoked to get a mask to
- * encrypt or decrypt packet header. This callback function must be
- * specified.
- */
- ngtcp2_hp_mask hp_mask;
- /**
- * recv_stream_data is a callback function which is invoked when
- * STREAM data, which includes application data, is received. This
- * callback function is optional.
- */
- ngtcp2_recv_stream_data recv_stream_data;
- /**
- * acked_crypto_offset is a callback function which is invoked when
- * CRYPTO data is acknowledged by a remote endpoint. It tells an
- * application the largest offset of acknowledged CRYPTO data
- * without a gap so that the application can free memory for the
- * data. This callback function is optional.
- */
- ngtcp2_acked_crypto_offset acked_crypto_offset;
- /**
- * acked_stream_data_offset is a callback function which is invoked
- * when STREAM data, which includes application data, is
- * acknowledged by a remote endpoint. It tells an application the
- * largest offset of acknowledged STREAM data without a gap so that
- * application can free memory for the data. This callback function
- * is optional.
- */
- ngtcp2_acked_stream_data_offset acked_stream_data_offset;
- /**
- * stream_open is a callback function which is invoked when new
- * remote stream is opened by a remote endpoint. This callback
- * function is optional.
- */
- ngtcp2_stream_open stream_open;
- /**
- * stream_close is a callback function which is invoked when a
- * stream is closed. This callback function is optional.
- */
- ngtcp2_stream_close stream_close;
- /**
- * recv_stateless_reset is a callback function which is invoked when
- * Stateless Reset packet is received. This callback function is
- * optional.
- */
- ngtcp2_recv_stateless_reset recv_stateless_reset;
- /**
- * recv_retry is a callback function which is invoked when a client
- * receives Retry packet. For client, this callback function must
- * be specified. Server never receive Retry packet.
- */
- ngtcp2_recv_retry recv_retry;
- /**
- * extend_max_local_streams_bidi is a callback function which is
- * invoked when the number of bidirectional stream which a local
- * endpoint can open is increased. This callback function is
- * optional.
- */
- ngtcp2_extend_max_streams extend_max_local_streams_bidi;
- /**
- * extend_max_local_streams_uni is a callback function which is
- * invoked when the number of unidirectional stream which a local
- * endpoint can open is increased. This callback function is
- * optional.
- */
- ngtcp2_extend_max_streams extend_max_local_streams_uni;
- /**
- * rand is a callback function which is invoked when the library
- * needs unpredictable sequence of random data. This callback
- * function must be specified.
- */
- ngtcp2_rand rand;
- /**
- * get_new_connection_id is a callback function which is invoked
- * when the library needs new connection ID. This callback function
- * must be specified.
- */
- ngtcp2_get_new_connection_id get_new_connection_id;
- /**
- * remove_connection_id is a callback function which notifies an
- * application that connection ID is no longer used by a remote
- * endpoint. This callback function is optional.
- */
- ngtcp2_remove_connection_id remove_connection_id;
- /**
- * update_key is a callback function which is invoked when the
- * library tells an application that it must update keying materials
- * and install new keys. This function must be specified.
- */
- ngtcp2_update_key update_key;
- /**
- * path_validation is a callback function which is invoked when path
- * validation completed. This function is optional.
- */
- ngtcp2_path_validation path_validation;
- /**
- * select_preferred_addr is a callback function which is invoked
- * when the library asks a client to select preferred address
- * presented by a server. This function is optional.
- */
- ngtcp2_select_preferred_addr select_preferred_addr;
- /**
- * stream_reset is a callback function which is invoked when a
- * stream is reset by a remote endpoint. This callback function is
- * optional.
- */
- ngtcp2_stream_reset stream_reset;
- /**
- * extend_max_remote_streams_bidi is a callback function which is
- * invoked when the number of bidirectional streams which a remote
- * endpoint can open is increased. This callback function is
- * optional.
- */
- ngtcp2_extend_max_streams extend_max_remote_streams_bidi;
- /**
- * extend_max_remote_streams_uni is a callback function which is
- * invoked when the number of unidirectional streams which a remote
- * endpoint can open is increased. This callback function is
- * optional.
- */
- ngtcp2_extend_max_streams extend_max_remote_streams_uni;
- /**
- * extend_max_stream_data is callback function which is invoked when
- * the maximum offset of STREAM data that a local endpoint can send
- * is increased. This callback function is optional.
- */
- ngtcp2_extend_max_stream_data extend_max_stream_data;
- /**
- * dcid_status is a callback function which is invoked when the new
- * destination Connection ID is activated or the activated
- * destination Connection ID is now deactivated.
- */
- ngtcp2_connection_id_status dcid_status;
- /**
- * handshake_confirmed is a callback function which is invoked when
- * both endpoints agree that handshake has finished. This field is
- * ignored by server because handshake_completed indicates the
- * handshake confirmation for server.
- */
- ngtcp2_handshake_confirmed handshake_confirmed;
- /**
- * recv_new_token is a callback function which is invoked when new
- * token is received from server. This field is ignored by server.
- */
- ngtcp2_recv_new_token recv_new_token;
- /**
- * delete_crypto_aead_ctx is a callback function which deletes a
- * given AEAD cipher context object.
- */
- ngtcp2_delete_crypto_aead_ctx delete_crypto_aead_ctx;
- /**
- * delete_crypto_cipher_ctx is a callback function which deletes a
- * given cipher context object.
- */
- ngtcp2_delete_crypto_cipher_ctx delete_crypto_cipher_ctx;
-} ngtcp2_conn_callbacks;
-
-/**
- * @function
- *
- * `ngtcp2_pkt_write_connection_close` writes Initial packet
- * containing CONNECTION_CLOSE frame with the given |error_code| to
- * the buffer pointed by |dest| of length |destlen|. All encryption
- * parameters are for Initial packet encryption. The packet number is
- * always 0.
- *
- * The primary use case of this function is for server to send
- * CONNECTION_CLOSE frame in Initial packet to close connection
- * without committing the state when validating Retry token fails.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small.
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE
- * Callback function failed.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_connection_close(
- uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt,
- const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_write_retry` writes Retry packet in the buffer pointed
- * by |dest| whose length is |destlen|. |odcid| specifies Original
- * Destination Connection ID. |token| specifies Retry Token, and
- * |tokenlen| specifies its length. |aead| must be AEAD_AES_128_GCM.
- * |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as an
- * encryption key.
- *
- * This function returns the number of bytes written to the buffer, or
- * one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small.
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE
- * Callback function failed.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_pkt_write_retry(
- uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
- size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_accept` is used by server implementation, and decides
- * whether packet |pkt| of length |pktlen| is acceptable for initial
- * packet from client.
- *
- * If it is acceptable, it returns 0. If it is not acceptable, and
- * Version Negotiation packet is required to send, it returns 1.
- * Otherwise, it returns -1.
- *
- * If |dest| is not NULL, and the return value is 0 or 1, the decoded
- * packet header is stored to the object pointed by |dest|.
- */
-NGTCP2_EXTERN int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
- size_t pktlen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_client_new` creates new :type:`ngtcp2_conn`, and
- * initializes it as client. |dcid| is randomized destination
- * connection ID. |scid| is source connection ID. |version| is a
- * QUIC version to use. |path| is the network path where this QUIC
- * connection is being established and must not be NULL. |callbacks|,
- * and |settings| must not be NULL, and the function make a copy of
- * each of them. |user_data| is the arbitrary pointer which is passed
- * to the user-defined callback functions. If |mem| is NULL, the
- * memory allocator returned by `ngtcp2_mem_default()` is used.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int
-ngtcp2_conn_client_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_path *path,
- uint32_t version, const ngtcp2_conn_callbacks *callbacks,
- const ngtcp2_settings *settings, const ngtcp2_mem *mem,
- void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_conn_server_new` creates new :type:`ngtcp2_conn`, and
- * initializes it as server. |dcid| is a destination connection ID.
- * |scid| is a source connection ID. |path| is the network path where
- * this QUIC connection is being established and must not be NULL.
- * |version| is a QUIC version to use. |callbacks|, and |settings|
- * must not be NULL, and the function make a copy of each of them.
- * |user_data| is the arbitrary pointer which is passed to the
- * user-defined callback functions. If |mem| is NULL, the memory
- * allocator returned by `ngtcp2_mem_default()` is used.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int
-ngtcp2_conn_server_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_path *path,
- uint32_t version, const ngtcp2_conn_callbacks *callbacks,
- const ngtcp2_settings *settings, const ngtcp2_mem *mem,
- void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_conn_del` frees resources allocated for |conn|. It also
- * frees memory pointed by |conn|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_del(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_read_pkt` decrypts QUIC packet given in |pkt| of
- * length |pktlen| and processes it. |path| is the network path the
- * packet is delivered and must not be NULL. This function performs
- * QUIC handshake as well.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * This function returns 0 if it succeeds, or negative error codes.
- * In general, if the error code which satisfies
- * ngtcp2_erro_is_fatal(err) != 0 is returned, the application should
- * just close the connection by calling
- * `ngtcp2_conn_write_connection_close` or just delete the QUIC
- * connection using `ngtcp2_conn_del`. It is undefined to call the
- * other library functions. If :enum:`NGTCP2_ERR_RETRY` is returned,
- * application must be a server and it must perform address validation
- * by sending Retry packet and close the connection. If
- * :enum:`NGTCP2_ERR_DROP_CONN` is returned, server application must
- * drop the connection silently (without sending any CONNECTION_CLOSE
- * frame) and discard connection state.
- */
-NGTCP2_EXTERN int ngtcp2_conn_read_pkt(ngtcp2_conn *conn,
- const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_write_pkt` is equivalent to calling
- * `ngtcp2_conn_writev_stream` without specifying stream data and
- * :enum:`NGTCP2_WRITE_STREAM_FLAG_NONE` as flags.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_pkt(ngtcp2_conn *conn,
- ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_handshake_completed` tells |conn| that the QUIC
- * handshake has completed.
- */
-NGTCP2_EXTERN void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_handshake_completed` returns nonzero if handshake
- * has completed.
- */
-NGTCP2_EXTERN int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_initial_key` installs packet protection keying
- * materials for Initial packets. |rx_aead_ctx| is AEAD cipher
- * context object and must be initialized with decryption key, IV
- * |rx_iv| of length |rx_ivlen|, and packet header protection cipher
- * context object |rx_hp_ctx| to decrypt incoming Initial packets.
- * Similarly, |tx_aead_ctx|, |tx_iv| and |tx_hp_ctx| are for
- * encrypting outgoing packets and are the same length with the
- * decryption counterpart . If they have already been set, they are
- * overwritten.
- *
- * If this function succeeds, |conn| takes ownership of |rx_aead_ctx|,
- * |rx_hp_ctx|, |tx_aead_ctx|, and |tx_hp_ctx|.
- * :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * After receiving Retry packet, the DCID most likely changes. In
- * that case, client application must generate these keying materials
- * again based on new DCID and install them again.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_initial_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx,
- const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx,
- const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv,
- const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_rx_handshake_key` installs packet protection
- * keying materials for decrypting incoming Handshake packets.
- * |aead_ctx| is AEAD cipher context object which must be initialized
- * with decryption key, IV |iv| of length |ivlen|, and packet header
- * protection cipher context object |hp_ctx| to decrypt incoming
- * Handshake packets.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx|,
- * and |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_rx_handshake_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_tx_handshake_key` installs packet protection
- * keying materials for encrypting outgoing Handshake packets.
- * |aead_ctx| is AEAD cipher context object which must be initialized
- * with encryption key, IV |iv| of length |ivlen|, and packet header
- * protection cipher context object |hp_ctx| to encrypt outgoing
- * Handshake packets.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx| and
- * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_tx_handshake_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_aead_overhead` tells the ngtcp2 library the length
- * of AEAD tag which the negotiated cipher suites defines. This
- * function must be called before encrypting or decrypting the
- * incoming packets other than Initial packets.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_aead_overhead(ngtcp2_conn *conn,
- size_t aead_overhead);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_aead_overhead` returns the aead overhead passed to
- * `ngtcp2_conn_set_aead_overhead`. If `ngtcp2_conn_set_aead_overhead` hasn't
- * been called yet this function returns 0.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_aead_overhead(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_early_key` installs packet protection AEAD
- * cipher context object |aead_ctx|, IV |iv| of length |ivlen|, and
- * packet header protection cipher context object |hp_ctx| to encrypt
- * (for client) or decrypt (for server) 0RTT packets.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx| and
- * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_early_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_rx_key` installs packet protection keying
- * materials for decrypting Short packets. |secret| of length
- * |secretlen| is the decryption secret which is used to derive keying
- * materials passed to this function. |aead_ctx| is AEAD cipher
- * context object which must be initialized with decryption key, IV
- * |iv| of length |ivlen|, and packet header protection cipher context
- * object |hp_ctx| to decrypt incoming Short packets.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx| and
- * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_rx_key(
- ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen,
- const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_install_tx_key` installs packet protection keying
- * materials for encrypting Short packets. |secret| of length
- * |secretlen| is the encryption secret which is used to derive keying
- * materials passed to this function. |aead_ctx| is AEAD cipher
- * context object which must be initialized with encryption key, IV
- * |iv| of length |ivlen|, and packet header protection cipher context
- * object |hp_ctx| to encrypt outgoing Short packets.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx| and
- * |hp_ctx|. :type:`ngtcp2_delete_crypto_aead_ctx` and
- * :type:`ngtcp2_delete_crypto_cipher_ctx` will be called to delete
- * these objects when they are no longer used. If this function
- * fails, the caller is responsible to delete them.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_install_tx_key(
- ngtcp2_conn *conn, const uint8_t *secret, size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx, const uint8_t *iv, size_t ivlen,
- const ngtcp2_crypto_cipher_ctx *hp_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_initiate_key_update` initiates the key update.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_INVALID_STATE`
- * The previous key update has not been confirmed yet; or key
- * update is too frequent; or new keys are not available yet.
- */
-NGTCP2_EXTERN int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_tls_error` sets the TLS related error in |conn|.
- * In general, error code should be propagated via return value, but
- * sometimes ngtcp2 API is called inside callback function of TLS
- * stack and it does not allow to return ngtcp2 error code directly.
- * In this case, implementation can set the error code (e.g.,
- * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM) using this function.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_tls_error` returns the value set by
- * `ngtcp2_conn_set_tls_error`. If no value is set, this function
- * returns 0.
- */
-NGTCP2_EXTERN int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_loss_detection_expiry` returns the expiry time point
- * of loss detection timer. Application should call
- * `ngtcp2_conn_on_loss_detection_timer` and `ngtcp2_conn_write_pkt`
- * (or `ngtcp2_conn_writev_stream`) when it expires. It returns
- * UINT64_MAX if loss detection timer is not armed.
- */
-NGTCP2_EXTERN ngtcp2_tstamp
-ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_ack_delay_expiry` returns the expiry time point of
- * delayed protected ACK. Application should call
- * ngtcp2_conn_cancel_expired_ack_delay_timer() and
- * `ngtcp2_conn_write_pkt` (or `ngtcp2_conn_writev_stream`) when it
- * expires. It returns UINT64_MAX if there is no expiry.
- */
-NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_ack_delay_expiry(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_expiry` returns the next expiry time. This
- * function returns the timestamp such that
- * min(ngtcp2_conn_loss_detection_expiry(conn),
- * ngtcp2_conn_ack_delay_expiry(conn), other timers in |conn|).
- *
- * Call `ngtcp2_conn_handle_expiry()` and `ngtcp2_conn_write_pkt` (or
- * `ngtcp2_conn_writev_stream`) if expiry time is passed.
- */
-NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_handle_expiry` handles expired timer. It does nothing
- * if timer is not expired.
- */
-NGTCP2_EXTERN int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_cancel_expired_ack_delay_timer` stops expired ACK
- * delay timer. |ts| is the current time. This function must be
- * called when ngtcp2_conn_ack_delay_expiry() <= ts.
- */
-NGTCP2_EXTERN void ngtcp2_conn_cancel_expired_ack_delay_timer(ngtcp2_conn *conn,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_idle_expiry` returns the time when a connection
- * should be closed if it continues to be idle. If idle timeout is
- * disabled, this function returns UINT64_MAX.
- */
-NGTCP2_EXTERN ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_pto` returns Probe Timeout (PTO).
- */
-NGTCP2_EXTERN ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_remote_transport_params` sets transport parameter
- * |params| to |conn|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_PROTO`
- * If |conn| is server, and negotiated_version field is not the
- * same as the used version.
- */
-NGTCP2_EXTERN int
-ngtcp2_conn_set_remote_transport_params(ngtcp2_conn *conn,
- const ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_remote_transport_params` fills settings values in
- * |params|. original_connection_id and
- * original_connection_id_present are always zero filled.
- */
-NGTCP2_EXTERN void
-ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn,
- ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_early_remote_transport_params` sets |params| as
- * transport parameter previously received from a server. The
- * parameters are used to send 0-RTT data. QUIC requires that client
- * application should remember transport parameter as well as session
- * ticket.
- *
- * At least following fields must be set:
- *
- * * initial_max_stream_id_bidi
- * * initial_max_stream_id_uni
- * * initial_max_stream_data_bidi_local
- * * initial_max_stream_data_bidi_remote
- * * initial_max_stream_data_uni
- * * initial_max_data
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_early_remote_transport_params(
- ngtcp2_conn *conn, const ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_local_transport_params` sets the local transport
- * parameters |params|. This function can only be called by server.
- * Although the local transport parameters are passed to
- * `ngtcp2_conn_server_new`, server might want to update them after
- * ALPN is chosen. In that case, server can update the transport
- * parameter with this function. Server must call this function
- * before calling `ngtcp2_conn_install_tx_handshake_key`.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_INVALID_STATE`
- * `ngtcp2_conn_install_tx_handshake_key` has been called.
- */
-NGTCP2_EXTERN int
-ngtcp2_conn_set_local_transport_params(ngtcp2_conn *conn,
- const ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_local_transport_params` fills settings values in
- * |params|.
- */
-NGTCP2_EXTERN void
-ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn,
- ngtcp2_transport_params *params);
-
-/**
- * @function
- *
- * `ngtcp2_conn_open_bidi_stream` opens new bidirectional stream. The
- * |stream_user_data| is the user data specific to the stream. The
- * open stream ID is stored in |*pstream_id|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_ID_BLOCKED`
- * The remote peer does not allow |stream_id| yet.
- */
-NGTCP2_EXTERN int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn,
- int64_t *pstream_id,
- void *stream_user_data);
-
-/**
- * @function
- *
- * `ngtcp2_conn_open_uni_stream` opens new unidirectional stream. The
- * |stream_user_data| is the user data specific to the stream. The
- * open stream ID is stored in |*pstream_id|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_ID_BLOCKED`
- * The remote peer does not allow |stream_id| yet.
- */
-NGTCP2_EXTERN int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn,
- int64_t *pstream_id,
- void *stream_user_data);
-
-/**
- * @function
- *
- * `ngtcp2_conn_shutdown_stream` closes stream denoted by |stream_id|
- * abruptly. |app_error_code| is one of application error codes, and
- * indicates the reason of shutdown. Successful call of this function
- * does not immediately erase the state of the stream. The actual
- * deletion is done when the remote endpoint sends acknowledgement.
- * Calling this function is equivalent to call
- * `ngtcp2_conn_shutdown_stream_read`, and
- * `ngtcp2_conn_shutdown_stream_write` sequentially.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream does not exist
- */
-NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t app_error_code);
-
-/**
- * @function
- *
- * `ngtcp2_conn_shutdown_stream_write` closes write-side of stream
- * denoted by |stream_id| abruptly. |app_error_code| is one of
- * application error codes, and indicates the reason of shutdown. If
- * this function succeeds, no application data is sent to the remote
- * endpoint. It discards all data which has not been acknowledged
- * yet.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream does not exist
- */
-NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t app_error_code);
-
-/**
- * @function
- *
- * `ngtcp2_conn_shutdown_stream_read` closes read-side of stream
- * denoted by |stream_id| abruptly. |app_error_code| is one of
- * application error codes, and indicates the reason of shutdown. If
- * this function succeeds, no application data is forwarded to an
- * application layer.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream does not exist
- */
-NGTCP2_EXTERN int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t app_error_code);
-
-/**
- * @enum
- *
- * ngtcp2_write_stream_flag defines extra behaviour for
- * `ngtcp2_conn_writev_stream()`.
- */
-typedef enum ngtcp2_write_stream_flag {
- NGTCP2_WRITE_STREAM_FLAG_NONE = 0x00,
- /**
- * NGTCP2_WRITE_STREAM_FLAG_MORE indicates that more stream data may
- * come and should be coalesced into the same packet if possible.
- */
- NGTCP2_WRITE_STREAM_FLAG_MORE = 0x01,
- /**
- * NGTCP2_WRITE_STREAM_FLAG_FIN indicates that the passed data is
- * the final part of a stream.
- */
- NGTCP2_WRITE_STREAM_FLAG_FIN = 0x02
-} ngtcp2_write_stream_flag;
-
-/**
- * @function
- *
- * `ngtcp2_conn_write_stream` is just like
- * `ngtcp2_conn_writev_stream`. The only difference is that it
- * conveniently accepts a single buffer.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream(
- ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id,
- const uint8_t *data, size_t datalen, ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_writev_stream` writes a packet containing stream data
- * of stream denoted by |stream_id|. The buffer of the packet is
- * pointed by |dest| of length |destlen|. This function performs QUIC
- * handshake as well.
- *
- * Specifying -1 to |stream_id| means no new stream data to send.
- *
- * If |path| is not NULL, this function stores the network path with
- * which the packet should be sent. Each addr field must point to the
- * buffer which is at least 128 bytes. ``sizeof(struct
- * sockaddr_storage)`` is enough. The assignment might not be done if
- * nothing is written to |dest|.
- *
- * If the all given data is encoded as STREAM frame in |dest|, and if
- * |flags| & NGTCP2_WRITE_STREAM_FLAG_FIN is nonzero, fin flag is set
- * to outgoing STREAM frame. Otherwise, fin flag in STREAM frame is
- * not set.
- *
- * This packet may contain frames other than STREAM frame. The packet
- * might not contain STREAM frame if other frames occupy the packet.
- * In that case, |*pdatalen| would be -1 if |pdatalen| is not NULL.
- *
- * If |flags| & NGTCP2_WRITE_STREAM_FLAG_FIN is nonzero, and 0 length
- * STREAM frame is successfully serialized, |*pdatalen| would be 0.
- *
- * The number of data encoded in STREAM frame is stored in |*pdatalen|
- * if it is not NULL. The caller must keep the portion of data
- * covered by |*pdatalen| bytes in tact until
- * :type:`ngtcp2_acked_stream_data_offset` indicates that they are
- * acknowledged by a remote endpoint or the stream is closed.
- *
- * If |flags| equals to :enum:`NGTCP2_WRITE_STREAM_FLAG_NONE`, this
- * function produces a single payload of UDP packet. If the given
- * stream data is small (e.g., few bytes), the packet might be
- * severely under filled. Too many small packet might increase
- * overall packet processing costs. Unless there are retransmissions,
- * by default, application can only send 1 STREAM frame in one QUIC
- * packet. In order to include more than 1 STREAM frame in one QUIC
- * packet, specify :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE` in |flags|.
- * This is analogous to ``MSG_MORE`` flag in ``send(2)``. If the
- * :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE` is used, there are 4
- * outcomes:
- *
- * - The function returns the written length of packet just like
- * without :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE`. This is because
- * packet is nearly full and the library decided to make a complete
- * packet. In this case, |*pdatalen| == -1 is asserted.
- *
- * - The function returns :enum:`NGTCP2_ERR_WRITE_MORE`. In this
- * case, |*pdatalen| >= 0 is asserted. This indicates that
- * application can call this function with different stream data to
- * pack them into the same packet. Application has to specify the
- * same |conn|, |path|, |dest|, |destlen|, |pdatalen|, and |ts|
- * parameters, otherwise the behaviour is undefined. The
- * application can change |flags|.
- *
- * - The function returns :enum:`NGTCP2_ERR_STREAM_DATA_BLOCKED` which
- * indicates that stream is blocked because of flow control.
- *
- * - The other error might be returned just like without
- * :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE`.
- *
- * When application sees :enum:`NGTCP2_ERR_WRITE_MORE`, it must not
- * call other ngtcp2 API functions (application can still call
- * `ngtcp2_conn_write_connection_close` or
- * `ngtcp2_conn_write_application_close` to handle error from this
- * function). Just keep calling `ngtcp2_conn_writev_stream` or
- * `ngtcp2_conn_write_pkt` until it returns a positive number (which
- * indicates a complete packet is ready). If |*pdatalen| >= 0, the
- * function always return :enum:`NGTCP2_ERR_WRITE_MORE`.
- *
- * This function returns 0 if it cannot write any frame because buffer
- * is too small, or packet is congestion limited. Application should
- * keep reading and wait for congestion window to grow.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream does not exist
- * :enum:`NGTCP2_ERR_STREAM_SHUT_WR`
- * Stream is half closed (local); or stream is being reset.
- * :enum:`NGTCP2_ERR_PKT_NUM_EXHAUSTED`
- * Packet number is exhausted, and cannot send any more packet.
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
- * User callback failed
- * :enum:`NGTCP2_ERR_STREAM_DATA_BLOCKED`
- * Stream is blocked because of flow control.
- * :enum:`NGTCP2_ERR_WRITE_MORE`
- * (Only when :enum:`NGTCP2_WRITE_STREAM_FLAG_MORE` is specified)
- * Application can call this function to pack more stream data
- * into the same packet. See above to know how it works.
- *
- * In general, if the error code which satisfies
- * ngtcp2_err_is_fatal(err) != 0 is returned, the application should
- * just close the connection by calling
- * `ngtcp2_conn_write_connection_close` or just delete the QUIC
- * connection using `ngtcp2_conn_del`. It is undefined to call the
- * other library functions.
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_writev_stream(
- ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags, int64_t stream_id,
- const ngtcp2_vec *datav, size_t datavcnt, ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_write_connection_close` writes a packet which contains
- * a CONNECTION_CLOSE frame (type 0x1c) in the buffer pointed by
- * |dest| whose capacity is |datalen|.
- *
- * If |path| is not NULL, this function stores the network path with
- * which the packet should be sent. Each addr field must point to the
- * buffer which is at least 128 bytes. ``sizeof(struct
- * sockaddr_storage)`` is enough. The assignment might not be done if
- * nothing is written to |dest|.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * At the moment, successful call to this function makes connection
- * close. We may change this behaviour in the future to allow
- * graceful shutdown.
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small
- * :enum:`NGTCP2_ERR_INVALID_STATE`
- * The current state does not allow sending CONNECTION_CLOSE.
- * :enum:`NGTCP2_ERR_PKT_NUM_EXHAUSTED`
- * Packet number is exhausted, and cannot send any more packet.
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
- * User callback failed
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_connection_close(
- ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- uint64_t error_code, ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_write_application_close` writes a packet which
- * contains a CONNECTION_CLOSE frame (type 0x1d) in the buffer pointed
- * by |dest| whose capacity is |datalen|.
- *
- * If |path| is not NULL, this function stores the network path with
- * which the packet should be sent. Each addr field must point to the
- * buffer which is at least 128 bytes. ``sizeof(struct
- * sockaddr_storage)`` is enough. The assignment might not be done if
- * nothing is written to |dest|.
- *
- * If handshake has not been confirmed yet, CONNECTION_CLOSE (type
- * 0x1c) with error code :macro:`NGTCP2_APPLICATION_ERROR` is written
- * instead.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * At the moment, successful call to this function makes connection
- * close. We may change this behaviour in the future to allow
- * graceful shutdown.
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer is too small
- * :enum:`NGTCP2_ERR_INVALID_STATE`
- * The current state does not allow sending CONNECTION_CLOSE.
- * :enum:`NGTCP2_ERR_PKT_NUM_EXHAUSTED`
- * Packet number is exhausted, and cannot send any more packet.
- * :enum:`NGTCP2_ERR_CALLBACK_FAILURE`
- * User callback failed
- */
-NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_application_close(
- ngtcp2_conn *conn, ngtcp2_path *path, uint8_t *dest, size_t destlen,
- uint64_t app_error_code, ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_is_in_closing_period` returns nonzero if |conn| is in
- * closing period.
- */
-NGTCP2_EXTERN int ngtcp2_conn_is_in_closing_period(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_is_in_draining_period` returns nonzero if |conn| is in
- * draining period.
- */
-NGTCP2_EXTERN int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_extend_max_stream_offset` extends stream's max stream
- * data value by |datalen|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream was not found
- */
-NGTCP2_EXTERN int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn,
- int64_t stream_id,
- uint64_t datalen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_extend_max_offset` extends max data offset by
- * |datalen|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn,
- uint64_t datalen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_extend_max_streams_bidi` extends the number of maximum
- * local bidirectional streams that a remote endpoint can open by |n|.
- *
- * The library does not increase maximum stream limit automatically.
- * The exception is when a stream is closed without
- * :type:`ngtcp2_stream_open` callback being called. In this case,
- * stream limit is increased automatically.
- */
-NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_bidi(ngtcp2_conn *conn,
- size_t n);
-
-/**
- * @function
- *
- * `ngtcp2_conn_extend_max_streams_uni` extends the number of maximum
- * local unidirectional streams that a remote endpoint can open by
- * |n|.
- *
- * The library does not increase maximum stream limit automatically.
- * The exception is when a stream is closed without
- * :type:`ngtcp2_stream_open` callback being called. In this case,
- * stream limit is increased automatically.
- */
-NGTCP2_EXTERN void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn,
- size_t n);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_dcid` returns the non-NULL pointer to destination
- * connection ID. If no destination connection ID is present, the
- * return value is not ``NULL``, and its datalen field is 0.
- */
-NGTCP2_EXTERN const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_num_scid` returns the number of source connection
- * IDs which the local endpoint has provided to the peer and have not
- * retired.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_num_scid(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_scid` writes the all source connection IDs which
- * the local endpoint has provided to the peer and have not retired in
- * |dest|. The buffer pointed by |dest| must have
- * ``sizeof(ngtcp2_cid) * n`` bytes available, where n is the return
- * value of `ngtcp2_conn_get_num_scid()`.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_num_active_dcid` returns the number of the active
- * destination connection ID.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_num_active_dcid(ngtcp2_conn *conn);
-
-/**
- * @struct
- *
- * :type:`ngtcp2_cid_token` is the convenient struct to store
- * Connection ID, its associated path, and stateless reset token.
- */
-typedef struct ngtcp2_cid_token {
- /* seq is the sequence number of this Connection ID. */
- uint64_t seq;
- /* cid is Connection ID. */
- ngtcp2_cid cid;
- /* ps is the path which is associated to this Connection ID. */
- ngtcp2_path_storage ps;
- /* token is the stateless reset token for this Connection ID. */
- uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN];
- /* token_resent is nonzero if token contains stateless reset
- token. */
- uint8_t token_present;
-} ngtcp2_cid_token;
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_active_dcid` writes the all active destination
- * connection IDs and tokens to |dest|. The buffer pointed by |dest|
- * must have ``sizeof(ngtcp2_cid_token) * n`` bytes available, where n
- * is the return value of `ngtcp2_conn_get_num_active_dcid()`.
- */
-NGTCP2_EXTERN size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn,
- ngtcp2_cid_token *dest);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_negotiated_version` returns the negotiated version.
- */
-NGTCP2_EXTERN uint32_t ngtcp2_conn_get_negotiated_version(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_early_data_rejected` tells |conn| that 0-RTT data was
- * rejected by a server.
- */
-NGTCP2_EXTERN int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_conn_stat` assigns connection statistics data to
- * |*cstat|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_get_conn_stat(ngtcp2_conn *conn,
- ngtcp2_conn_stat *cstat);
-
-/**
- * @function
- *
- * `ngtcp2_conn_on_loss_detection_timer` should be called when a timer
- * returned from `ngtcp2_conn_earliest_expiry` fires.
- *
- * Application should call `ngtcp2_conn_handshake` if handshake has
- * not completed, otherwise `ngtcp2_conn_write_pkt` (or
- * `ngtcp2_conn_write_stream` if it has data to send) to send TLP/RTO
- * probe packets.
- *
- * This function must not be called from inside the callback
- * functions.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- */
-NGTCP2_EXTERN int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_submit_crypto_data` submits crypto stream data |data|
- * of length |datalen| to the library for transmission. The
- * encryption level is given in |crypto_level|.
- *
- * Application should keep the buffer pointed by |data| alive until
- * the data is acknowledged. The acknowledgement is notified by
- * :type:`ngtcp2_acked_crypto_offset` callback.
- */
-NGTCP2_EXTERN int
-ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- const uint8_t *data, const size_t datalen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_submit_new_token` submits address validation token.
- * It is sent in NEW_TOKEN frame. Only server can call this function.
- * |tokenlen| must not be 0.
- *
- * This function makes a copy of the buffer pointed by |token| of
- * length |tokenlen|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory.
- */
-NGTCP2_EXTERN int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn,
- const uint8_t *token,
- size_t tokenlen);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_local_addr` sets local endpoint address |addr| to
- * |conn|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_local_addr(ngtcp2_conn *conn,
- const ngtcp2_addr *addr);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_remote_addr` sets remote endpoint address |addr|
- * to |conn|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_remote_addr(ngtcp2_conn *conn,
- const ngtcp2_addr *addr);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_remote_addr` returns the remote endpoint address
- * set in |conn|.
- */
-NGTCP2_EXTERN const ngtcp2_addr *ngtcp2_conn_get_remote_addr(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_initiate_migration` starts connection migration to the
- * given |path| which must not be NULL. Only client can initiate
- * migration. This function does immediate migration; it does not
- * probe peer reachability from a new local address.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_INVALID_STATE`
- * Migration is disabled.
- * :enum:`NGTCP2_ERR_CONN_ID_BLOCKED`
- * No unused connection ID is available.
- * :enum:`NGTCP2_ERR_INVALID_ARGUMENT`
- * |path| equals the current path.
- * :enum:`NGTCP2_ERR_NOMEM`
- * Out of memory
- */
-NGTCP2_EXTERN int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn,
- const ngtcp2_path *path,
- ngtcp2_tstamp ts);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_max_local_streams_uni` returns the cumulative
- * number of streams which local endpoint can open.
- */
-NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_local_streams_uni(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_max_data_left` returns the number of bytes that
- * this local endpoint can send in this connection.
- */
-NGTCP2_EXTERN uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_streams_bidi_left` returns the number of
- * bidirectional streams which the local endpoint can open without
- * violating stream concurrency limit.
- */
-NGTCP2_EXTERN uint64_t ngtcp2_conn_get_streams_bidi_left(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_streams_uni_left` returns the number of
- * unidirectional streams which the local endpoint can open without
- * violating stream concurrency limit.
- */
-NGTCP2_EXTERN uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_initial_crypto_ctx` sets |ctx| for Initial packet
- * encryption. The passed data will be passed to
- * :type:`ngtcp2_encrypt`, :type:`ngtcp2_decrypt` and
- * :type:`ngtcp2_hp_mask` callbacks.
- */
-NGTCP2_EXTERN void
-ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn,
- const ngtcp2_crypto_ctx *ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_initial_crypto_ctx` returns
- * :type:`ngtcp2_crypto_ctx` object for Initial packet encryption.
- */
-NGTCP2_EXTERN const ngtcp2_crypto_ctx *
-ngtcp2_conn_get_initial_crypto_ctx(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_initial_crypto_ctx` sets |ctx| for
- * 0RTT/Handshake/Short packet encryption. In other words, this
- * crypto context is used for all packets except for Initial packets.
- * The passed data will be passed to :type:`ngtcp2_encrypt`,
- * :type:`ngtcp2_decrypt` and :type:`ngtcp2_hp_mask` callbacks.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn,
- const ngtcp2_crypto_ctx *ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_tls_native_handle` returns TLS native handle set by
- * `ngtcp2_conn_set_tls_native_handle()`.
- */
-NGTCP2_EXTERN void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_tls_native_handle` sets TLS native handle
- * |tls_native_handle| to |conn|. Internally, it is used as an opaque
- * pointer.
- */
-NGTCP2_EXTERN void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn,
- void *tls_native_handle);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_retry_aead` sets |aead| and |aead_ctx| for Retry
- * integrity tag verification. |aead| must be AEAD_AES_128_GCM.
- * |aead_ctx| must be initialized with :macro:`NGTCP2_RETRY_KEY` as
- * encryption key. This function must be called if |conn| is
- * initialized as client. Server does not verify the tag and has no
- * need to call this function.
- *
- * If this function succeeds, |conn| takes ownership of |aead_ctx|.
- * :type:`ngtcp2_delete_crypto_aead_ctx` will be called to delete this
- * object when it is no longer used. If this function fails, the
- * caller is responsible to delete it.
- */
-NGTCP2_EXTERN void
-ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx);
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_crypto_ctx` returns :type:`ngtcp2_crypto_ctx`
- * object for 0RTT/Handshake/Short packet encryption.
- */
-NGTCP2_EXTERN const ngtcp2_crypto_ctx *
-ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn);
-
-typedef enum ngtcp2_connection_close_error_code_type {
- /* NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT indicates the
- error code is QUIC transport error code. */
- NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT,
- /* NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION indicates the
- error code is application error code. */
- NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION,
-} ngtcp2_connection_close_error_code_type;
-
-typedef struct ngtcp2_connection_close_error_code {
- /* error_code is the error code for connection closure. */
- uint64_t error_code;
- /* type is the type of error_code. */
- ngtcp2_connection_close_error_code_type type;
-} ngtcp2_connection_close_error_code;
-
-/**
- * @function
- *
- * `ngtcp2_conn_get_connection_close_error_code` stores the received
- * connection close error code in |ccec|.
- */
-NGTCP2_EXTERN void ngtcp2_conn_get_connection_close_error_code(
- ngtcp2_conn *conn, ngtcp2_connection_close_error_code *ccec);
-
-/**
- * @function
- *
- * `ngtcp2_conn_is_local_stream` returns nonzero if |stream_id| denotes the
- * stream which a local endpoint issues.
- */
-NGTCP2_EXTERN int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn,
- int64_t stream_id);
-
-/**
- * @function
- *
- * `ngtcp2_conn_is_server` returns nonzero if |conn| is initialized as
- * server.
- */
-NGTCP2_EXTERN int ngtcp2_conn_is_server(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_after_retry` returns nonzero if |conn| as a client has
- * received Retry packet from server and successfully validated it.
- */
-NGTCP2_EXTERN int ngtcp2_conn_after_retry(ngtcp2_conn *conn);
-
-/**
- * @function
- *
- * `ngtcp2_conn_set_stream_user_data` sets |stream_user_data| to the
- * stream identified by |stream_id|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * :enum:`NGTCP2_ERR_STREAM_NOT_FOUND`
- * Stream does not exist
- */
-NGTCP2_EXTERN int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn,
- int64_t stream_id,
- void *stream_user_data);
-
-/**
- * @function
- *
- * `ngtcp2_strerror` returns the text representation of |liberr|.
- */
-NGTCP2_EXTERN const char *ngtcp2_strerror(int liberr);
-
-/**
- * @function
- *
- * `ngtcp2_err_is_fatal` returns nonzero if |liberr| is a fatal error.
- */
-NGTCP2_EXTERN int ngtcp2_err_is_fatal(int liberr);
-
-/**
- * @function
- *
- * `ngtcp2_err_infer_quic_transport_error_code` returns a QUIC
- * transport error code which corresponds to |liberr|.
- */
-NGTCP2_EXTERN uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr);
-
-/**
- * @function
- *
- * `ngtcp2_addr_init` initializes |dest| with the given arguments and
- * returns |dest|.
- */
-NGTCP2_EXTERN ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest,
- const struct sockaddr *addr,
- size_t addrlen, void *user_data);
-
-/**
- * @function
- *
- * `ngtcp2_path_storage_init` initializes |ps| with the given
- * arguments. This function copies |local_addr| and |remote_addr|.
- */
-NGTCP2_EXTERN void ngtcp2_path_storage_init(ngtcp2_path_storage *ps,
- const struct sockaddr *local_addr,
- size_t local_addrlen,
- void *local_user_data,
- const struct sockaddr *remote_addr,
- size_t remote_addrlen,
- void *remote_user_data);
-
-/**
- * @function
- *
- * `ngtcp2_path_storage_zero` initializes |ps| with the zero length
- * addresses.
- */
-NGTCP2_EXTERN void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps);
-
-/**
- * @function
- *
- * `ngtcp2_settings_default` initializes |settings| with the default
- * values. First this function fills |settings| with 0 and set the
- * default value to the following fields:
- *
- * * cc_algo = NGTCP2_CC_ALGO_CUBIC
- * * initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT
- * * transport_params.max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE
- * * transport_params.ack_delay_component = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT
- * * transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY
- * * transport_params.active_connection_id_limit =
- * NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT
- */
-NGTCP2_EXTERN void ngtcp2_settings_default(ngtcp2_settings *settings);
-
-/*
- * @function
- *
- * `ngtcp2_mem_default` returns the default, system standard memory
- * allocator.
- */
-NGTCP2_EXTERN const ngtcp2_mem *ngtcp2_mem_default(void);
-
-/**
- * @macro
- *
- * The age of :type:`ngtcp2_info`
- */
-#define NGTCP2_VERSION_AGE 1
-
-/**
- * @struct
- *
- * This struct is what `ngtcp2_version()` returns. It holds
- * information about the particular ngtcp2 version.
- */
-typedef struct ngtcp2_info {
- /**
- * Age of this struct. This instance of ngtcp2 sets it to
- * :macro:`NGTCP2_VERSION_AGE` but a future version may bump it and
- * add more struct fields at the bottom
- */
- int age;
- /**
- * the :macro:`NGTCP2_VERSION_NUM` number (since age ==1)
- */
- int version_num;
- /**
- * points to the :macro:`NGTCP2_VERSION` string (since age ==1)
- */
- const char *version_str;
- /* -------- the above fields all exist when age == 1 */
-} ngtcp2_info;
-
-/**
- * @function
- *
- * Returns a pointer to a ngtcp2_info struct with version information
- * about the run-time library in use. The |least_version| argument
- * can be set to a 24 bit numerical value for the least accepted
- * version number and if the condition is not met, this function will
- * return a ``NULL``. Pass in 0 to skip the version checking.
- */
-NGTCP2_EXTERN ngtcp2_info *ngtcp2_version(int least_version);
-
-/**
- * @function
- *
- * `ngtcp2_is_bidi_stream` returns nonzero if |stream_id| denotes
- * bidirectional stream.
- */
-NGTCP2_EXTERN int ngtcp2_is_bidi_stream(int64_t stream_id);
-
-typedef enum {
- NGTCP2_LOG_EVENT_NONE,
- /* connection (catch-all) event */
- NGTCP2_LOG_EVENT_CON,
- /* packet event */
- NGTCP2_LOG_EVENT_PKT,
- /* frame event */
- NGTCP2_LOG_EVENT_FRM,
- /* recovery event */
- NGTCP2_LOG_EVENT_RCV,
- /* crypto event */
- NGTCP2_LOG_EVENT_CRY,
- /* path validation event */
- NGTCP2_LOG_EVENT_PTV,
-} ngtcp2_log_event;
-
-/**
- * @function
- *
- * `ngtcp2_log_info` writes info level log.
- */
-NGTCP2_EXTERN void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev,
- const char *fmt, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* NGTCP2_H */
diff --git a/deps/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/lib/includes/ngtcp2/version.h
deleted file mode 100644
index 3782959c28..0000000000
--- a/deps/ngtcp2/lib/includes/ngtcp2/version.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2016 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef VERSION_H
-#define VERSION_H
-
-/**
- * @macro
- *
- * Version number of the ngtcp2 library release.
- */
-#define NGTCP2_VERSION "0.1.0-DEV"
-
-/**
- * @macro
- *
- * Numerical representation of the version number of the ngtcp2
- * library 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 NGTCP2_VERSION_NUM 0x000100
-
-#endif /* VERSION_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_acktr.c b/deps/ngtcp2/lib/ngtcp2_acktr.c
deleted file mode 100644
index 7a7f3e469a..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_acktr.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_acktr.h"
-
-#include <assert.h>
-
-int ngtcp2_acktr_entry_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
- ngtcp2_tstamp tstamp, const ngtcp2_mem *mem) {
- *ent = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_acktr_entry));
- if (*ent == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- (*ent)->pkt_num = pkt_num;
- (*ent)->len = 1;
- (*ent)->tstamp = tstamp;
-
- return 0;
-}
-
-void ngtcp2_acktr_entry_del(ngtcp2_acktr_entry *ent, const ngtcp2_mem *mem) {
- ngtcp2_mem_free(mem, ent);
-}
-
-static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *(int64_t *)lhs > *(int64_t *)rhs;
-}
-
-int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
- const ngtcp2_mem *mem) {
- int rv;
-
- rv = ngtcp2_ringbuf_init(&acktr->acks, 128, sizeof(ngtcp2_acktr_ack_entry),
- mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_ksl_init(&acktr->ents, greater, sizeof(int64_t), mem);
- if (rv != 0) {
- ngtcp2_ringbuf_free(&acktr->acks);
- return rv;
- }
-
- acktr->log = log;
- acktr->mem = mem;
- acktr->flags = NGTCP2_ACKTR_FLAG_NONE;
- acktr->first_unacked_ts = UINT64_MAX;
- acktr->rx_npkt = 0;
-
- return 0;
-}
-
-void ngtcp2_acktr_free(ngtcp2_acktr *acktr) {
- ngtcp2_ksl_it it;
-
- if (acktr == NULL) {
- return;
- }
-
- for (it = ngtcp2_ksl_begin(&acktr->ents); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ngtcp2_acktr_entry_del(ngtcp2_ksl_it_get(&it), acktr->mem);
- }
- ngtcp2_ksl_free(&acktr->ents);
-
- ngtcp2_ringbuf_free(&acktr->acks);
-}
-
-int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
- ngtcp2_tstamp ts) {
- ngtcp2_ksl_it it;
- ngtcp2_acktr_entry *ent, *prev_ent, *delent;
- int rv;
- int added = 0;
-
- if (ngtcp2_ksl_len(&acktr->ents)) {
- it = ngtcp2_ksl_lower_bound(&acktr->ents, &pkt_num);
- if (ngtcp2_ksl_it_end(&it)) {
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
-
- assert(ent->pkt_num >= pkt_num + (int64_t)ent->len);
-
- if (ent->pkt_num == pkt_num + (int64_t)ent->len) {
- ++ent->len;
- added = 1;
- }
- } else {
- ent = ngtcp2_ksl_it_get(&it);
-
- assert(ent->pkt_num != pkt_num);
-
- if (ngtcp2_ksl_it_begin(&it)) {
- if (ent->pkt_num + 1 == pkt_num) {
- ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
- ent->pkt_num = pkt_num;
- ent->tstamp = ts;
- ++ent->len;
- added = 1;
- }
- } else {
- ngtcp2_ksl_it_prev(&it);
- prev_ent = ngtcp2_ksl_it_get(&it);
-
- assert(prev_ent->pkt_num >= pkt_num + (int64_t)prev_ent->len);
-
- if (ent->pkt_num + 1 == pkt_num) {
- if (prev_ent->pkt_num == pkt_num + (int64_t)prev_ent->len) {
- prev_ent->len += ent->len + 1;
- ngtcp2_ksl_remove(&acktr->ents, NULL, &ent->pkt_num);
- ngtcp2_acktr_entry_del(ent, acktr->mem);
- added = 1;
- } else {
- ngtcp2_ksl_update_key(&acktr->ents, &ent->pkt_num, &pkt_num);
- ent->pkt_num = pkt_num;
- ent->tstamp = ts;
- ++ent->len;
- added = 1;
- }
- } else if (prev_ent->pkt_num == pkt_num + (int64_t)prev_ent->len) {
- ++prev_ent->len;
- added = 1;
- }
- }
- }
- }
-
- if (!added) {
- rv = ngtcp2_acktr_entry_new(&ent, pkt_num, ts, acktr->mem);
- if (rv != 0) {
- return rv;
- }
- rv = ngtcp2_ksl_insert(&acktr->ents, NULL, &ent->pkt_num, ent);
- if (rv != 0) {
- ngtcp2_acktr_entry_del(ent, acktr->mem);
- return rv;
- }
- }
-
- if (active_ack) {
- acktr->flags |= NGTCP2_ACKTR_FLAG_ACTIVE_ACK;
- if (acktr->first_unacked_ts == UINT64_MAX) {
- acktr->first_unacked_ts = ts;
- }
- }
-
- if (ngtcp2_ksl_len(&acktr->ents) > NGTCP2_ACKTR_MAX_ENT) {
- it = ngtcp2_ksl_end(&acktr->ents);
- ngtcp2_ksl_it_prev(&it);
- delent = ngtcp2_ksl_it_get(&it);
- ngtcp2_ksl_remove(&acktr->ents, NULL, &delent->pkt_num);
- ngtcp2_acktr_entry_del(delent, acktr->mem);
- }
-
- return 0;
-}
-
-void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent) {
- ngtcp2_ksl_it it;
-
- it = ngtcp2_ksl_lower_bound(&acktr->ents, &ent->pkt_num);
- assert(*(int64_t *)ngtcp2_ksl_it_key(&it) == (int64_t)ent->pkt_num);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- ent = ngtcp2_ksl_it_get(&it);
- ngtcp2_ksl_remove(&acktr->ents, &it, &ent->pkt_num);
- ngtcp2_acktr_entry_del(ent, acktr->mem);
- }
-}
-
-ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr) {
- return ngtcp2_ksl_begin(&acktr->ents);
-}
-
-int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) {
- ngtcp2_ksl_it it = ngtcp2_ksl_begin(&acktr->ents);
- return ngtcp2_ksl_it_end(&it);
-}
-
-ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr,
- int64_t pkt_num,
- int64_t largest_ack) {
- ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks);
-
- ent->largest_ack = largest_ack;
- ent->pkt_num = pkt_num;
-
- return ent;
-}
-
-/*
- * acktr_remove removes |ent| from |acktr|. The iterator which points
- * to the entry next to |ent| is assigned to |it|.
- */
-static void acktr_remove(ngtcp2_acktr *acktr, ngtcp2_ksl_it *it,
- ngtcp2_acktr_entry *ent) {
- ngtcp2_ksl_remove(&acktr->ents, it, &ent->pkt_num);
- ngtcp2_acktr_entry_del(ent, acktr->mem);
-}
-
-static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb,
- size_t ack_ent_offset) {
- ngtcp2_acktr_ack_entry *ack_ent;
- ngtcp2_acktr_entry *ent;
- ngtcp2_ksl_it it;
-
- assert(ngtcp2_ringbuf_len(rb));
-
- ack_ent = ngtcp2_ringbuf_get(rb, ack_ent_offset);
-
- /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
- it = ngtcp2_ksl_lower_bound(&acktr->ents, &ack_ent->largest_ack);
- for (; !ngtcp2_ksl_it_end(&it);) {
- ent = ngtcp2_ksl_it_get(&it);
- acktr_remove(acktr, &it, ent);
- }
-
- if (ngtcp2_ksl_len(&acktr->ents)) {
- assert(ngtcp2_ksl_it_end(&it));
-
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
- if (ent->pkt_num > ack_ent->largest_ack &&
- ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) {
- ent->len = (size_t)(ent->pkt_num - ack_ent->largest_ack);
- }
- }
-
- ngtcp2_ringbuf_resize(rb, ack_ent_offset);
-}
-
-void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) {
- ngtcp2_acktr_ack_entry *ent;
- int64_t largest_ack = fr->largest_ack, min_ack;
- size_t i, j;
- ngtcp2_ringbuf *rb = &acktr->acks;
- size_t nacks = ngtcp2_ringbuf_len(rb);
-
- /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
- for (j = 0; j < nacks; ++j) {
- ent = ngtcp2_ringbuf_get(rb, j);
- if (largest_ack >= ent->pkt_num) {
- break;
- }
- }
- if (j == nacks) {
- return;
- }
-
- min_ack = largest_ack - (int64_t)fr->first_ack_blklen;
-
- if (min_ack <= ent->pkt_num && ent->pkt_num <= largest_ack) {
- acktr_on_ack(acktr, rb, j);
- return;
- }
-
- for (i = 0; i < fr->num_blks && j < nacks; ++i) {
- largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2;
- min_ack = largest_ack - (int64_t)fr->blks[i].blklen;
-
- for (;;) {
- if (ent->pkt_num > largest_ack) {
- ++j;
- if (j == nacks) {
- return;
- }
- ent = ngtcp2_ringbuf_get(rb, j);
- continue;
- }
- if (ent->pkt_num < min_ack) {
- break;
- }
- acktr_on_ack(acktr, rb, j);
- return;
- }
- }
-}
-
-void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr) {
- acktr->flags &= (uint16_t) ~(NGTCP2_ACKTR_FLAG_ACTIVE_ACK |
- NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK |
- NGTCP2_ACKTR_FLAG_CANCEL_TIMER);
- acktr->first_unacked_ts = UINT64_MAX;
- acktr->rx_npkt = 0;
-}
-
-int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr,
- ngtcp2_duration max_ack_delay,
- ngtcp2_tstamp ts) {
- return acktr->first_unacked_ts <= ts - max_ack_delay;
-}
-
-void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr) {
- acktr->flags |= NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_acktr.h b/deps/ngtcp2/lib/ngtcp2_acktr.h
deleted file mode 100644
index 38c1ebe2cf..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_acktr.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_ACKTR_H
-#define NGTCP2_ACKTR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_ringbuf.h"
-#include "ngtcp2_ksl.h"
-#include "ngtcp2_pkt.h"
-
-/* NGTCP2_ACKTR_MAX_ENT is the maximum number of ngtcp2_acktr_entry
- which ngtcp2_acktr stores. */
-#define NGTCP2_ACKTR_MAX_ENT 1024
-
-/* NGTCP2_NUM_IMMEDIATE_ACK_PKT is the maximum number of received
- packets which triggers the immediate ACK. */
-#define NGTCP2_NUM_IMMEDIATE_ACK_PKT 2
-
-struct ngtcp2_acktr_entry;
-typedef struct ngtcp2_acktr_entry ngtcp2_acktr_entry;
-
-struct ngtcp2_log;
-typedef struct ngtcp2_log ngtcp2_log;
-
-/*
- * ngtcp2_acktr_entry is a range of packets which need to be acked.
- */
-struct ngtcp2_acktr_entry {
- /* pkt_num is the largest packet number to acknowledge in this
- range. */
- int64_t pkt_num;
- /* len is the consecutive packets started from pkt_num which
- includes pkt_num itself counting in decreasing order. So pkt_num
- = 987 and len = 2, this entry includes packet 987 and 986. */
- size_t len;
- /* tstamp is the timestamp when a packet denoted by pkt_num is
- received. */
- ngtcp2_tstamp tstamp;
-};
-
-/*
- * ngtcp2_acktr_entry_new allocates memory for ent, and initializes it
- * with the given parameters. The pointer to the allocated object is
- * stored to |*ent|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_acktr_entry_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
- ngtcp2_tstamp tstamp, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_acktr_entry_del deallocates memory allocated for |ent|. It
- * deallocates memory pointed by |ent|.
- */
-void ngtcp2_acktr_entry_del(ngtcp2_acktr_entry *ent, const ngtcp2_mem *mem);
-
-typedef struct {
- /* largest_ack is the largest packet number in outgoing ACK frame */
- int64_t largest_ack;
- /* pkt_num is the packet number that ACK frame is included. */
- int64_t pkt_num;
-} ngtcp2_acktr_ack_entry;
-
-typedef enum {
- NGTCP2_ACKTR_FLAG_NONE = 0x00,
- /* NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK indicates that immediate
- acknowledgement is required. */
- NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK = 0x01,
- /* NGTCP2_ACKTR_FLAG_ACTIVE_ACK indicates that there are
- pending protected packet to be acknowledged. */
- NGTCP2_ACKTR_FLAG_ACTIVE_ACK = 0x02,
- /* NGTCP2_ACKTR_FLAG_ACK_FINISHED_ACK is set when server received
- acknowledgement for ACK which acknowledges the last handshake
- packet from client (which contains TLSv1.3 Finished message). */
- NGTCP2_ACKTR_FLAG_ACK_FINISHED_ACK = 0x80,
- /* NGTCP2_ACKTR_FLAG_CANCEL_TIMER is set when ACK delay timer is
- expired and canceled. */
- NGTCP2_ACKTR_FLAG_CANCEL_TIMER = 0x0100,
-} ngtcp2_acktr_flag;
-
-/*
- * ngtcp2_acktr tracks received packets which we have to send ack.
- */
-typedef struct {
- ngtcp2_ringbuf acks;
- /* ents includes ngtcp2_acktr_entry sorted by decreasing order of
- packet number. */
- ngtcp2_ksl ents;
- ngtcp2_log *log;
- const ngtcp2_mem *mem;
- /* flags is bitwise OR of zero, or more of ngtcp2_ack_flag. */
- uint16_t flags;
- /* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added
- first time after the last outgoing ACK frame. */
- ngtcp2_tstamp first_unacked_ts;
- /* rx_npkt is the number of packets received without sending ACK. */
- size_t rx_npkt;
-} ngtcp2_acktr;
-
-/*
- * ngtcp2_acktr_init initializes |acktr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_acktr_free frees resources allocated for |acktr|. It frees
- * any ngtcp2_acktr_entry added to |acktr|.
- */
-void ngtcp2_acktr_free(ngtcp2_acktr *acktr);
-
-/*
- * ngtcp2_acktr_add adds packet number |pkt_num| to |acktr|.
- * |active_ack| is nonzero if |pkt_num| is retransmittable packet.
- *
- * This function assumes that |acktr| does not contain |pkt_num|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * OUt of memory.
- */
-int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
- ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_acktr_forget removes all entries which have the packet
- * number that is equal to or less than ent->pkt_num. This function
- * assumes that |acktr| includes |ent|.
- */
-void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent);
-
-/*
- * ngtcp2_acktr_get returns the pointer to pointer to the entry which
- * has the largest packet number to be acked. If there is no entry,
- * returned value satisfies ngtcp2_ksl_it_end(&it) != 0.
- */
-ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr);
-
-/*
- * ngtcp2_acktr_empty returns nonzero if it has no packet to
- * acknowledge.
- */
-int ngtcp2_acktr_empty(ngtcp2_acktr *acktr);
-
-/*
- * ngtcp2_acktr_add_ack records outgoing ACK frame whose largest
- * acknowledged packet number is |largest_ack|. |pkt_num| is the
- * packet number of a packet in which ACK frame is included. This
- * function returns a pointer to the object it adds.
- */
-ngtcp2_acktr_ack_entry *
-ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t pkt_num, int64_t largest_ack);
-
-/*
- * ngtcp2_acktr_recv_ack processes the incoming ACK frame |fr|.
- * |pkt_num| is a packet number which includes |fr|. If we receive
- * ACK which acknowledges the ACKs added by ngtcp2_acktr_add_ack,
- * ngtcp2_acktr_entry which the outgoing ACK acknowledges is removed.
- */
-void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr);
-
-/*
- * ngtcp2_acktr_commit_ack tells |acktr| that ACK frame is generated.
- */
-void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr);
-
-/*
- * ngtcp2_acktr_require_active_ack returns nonzero if ACK frame should
- * be generated actively.
- */
-int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr,
- ngtcp2_duration max_ack_delay,
- ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_acktr_immediate_ack tells |acktr| that immediate
- * acknowledgement is required.
- */
-void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr);
-
-#endif /* NGTCP2_ACKTR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_addr.c b/deps/ngtcp2/lib/ngtcp2_addr.c
deleted file mode 100644
index cfc91c41e2..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_addr.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_addr.h"
-
-#include <string.h>
-#include <assert.h>
-
-#ifdef WIN32
-# include <winsock2.h>
-# include <ws2tcpip.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netinet/ip.h>
-# include <netinet/tcp.h>
-# include <arpa/inet.h>
-#endif
-
-ngtcp2_addr *ngtcp2_addr_init(ngtcp2_addr *dest, const struct sockaddr *addr,
- size_t addrlen, void *user_data) {
- dest->addrlen = addrlen;
- dest->addr = (struct sockaddr *)addr;
- dest->user_data = user_data;
- return dest;
-}
-
-void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src) {
- dest->addrlen = src->addrlen;
- if (src->addrlen) {
- memcpy(dest->addr, src->addr, src->addrlen);
- }
- dest->user_data = src->user_data;
-}
-
-void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const struct sockaddr *addr,
- size_t addrlen) {
- dest->addrlen = addrlen;
- if (addrlen) {
- memcpy(dest->addr, addr, addrlen);
- }
-}
-
-static int sockaddr_eq(const struct sockaddr *a, const struct sockaddr *b) {
- assert(a->sa_family == b->sa_family);
-
- switch (a->sa_family) {
- case AF_INET: {
- const struct sockaddr_in *ai = (const struct sockaddr_in *)(void *)a,
- *bi = (const struct sockaddr_in *)(void *)b;
- return ai->sin_port == bi->sin_port &&
- memcmp(&ai->sin_addr, &bi->sin_addr, sizeof(ai->sin_addr)) == 0;
- }
- case AF_INET6: {
- const struct sockaddr_in6 *ai = (const struct sockaddr_in6 *)(void *)a,
- *bi = (const struct sockaddr_in6 *)(void *)b;
- return ai->sin6_port == bi->sin6_port &&
- memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0;
- }
- default:
- assert(0);
- }
-}
-
-int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b) {
- return a->addr->sa_family == b->addr->sa_family &&
- sockaddr_eq(a->addr, b->addr);
-}
-
-int ngtcp2_addr_empty(const ngtcp2_addr *addr) { return addr->addrlen == 0; }
diff --git a/deps/ngtcp2/lib/ngtcp2_addr.h b/deps/ngtcp2/lib/ngtcp2_addr.h
deleted file mode 100644
index 238bb43518..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_addr.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_ADDR_H
-#define NGTCP2_ADDR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/*
- * ngtcp2_addr_copy copies |src| to |dest|. This function assumes
- * that dest->addr points to a buffer which have sufficient size to
- * store the copy.
- */
-void ngtcp2_addr_copy(ngtcp2_addr *dest, const ngtcp2_addr *src);
-
-/*
- * ngtcp2_addr_copy_byte copies |addr| of length |addrlen| into the
- * buffer pointed by dest->addr. dest->len is updated to have
- * |addrlen|. This function assumes that dest->addr points to a
- * buffer which have sufficient size to store the copy.
- */
-void ngtcp2_addr_copy_byte(ngtcp2_addr *dest, const struct sockaddr *addr,
- size_t addrlen);
-
-/*
- * ngtcp2_addr_eq returns nonzero if |a| equals |b|.
- */
-int ngtcp2_addr_eq(const ngtcp2_addr *a, const ngtcp2_addr *b);
-
-/*
- * ngtcp2_addr_empty returns nonzero if |addr| has zero length
- * address.
- */
-int ngtcp2_addr_empty(const ngtcp2_addr *addr);
-
-#endif /* NGTCP2_ADDR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_buf.c b/deps/ngtcp2/lib/ngtcp2_buf.c
deleted file mode 100644
index 373f23d91a..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_buf.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_buf.h"
-
-void ngtcp2_buf_init(ngtcp2_buf *buf, uint8_t *begin, size_t len) {
- buf->begin = buf->pos = buf->last = begin;
- buf->end = begin + len;
-}
-
-void ngtcp2_buf_reset(ngtcp2_buf *buf) { buf->pos = buf->last = buf->begin; }
-
-size_t ngtcp2_buf_left(const ngtcp2_buf *buf) {
- return (size_t)(buf->end - buf->last);
-}
-
-size_t ngtcp2_buf_len(const ngtcp2_buf *buf) {
- return (size_t)(buf->last - buf->pos);
-}
-
-size_t ngtcp2_buf_cap(const ngtcp2_buf *buf) {
- return (size_t)(buf->end - buf->begin);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_buf.h b/deps/ngtcp2/lib/ngtcp2_buf.h
deleted file mode 100644
index fe3d06a1c9..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_buf.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_BUF_H
-#define NGTCP2_BUF_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-typedef struct {
- /* begin points to the beginning of the buffer. */
- uint8_t *begin;
- /* end points to the one beyond of the last byte of the buffer */
- uint8_t *end;
- /* pos pointers to the start of data. Typically, this points to the
- point that next data should be read. Initially, it points to
- |begin|. */
- uint8_t *pos;
- /* last points to the one beyond of the last data of the buffer.
- Typically, new data is written at this point. Initially, it
- points to |begin|. */
- uint8_t *last;
-} ngtcp2_buf;
-
-/*
- * ngtcp2_buf_init initializes |buf| with the given buffer.
- */
-void ngtcp2_buf_init(ngtcp2_buf *buf, uint8_t *begin, size_t len);
-
-/*
- * ngtcp2_buf_reset resets pos and last fields to match begin field to
- * make ngtcp2_buf_len(buf) return 0.
- */
-void ngtcp2_buf_reset(ngtcp2_buf *buf);
-
-/*
- * ngtcp2_buf_left returns the number of additional bytes which can be
- * written to the underlying buffer. In other words, it returns
- * buf->end - buf->last.
- */
-size_t ngtcp2_buf_left(const ngtcp2_buf *buf);
-
-/*
- * ngtcp2_buf_len returns the number of bytes left to read. In other
- * words, it returns buf->last - buf->pos.
- */
-size_t ngtcp2_buf_len(const ngtcp2_buf *buf);
-
-/*
- * ngtcp2_buf_cap returns the capacity of the buffer. In other words,
- * it returns buf->end - buf->begin.
- */
-size_t ngtcp2_buf_cap(const ngtcp2_buf *buf);
-
-#endif /* NGTCP2_BUF_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/lib/ngtcp2_cc.c
deleted file mode 100644
index ef2e63a0ef..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_cc.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_cc.h"
-
-#include <assert.h>
-
-#if defined(_MSC_VER)
-# include <intrin.h>
-#endif
-
-#include "ngtcp2_log.h"
-#include "ngtcp2_macro.h"
-#include "ngtcp2_mem.h"
-#include "ngtcp2_rcvry.h"
-
-uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) {
- uint64_t n = 2 * max_udp_payload_size;
- n = ngtcp2_max(n, 14720);
- return ngtcp2_min(10 * max_udp_payload_size, n);
-}
-
-ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
- size_t pktlen, ngtcp2_pktns_id pktns_id,
- ngtcp2_tstamp ts_sent) {
- pkt->pkt_num = pkt_num;
- pkt->pktlen = pktlen;
- pkt->pktns_id = pktns_id;
- pkt->ts_sent = ts_sent;
-
- return pkt;
-}
-
-static void reno_cc_reset(ngtcp2_reno_cc *cc) {
- cc->max_delivery_rate_sec = 0;
- cc->target_cwnd = 0;
-}
-
-void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log) {
- cc->ccb.log = log;
- reno_cc_reset(cc);
-}
-
-void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc) { (void)cc; }
-
-int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
- const ngtcp2_mem *mem) {
- ngtcp2_reno_cc *reno_cc;
-
- reno_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_reno_cc));
- if (reno_cc == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_reno_cc_init(reno_cc, log);
-
- cc->ccb = &reno_cc->ccb;
- cc->on_pkt_acked = ngtcp2_cc_reno_cc_on_pkt_acked;
- cc->congestion_event = ngtcp2_cc_reno_cc_congestion_event;
- cc->on_persistent_congestion = ngtcp2_cc_reno_cc_on_persistent_congestion;
- cc->on_ack_recv = ngtcp2_cc_reno_cc_on_ack_recv;
- cc->reset = ngtcp2_cc_reno_cc_reset;
-
- return 0;
-}
-
-void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) {
- ngtcp2_reno_cc *reno_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_reno_cc, ccb);
-
- ngtcp2_reno_cc_free(reno_cc);
- ngtcp2_mem_free(mem, reno_cc);
-}
-
-static int in_congestion_recovery(const ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp sent_time) {
- return sent_time <= cstat->congestion_recovery_start_ts;
-}
-
-void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts) {
- ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
- (void)ts;
-
- if (in_congestion_recovery(cstat, pkt->ts_sent)) {
- return;
- }
-
- if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
- return;
- }
-
- if (cstat->cwnd < cstat->ssthresh) {
- cstat->cwnd += pkt->pktlen;
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64,
- pkt->pkt_num, cstat->cwnd);
- return;
- }
-
- cstat->cwnd += cstat->max_udp_payload_size * pkt->pktlen / cstat->cwnd;
-}
-
-void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts_sent,
- ngtcp2_tstamp ts) {
- ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
- uint64_t min_cwnd;
-
- if (in_congestion_recovery(cstat, ts_sent)) {
- return;
- }
-
- cstat->congestion_recovery_start_ts = ts;
- cstat->cwnd >>= NGTCP2_LOSS_REDUCTION_FACTOR_BITS;
- min_cwnd = 2 * cstat->max_udp_payload_size;
- cstat->cwnd = ngtcp2_max(cstat->cwnd, min_cwnd);
- cstat->ssthresh = cstat->cwnd;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "reduce cwnd because of packet loss cwnd=%" PRIu64,
- cstat->cwnd);
-}
-
-void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *ccx,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts) {
- (void)ccx;
- (void)ts;
-
- cstat->cwnd = 2 * cstat->max_udp_payload_size;
-}
-
-void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts) {
- ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
- uint64_t target_cwnd, initcwnd;
- (void)ts;
-
- /* TODO Use sliding window for min rtt measurement */
- /* TODO Use sliding window */
- cc->max_delivery_rate_sec =
- ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec);
-
- if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
- target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
- initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
- cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64
- " min_rtt=%" PRIu64,
- cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt);
- }
-}
-
-void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *ccx) {
- ngtcp2_reno_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_reno_cc, ccb);
- reno_cc_reset(cc);
-}
-
-static void cubic_cc_reset(ngtcp2_cubic_cc *cc) {
- cc->max_delivery_rate_sec = 0;
- cc->target_cwnd = 0;
- cc->w_last_max = 0;
- cc->w_tcp = 0;
- cc->origin_point = 0;
- cc->epoch_start = UINT64_MAX;
- cc->k = 0;
-
- cc->rtt_sample_count = 0;
- cc->current_round_min_rtt = UINT64_MAX;
- cc->last_round_min_rtt = UINT64_MAX;
- cc->window_end = -1;
-}
-
-void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log) {
- cc->ccb.log = log;
- cubic_cc_reset(cc);
-}
-
-void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc) { (void)cc; }
-
-int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
- const ngtcp2_mem *mem) {
- ngtcp2_cubic_cc *cubic_cc;
-
- cubic_cc = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_cubic_cc));
- if (cubic_cc == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_cubic_cc_init(cubic_cc, log);
-
- cc->ccb = &cubic_cc->ccb;
- cc->on_pkt_acked = ngtcp2_cc_cubic_cc_on_pkt_acked;
- cc->congestion_event = ngtcp2_cc_cubic_cc_congestion_event;
- cc->on_persistent_congestion = ngtcp2_cc_cubic_cc_on_persistent_congestion;
- cc->on_ack_recv = ngtcp2_cc_cubic_cc_on_ack_recv;
- cc->on_pkt_sent = ngtcp2_cc_cubic_cc_on_pkt_sent;
- cc->new_rtt_sample = ngtcp2_cc_cubic_cc_new_rtt_sample;
- cc->reset = ngtcp2_cc_cubic_cc_reset;
- cc->event = ngtcp2_cc_cubic_cc_event;
-
- return 0;
-}
-
-void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem) {
- ngtcp2_cubic_cc *cubic_cc = ngtcp2_struct_of(cc->ccb, ngtcp2_cubic_cc, ccb);
-
- ngtcp2_cubic_cc_free(cubic_cc);
- ngtcp2_mem_free(mem, cubic_cc);
-}
-
-static uint64_t ngtcp2_cbrt(uint64_t n) {
- int d;
- uint64_t a;
-
- if (n == 0) {
- return 0;
- }
-
-#if defined(_MSC_VER)
-# if defined(_M_X64)
- d = (int)__lzcnt64(n);
-# elif defined(_M_ARM64)
- {
- unsigned long index;
- d = sizeof(uint64_t) * CHAR_BIT;
- if (_BitScanReverse64(&index, n)) {
- d = d - 1 - index;
- }
- }
-# else
- if ((n >> 32) != 0) {
- d = __lzcnt((unsigned int)(n >> 32));
- } else {
- d = 32 + __lzcnt((unsigned int)n);
- }
-# endif
-#else
- d = __builtin_clzll(n);
-#endif
- a = 1ULL << ((64 - d) / 3 + 1);
-
- for (; a * a * a > n;) {
- a = (2 * a + n / a / a) / 3;
- }
- return a;
-}
-
-/* HyStart++ constants */
-#define NGTCP2_HS_MIN_SSTHRESH 16
-#define NGTCP2_HS_N_RTT_SAMPLE 8
-#define NGTCP2_HS_MIN_ETA (4 * NGTCP2_MILLISECONDS)
-#define NGTCP2_HS_MAX_ETA (16 * NGTCP2_MILLISECONDS)
-
-void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- ngtcp2_duration t, min_rtt, eta;
- uint64_t target;
- uint64_t tx, kx, time_delta, delta;
- uint64_t add, tcp_add;
- uint64_t m;
-
- if (pkt->pktns_id == NGTCP2_PKTNS_ID_APP && cc->window_end != -1 &&
- cc->window_end <= pkt->pkt_num) {
- cc->window_end = -1;
- }
-
- if (in_congestion_recovery(cstat, pkt->ts_sent)) {
- return;
- }
-
- if (cc->target_cwnd && cc->target_cwnd < cstat->cwnd) {
- return;
- }
-
- if (cstat->cwnd < cstat->ssthresh) {
- /* slow-start */
- cstat->cwnd += pkt->pktlen;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " acked, slow start cwnd=%" PRIu64,
- pkt->pkt_num, cstat->cwnd);
-
- if (cc->last_round_min_rtt != UINT64_MAX &&
- cc->current_round_min_rtt != UINT64_MAX &&
- cstat->cwnd >= NGTCP2_HS_MIN_SSTHRESH * cstat->max_udp_payload_size &&
- cc->rtt_sample_count >= NGTCP2_HS_N_RTT_SAMPLE) {
- eta = cc->last_round_min_rtt / 8;
-
- if (eta < NGTCP2_HS_MIN_ETA) {
- eta = NGTCP2_HS_MIN_ETA;
- } else if (eta > NGTCP2_HS_MAX_ETA) {
- eta = NGTCP2_HS_MAX_ETA;
- }
-
- if (cc->current_round_min_rtt >= cc->last_round_min_rtt + eta) {
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "HyStart++ exit slow start");
-
- cc->w_last_max = cstat->cwnd;
- cstat->ssthresh = cstat->cwnd;
- }
- }
-
- return;
- }
-
- /* congestion avoidance */
-
- if (cc->epoch_start == UINT64_MAX) {
- cc->epoch_start = ts;
- if (cstat->cwnd < cc->w_last_max) {
- cc->k = ngtcp2_cbrt((cc->w_last_max - cstat->cwnd) * 10 / 4 /
- cstat->max_udp_payload_size);
- cc->origin_point = cc->w_last_max;
- } else {
- cc->k = 0;
- cc->origin_point = cstat->cwnd;
- }
-
- cc->w_tcp = cstat->cwnd;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "cubic-ca epoch_start=%" PRIu64 " k=%" PRIu64
- " origin_point=%" PRIu64,
- cc->epoch_start, cc->k, cc->origin_point);
-
- cc->pending_add = 0;
- cc->pending_w_add = 0;
- }
-
- min_rtt = cstat->min_rtt == UINT64_MAX ? cstat->initial_rtt : cstat->min_rtt;
-
- t = ts + min_rtt - cc->epoch_start;
-
- tx = (t << 4) / NGTCP2_SECONDS;
- kx = (cc->k << 4);
-
- if (tx > kx) {
- time_delta = tx - kx;
- } else {
- time_delta = kx - tx;
- }
-
- delta = cstat->max_udp_payload_size *
- ((((time_delta * time_delta) >> 4) * time_delta) >> 8) * 4 / 10;
-
- if (tx > kx) {
- target = cc->origin_point + delta;
- } else {
- target = cc->origin_point - delta;
- }
-
- if (target > cstat->cwnd) {
- m = cc->pending_add + cstat->max_udp_payload_size * (target - cstat->cwnd);
- add = m / cstat->cwnd;
- cc->pending_add = m % cstat->cwnd;
- } else {
- m = cc->pending_add + cstat->max_udp_payload_size;
- add = m / (100 * cstat->cwnd);
- cc->pending_add = m % (100 * cstat->cwnd);
- }
-
- m = cc->pending_w_add + cstat->max_udp_payload_size * pkt->pktlen;
-
- cc->w_tcp += m / cstat->cwnd;
- cc->pending_w_add = m % cstat->cwnd;
-
- if (cc->w_tcp > cstat->cwnd) {
- tcp_add =
- cstat->max_udp_payload_size * (cc->w_tcp - cstat->cwnd) / cstat->cwnd;
- if (tcp_add > add) {
- add = tcp_add;
- }
- }
-
- cstat->cwnd += add;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " acked, cubic-ca cwnd=%" PRIu64 " t=%" PRIu64
- " k=%" PRIi64 " time_delta=%" PRIu64 " delta=%" PRIu64
- " target=%" PRIu64 " w_tcp=%" PRIu64,
- pkt->pkt_num, cstat->cwnd, t, cc->k, time_delta >> 4, delta,
- target, cc->w_tcp);
-}
-
-void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *ccx,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts_sent,
- ngtcp2_tstamp ts) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- uint64_t min_cwnd;
-
- if (in_congestion_recovery(cstat, ts_sent)) {
- return;
- }
-
- cstat->congestion_recovery_start_ts = ts;
-
- cc->epoch_start = UINT64_MAX;
- if (cstat->cwnd < cc->w_last_max) {
- cc->w_last_max = cstat->cwnd * 17 / 10 / 2;
- } else {
- cc->w_last_max = cstat->cwnd;
- }
-
- min_cwnd = 2 * cstat->max_udp_payload_size;
- cstat->ssthresh = cstat->cwnd * 7 / 10;
- cstat->ssthresh = ngtcp2_max(cstat->ssthresh, min_cwnd);
- cstat->cwnd = cstat->ssthresh;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "reduce cwnd because of packet loss cwnd=%" PRIu64,
- cstat->cwnd);
-}
-
-void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *ccx,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts) {
- (void)ccx;
- (void)ts;
-
- cstat->cwnd = 2 * cstat->max_udp_payload_size;
-}
-
-void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- uint64_t target_cwnd, initcwnd;
- (void)ts;
-
- /* TODO Use sliding window for min rtt measurement */
- /* TODO Use sliding window */
- cc->max_delivery_rate_sec =
- ngtcp2_max(cc->max_delivery_rate_sec, cstat->delivery_rate_sec);
-
- if (cstat->min_rtt != UINT64_MAX && cc->max_delivery_rate_sec) {
- target_cwnd = cc->max_delivery_rate_sec * cstat->min_rtt / NGTCP2_SECONDS;
- initcwnd = ngtcp2_cc_compute_initcwnd(cstat->max_udp_payload_size);
- cc->target_cwnd = ngtcp2_max(initcwnd, target_cwnd) * 289 / 100;
-
- ngtcp2_log_info(cc->ccb.log, NGTCP2_LOG_EVENT_RCV,
- "target_cwnd=%" PRIu64 " max_delivery_rate_sec=%" PRIu64
- " min_rtt=%" PRIu64,
- cc->target_cwnd, cc->max_delivery_rate_sec, cstat->min_rtt);
- }
-}
-
-void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- (void)cstat;
-
- if (pkt->pktns_id != NGTCP2_PKTNS_ID_APP || cc->window_end != -1) {
- return;
- }
-
- cc->window_end = pkt->pkt_num;
- cc->last_round_min_rtt = cc->current_round_min_rtt;
- cc->current_round_min_rtt = UINT64_MAX;
- cc->rtt_sample_count = 0;
-}
-
-void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- (void)ts;
-
- if (cc->window_end == -1) {
- return;
- }
-
- cc->current_round_min_rtt =
- ngtcp2_min(cc->current_round_min_rtt, cstat->latest_rtt);
- ++cc->rtt_sample_count;
-}
-
-void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *ccx) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- cubic_cc_reset(cc);
-}
-
-void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *ccx, ngtcp2_conn_stat *cstat,
- ngtcp2_cc_event_type event, ngtcp2_tstamp ts) {
- ngtcp2_cubic_cc *cc = ngtcp2_struct_of(ccx->ccb, ngtcp2_cubic_cc, ccb);
- ngtcp2_tstamp last_ts;
-
- if (event != NGTCP2_CC_EVENT_TYPE_TX_START || cc->epoch_start == UINT64_MAX) {
- return;
- }
-
- last_ts = cstat->last_tx_pkt_ts[NGTCP2_PKTNS_ID_APP];
- if (last_ts == UINT64_MAX || last_ts <= cc->epoch_start) {
- return;
- }
-
- assert(ts >= last_ts);
-
- cc->epoch_start += ts - last_ts;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_cc.h b/deps/ngtcp2/lib/ngtcp2_cc.h
deleted file mode 100644
index 05010d5725..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_cc.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CC_H
-#define NGTCP2_CC_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#define NGTCP2_LOSS_REDUCTION_FACTOR_BITS 1
-#define NGTCP2_PERSISTENT_CONGESTION_THRESHOLD 3
-
-struct ngtcp2_log;
-typedef struct ngtcp2_log ngtcp2_log;
-
-/*
- * ngtcp2_cc_compute_initcwnd computes initial cwnd.
- */
-uint64_t ngtcp2_cc_compute_initcwnd(size_t max_packet_size);
-
-ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num,
- size_t pktlen, ngtcp2_pktns_id pktns_id,
- ngtcp2_tstamp ts_sent);
-
-/* ngtcp2_reno_cc is the RENO congestion controller. */
-struct ngtcp2_reno_cc {
- ngtcp2_cc_base ccb;
- uint64_t max_delivery_rate_sec;
- uint64_t target_cwnd;
-};
-
-typedef struct ngtcp2_reno_cc ngtcp2_reno_cc;
-
-int ngtcp2_cc_reno_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
- const ngtcp2_mem *mem);
-
-void ngtcp2_cc_reno_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem);
-
-void ngtcp2_reno_cc_init(ngtcp2_reno_cc *cc, ngtcp2_log *log);
-
-void ngtcp2_reno_cc_free(ngtcp2_reno_cc *cc);
-
-void ngtcp2_cc_reno_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt, ngtcp2_tstamp ts);
-
-void ngtcp2_cc_reno_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts_sent,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_reno_cc_on_persistent_congestion(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_reno_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_reno_cc_reset(ngtcp2_cc *cc);
-
-/* ngtcp2_cubic_cc is CUBIC congestion controller. */
-typedef struct ngtcp2_cubic_cc {
- ngtcp2_cc_base ccb;
- uint64_t max_delivery_rate_sec;
- uint64_t target_cwnd;
- uint64_t w_last_max;
- uint64_t w_tcp;
- uint64_t origin_point;
- ngtcp2_tstamp epoch_start;
- uint64_t k;
- /* HyStart++ variables */
- size_t rtt_sample_count;
- uint64_t current_round_min_rtt;
- uint64_t last_round_min_rtt;
- int64_t window_end;
- uint64_t pending_add;
- uint64_t pending_w_add;
-} ngtcp2_cubic_cc;
-
-int ngtcp2_cc_cubic_cc_init(ngtcp2_cc *cc, ngtcp2_log *log,
- const ngtcp2_mem *mem);
-
-void ngtcp2_cc_cubic_cc_free(ngtcp2_cc *cc, const ngtcp2_mem *mem);
-
-void ngtcp2_cubic_cc_init(ngtcp2_cubic_cc *cc, ngtcp2_log *log);
-
-void ngtcp2_cubic_cc_free(ngtcp2_cubic_cc *cc);
-
-void ngtcp2_cc_cubic_cc_on_pkt_acked(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_cubic_cc_congestion_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts_sent,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_cubic_cc_on_persistent_congestion(ngtcp2_cc *cc,
- ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_cubic_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_cubic_cc_on_pkt_sent(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- const ngtcp2_cc_pkt *pkt);
-
-void ngtcp2_cc_cubic_cc_new_rtt_sample(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_tstamp ts);
-
-void ngtcp2_cc_cubic_cc_reset(ngtcp2_cc *cc);
-
-void ngtcp2_cc_cubic_cc_event(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat,
- ngtcp2_cc_event_type event, ngtcp2_tstamp ts);
-
-#endif /* NGTCP2_CC_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_cid.c b/deps/ngtcp2/lib/ngtcp2_cid.c
deleted file mode 100644
index 126e3c4a51..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_cid.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_cid.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "ngtcp2_path.h"
-#include "ngtcp2_str.h"
-
-void ngtcp2_cid_zero(ngtcp2_cid *cid) { cid->datalen = 0; }
-
-void ngtcp2_cid_init(ngtcp2_cid *cid, const uint8_t *data, size_t datalen) {
- assert(datalen <= NGTCP2_MAX_CIDLEN);
-
- cid->datalen = datalen;
- if (datalen) {
- ngtcp2_cpymem(cid->data, data, datalen);
- }
-}
-
-int ngtcp2_cid_eq(const ngtcp2_cid *cid, const ngtcp2_cid *other) {
- return cid->datalen == other->datalen &&
- 0 == memcmp(cid->data, other->data, cid->datalen);
-}
-
-int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs) {
- int s = lhs->datalen < rhs->datalen;
- size_t n = s ? lhs->datalen : rhs->datalen;
- int c = memcmp(lhs->data, rhs->data, n);
-
- return c < 0 || (c == 0 && s);
-}
-
-int ngtcp2_cid_empty(const ngtcp2_cid *cid) { return cid->datalen == 0; }
-
-void ngtcp2_scid_init(ngtcp2_scid *scid, uint64_t seq, const ngtcp2_cid *cid,
- const uint8_t *token) {
- scid->pe.index = NGTCP2_PQ_BAD_INDEX;
- scid->seq = seq;
- scid->cid = *cid;
- scid->ts_retired = UINT64_MAX;
- scid->flags = NGTCP2_SCID_FLAG_NONE;
- if (token) {
- memcpy(scid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN);
- } else {
- memset(scid->token, 0, NGTCP2_STATELESS_RESET_TOKENLEN);
- }
-}
-
-void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src) {
- ngtcp2_scid_init(dest, src->seq, &src->cid, src->token);
- dest->ts_retired = src->ts_retired;
- dest->flags = src->flags;
-}
-
-void ngtcp2_dcid_init(ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid,
- const uint8_t *token) {
- dcid->seq = seq;
- dcid->cid = *cid;
- if (token) {
- memcpy(dcid->token, token, NGTCP2_STATELESS_RESET_TOKENLEN);
- } else {
- memset(dcid->token, 0, NGTCP2_STATELESS_RESET_TOKENLEN);
- }
- ngtcp2_path_storage_zero(&dcid->ps);
- dcid->ts_retired = UINT64_MAX;
-}
-
-void ngtcp2_dcid_copy(ngtcp2_dcid *dest, const ngtcp2_dcid *src) {
- ngtcp2_dcid_init(dest, src->seq, &src->cid, src->token);
- ngtcp2_path_copy(&dest->ps.path, &src->ps.path);
- dest->ts_retired = src->ts_retired;
-}
-
-void ngtcp2_dcid_copy_no_path(ngtcp2_dcid *dest, const ngtcp2_dcid *src) {
- dest->seq = src->seq;
- dest->cid = src->cid;
- memcpy(dest->token, src->token, NGTCP2_STATELESS_RESET_TOKENLEN);
-
- dest->ts_retired = src->ts_retired;
-}
-
-int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq,
- const ngtcp2_cid *cid, const uint8_t *token) {
- if (dcid->seq == seq) {
- return ngtcp2_cid_eq(&dcid->cid, cid) &&
- memcmp(dcid->token, token,
- NGTCP2_STATELESS_RESET_TOKENLEN) == 0
- ? 0
- : NGTCP2_ERR_PROTO;
- }
-
- return !ngtcp2_cid_eq(&dcid->cid, cid) ? 0 : NGTCP2_ERR_PROTO;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_cid.h b/deps/ngtcp2/lib/ngtcp2_cid.h
deleted file mode 100644
index fe5576ae46..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_cid.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CID_H
-#define NGTCP2_CID_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_pq.h"
-#include "ngtcp2_path.h"
-
-typedef enum {
- NGTCP2_SCID_FLAG_NONE,
- NGTCP2_SCID_FLAG_USED = 0x01,
- NGTCP2_SCID_FLAG_RETIRED = 0x02,
-} ngtcp2_scid_flag;
-
-typedef struct {
- ngtcp2_pq_entry pe;
- /* seq is the sequence number associated to the CID. */
- uint64_t seq;
- /* cid is a connection ID */
- ngtcp2_cid cid;
- /* ts_retired is the timestamp when peer tells that this CID is
- retired. */
- ngtcp2_tstamp ts_retired;
- /* flags is the bitwise OR of zero or more of ngtcp2_scid_flag. */
- uint8_t flags;
- /* token is a stateless reset token associated to this CID.
- Actually, the stateless reset token is tied to the connection,
- not to the particular connection ID. */
- uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN];
-} ngtcp2_scid;
-
-typedef struct {
- /* seq is the sequence number associated to the CID. */
- uint64_t seq;
- /* cid is a connection ID */
- ngtcp2_cid cid;
- /* path is a path which cid is bound to. The addresses are zero
- length if cid has not been bound to a particular path yet. */
- ngtcp2_path_storage ps;
- /* ts_retired is the timestamp when peer tells that this CID is
- retired. */
- ngtcp2_tstamp ts_retired;
- /* token is a stateless reset token associated to this CID.
- Actually, the stateless reset token is tied to the connection,
- not to the particular connection ID. */
- uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN];
-} ngtcp2_dcid;
-
-/* ngtcp2_cid_zero makes |cid| zero-length. */
-void ngtcp2_cid_zero(ngtcp2_cid *cid);
-
-/*
- * ngtcp2_cid_eq returns nonzero if |cid| and |other| share the same
- * connection ID.
- */
-int ngtcp2_cid_eq(const ngtcp2_cid *cid, const ngtcp2_cid *other);
-
-/*
- * ngtcp2_cid_less returns nonzero if |lhs| is lexicographical smaller
- * than |rhs|.
- */
-int ngtcp2_cid_less(const ngtcp2_cid *lhs, const ngtcp2_cid *rhs);
-
-/*
- * ngtcp2_cid_empty returns nonzero if |cid| includes empty connection
- * ID.
- */
-int ngtcp2_cid_empty(const ngtcp2_cid *cid);
-
-/*
- * ngtcp2_scid_init initializes |scid| with the given parameters. If
- * |token| is NULL, the function fills scid->token it with 0. |token|
- * must be NGTCP2_STATELESS_RESET_TOKENLEN bytes long.
- */
-void ngtcp2_scid_init(ngtcp2_scid *scid, uint64_t seq, const ngtcp2_cid *cid,
- const uint8_t *token);
-
-/*
- * ngtcp2_scid_copy copies |src| into |dest|.
- */
-void ngtcp2_scid_copy(ngtcp2_scid *dest, const ngtcp2_scid *src);
-
-/*
- * ngtcp2_dcid_init initializes |dcid| with the given parameters. If
- * |token| is NULL, the function fills dcid->token it with 0. |token|
- * must be NGTCP2_STATELESS_RESET_TOKENLEN bytes long.
- */
-void ngtcp2_dcid_init(ngtcp2_dcid *dcid, uint64_t seq, const ngtcp2_cid *cid,
- const uint8_t *token);
-
-/*
- * ngtcp2_dcid_copy copies |src| into |dest|.
- */
-void ngtcp2_dcid_copy(ngtcp2_dcid *dest, const ngtcp2_dcid *src);
-
-/*
- * ngtcp2_dcid_copy_no_path behaves like ngtcp2_dcid_copy, but it does
- * not copy path.
- */
-void ngtcp2_dcid_copy_no_path(ngtcp2_dcid *dest, const ngtcp2_dcid *src);
-
-/*
- * ngtcp2_dcid_verify_uniqueness verifies uniqueness of (|seq|, |cid|,
- * |token|) tuple against |dcid|.
- */
-int ngtcp2_dcid_verify_uniqueness(ngtcp2_dcid *dcid, uint64_t seq,
- const ngtcp2_cid *cid, const uint8_t *token);
-
-#endif /* NGTCP2_CID_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/lib/ngtcp2_conn.c
deleted file mode 100644
index ff8c608b77..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_conn.c
+++ /dev/null
@@ -1,10100 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_conn.h"
-
-#include <string.h>
-#include <assert.h>
-#include <math.h>
-
-#include "ngtcp2_macro.h"
-#include "ngtcp2_log.h"
-#include "ngtcp2_cid.h"
-#include "ngtcp2_conv.h"
-#include "ngtcp2_vec.h"
-#include "ngtcp2_addr.h"
-#include "ngtcp2_path.h"
-#include "ngtcp2_rcvry.h"
-
-/*
- * conn_local_stream returns nonzero if |stream_id| indicates that it
- * is the stream initiated by local endpoint.
- */
-static int conn_local_stream(ngtcp2_conn *conn, int64_t stream_id) {
- return (uint8_t)(stream_id & 1) == conn->server;
-}
-
-/*
- * bidi_stream returns nonzero if |stream_id| is a bidirectional
- * stream ID.
- */
-static int bidi_stream(int64_t stream_id) { return (stream_id & 0x2) == 0; }
-
-static int conn_call_recv_client_initial(ngtcp2_conn *conn,
- const ngtcp2_cid *dcid) {
- int rv;
-
- assert(conn->callbacks.recv_client_initial);
-
- rv = conn->callbacks.recv_client_initial(conn, dcid, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_handshake_completed(ngtcp2_conn *conn) {
- int rv;
-
- if (!conn->callbacks.handshake_completed) {
- return 0;
- }
-
- rv = conn->callbacks.handshake_completed(conn, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_recv_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint32_t flags, uint64_t offset,
- const uint8_t *data, size_t datalen) {
- int rv;
-
- if (!conn->callbacks.recv_stream_data) {
- return 0;
- }
-
- rv = conn->callbacks.recv_stream_data(conn, flags, strm->stream_id, offset,
- data, datalen, conn->user_data,
- strm->stream_user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_recv_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset, const uint8_t *data,
- size_t datalen) {
- int rv;
-
- assert(conn->callbacks.recv_crypto_data);
-
- rv = conn->callbacks.recv_crypto_data(conn, crypto_level, offset, data,
- datalen, conn->user_data);
- switch (rv) {
- case 0:
- case NGTCP2_ERR_CRYPTO:
- case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
- case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
- case NGTCP2_ERR_TRANSPORT_PARAM:
- case NGTCP2_ERR_PROTO:
- case NGTCP2_ERR_CALLBACK_FAILURE:
- return rv;
- default:
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-}
-
-static int conn_call_stream_open(ngtcp2_conn *conn, ngtcp2_strm *strm) {
- int rv;
-
- if (!conn->callbacks.stream_open) {
- return 0;
- }
-
- rv = conn->callbacks.stream_open(conn, strm->stream_id, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_stream_close(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- int rv;
-
- if (!conn->callbacks.stream_close) {
- return 0;
- }
-
- rv = conn->callbacks.stream_close(conn, strm->stream_id, app_error_code,
- conn->user_data, strm->stream_user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_stream_reset(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t final_size, uint64_t app_error_code,
- void *stream_user_data) {
- int rv;
-
- if (!conn->callbacks.stream_reset) {
- return 0;
- }
-
- rv = conn->callbacks.stream_reset(conn, stream_id, final_size, app_error_code,
- conn->user_data, stream_user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_extend_max_local_streams_bidi(ngtcp2_conn *conn,
- uint64_t max_streams) {
- int rv;
-
- if (!conn->callbacks.extend_max_local_streams_bidi) {
- return 0;
- }
-
- rv = conn->callbacks.extend_max_local_streams_bidi(conn, max_streams,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_extend_max_local_streams_uni(ngtcp2_conn *conn,
- uint64_t max_streams) {
- int rv;
-
- if (!conn->callbacks.extend_max_local_streams_uni) {
- return 0;
- }
-
- rv = conn->callbacks.extend_max_local_streams_uni(conn, max_streams,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid,
- uint8_t *token, size_t cidlen) {
- int rv;
-
- assert(conn->callbacks.get_new_connection_id);
-
- rv = conn->callbacks.get_new_connection_id(conn, cid, token, cidlen,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_remove_connection_id(ngtcp2_conn *conn,
- const ngtcp2_cid *cid) {
- int rv;
-
- if (!conn->callbacks.remove_connection_id) {
- return 0;
- }
-
- rv = conn->callbacks.remove_connection_id(conn, cid, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_path_validation(ngtcp2_conn *conn, const ngtcp2_path *path,
- ngtcp2_path_validation_result res) {
- int rv;
-
- if (!conn->callbacks.path_validation) {
- return 0;
- }
-
- rv = conn->callbacks.path_validation(conn, path, res, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_select_preferred_addr(ngtcp2_conn *conn,
- ngtcp2_addr *dest) {
- int rv;
-
- if (!conn->callbacks.select_preferred_addr) {
- return 0;
- }
-
- assert(conn->remote.transport_params.preferred_address_present);
-
- rv = conn->callbacks.select_preferred_addr(
- conn, dest, &conn->remote.transport_params.preferred_address,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_extend_max_remote_streams_bidi(ngtcp2_conn *conn,
- uint64_t max_streams) {
- int rv;
-
- if (!conn->callbacks.extend_max_remote_streams_bidi) {
- return 0;
- }
-
- rv = conn->callbacks.extend_max_remote_streams_bidi(conn, max_streams,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_extend_max_remote_streams_uni(ngtcp2_conn *conn,
- uint64_t max_streams) {
- int rv;
-
- if (!conn->callbacks.extend_max_remote_streams_uni) {
- return 0;
- }
-
- rv = conn->callbacks.extend_max_remote_streams_uni(conn, max_streams,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_extend_max_stream_data(ngtcp2_conn *conn,
- ngtcp2_strm *strm,
- int64_t stream_id,
- uint64_t datalen) {
- int rv;
-
- if (!conn->callbacks.extend_max_stream_data) {
- return 0;
- }
-
- rv = conn->callbacks.extend_max_stream_data(
- conn, stream_id, datalen, conn->user_data, strm->stream_user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_dcid_status(ngtcp2_conn *conn,
- ngtcp2_connection_id_status_type type,
- const ngtcp2_dcid *dcid) {
- int rv;
-
- if (!conn->callbacks.dcid_status) {
- return 0;
- }
-
- rv = conn->callbacks.dcid_status(
- conn, (int)type, dcid->seq, &dcid->cid,
- ngtcp2_check_invalid_stateless_reset_token(dcid->token) ? NULL
- : dcid->token,
- conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-static int conn_call_activate_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid) {
- return conn_call_dcid_status(conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE,
- dcid);
-}
-
-static int conn_call_deactivate_dcid(ngtcp2_conn *conn,
- const ngtcp2_dcid *dcid) {
- return conn_call_dcid_status(
- conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE, dcid);
-}
-
-static void conn_call_delete_crypto_aead_ctx(ngtcp2_conn *conn,
- ngtcp2_crypto_aead_ctx *aead_ctx) {
- if (!aead_ctx->native_handle) {
- return;
- }
-
- assert(conn->callbacks.delete_crypto_aead_ctx);
-
- conn->callbacks.delete_crypto_aead_ctx(conn, aead_ctx, conn->user_data);
-}
-
-static void
-conn_call_delete_crypto_cipher_ctx(ngtcp2_conn *conn,
- ngtcp2_crypto_cipher_ctx *cipher_ctx) {
- if (!cipher_ctx->native_handle) {
- return;
- }
-
- assert(conn->callbacks.delete_crypto_cipher_ctx);
-
- conn->callbacks.delete_crypto_cipher_ctx(conn, cipher_ctx, conn->user_data);
-}
-
-static int crypto_offset_less(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs) {
- return *(int64_t *)lhs < *(int64_t *)rhs;
-}
-
-static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id,
- ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log,
- ngtcp2_qlog *qlog, const ngtcp2_mem *mem) {
- int rv;
-
- memset(pktns, 0, sizeof(*pktns));
-
- rv = ngtcp2_gaptr_init(&pktns->rx.pngap, mem);
- if (rv != 0) {
- return rv;
- }
-
- pktns->tx.last_pkt_num = -1;
- pktns->rx.max_pkt_num = -1;
-
- rv = ngtcp2_acktr_init(&pktns->acktr, log, mem);
- if (rv != 0) {
- goto fail_acktr_init;
- }
-
- rv = ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE, 0, 0,
- NULL, mem);
- if (rv != 0) {
- goto fail_crypto_init;
- }
-
- rv = ngtcp2_ksl_init(&pktns->crypto.tx.frq, crypto_offset_less,
- sizeof(uint64_t), mem);
- if (rv != 0) {
- goto fail_tx_frq_init;
- }
-
- ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, log,
- qlog, mem);
-
- return 0;
-
-fail_tx_frq_init:
- ngtcp2_strm_free(&pktns->crypto.strm);
-fail_crypto_init:
- ngtcp2_acktr_free(&pktns->acktr);
-fail_acktr_init:
- ngtcp2_gaptr_free(&pktns->rx.pngap);
-
- return rv;
-}
-
-static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id,
- ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log,
- ngtcp2_qlog *qlog, const ngtcp2_mem *mem) {
- int rv;
-
- *ppktns = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pktns));
- if (*ppktns == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = pktns_init(*ppktns, pktns_id, rst, cc, log, qlog, mem);
- if (rv != 0) {
- ngtcp2_mem_free(mem, *ppktns);
- }
-
- return rv;
-}
-
-static int cycle_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) {
- ngtcp2_strm *ls = ngtcp2_struct_of(lhs, ngtcp2_strm, pe);
- ngtcp2_strm *rs = ngtcp2_struct_of(rhs, ngtcp2_strm, pe);
-
- if (ls->cycle == rs->cycle) {
- return ls->stream_id < rs->stream_id;
- }
-
- return rs->cycle - ls->cycle <= 1;
-}
-
-static void delete_buffed_pkts(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem) {
- ngtcp2_pkt_chain *next;
-
- for (; pc;) {
- next = pc->next;
- ngtcp2_pkt_chain_del(pc, mem);
- pc = next;
- }
-}
-
-static void pktns_free(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) {
- ngtcp2_frame_chain *frc;
- ngtcp2_ksl_it it;
-
- delete_buffed_pkts(pktns->rx.buffed_pkts, mem);
-
- ngtcp2_frame_chain_list_del(pktns->tx.frq, mem);
-
- ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, mem);
- ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, mem);
-
- for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- frc = ngtcp2_ksl_it_get(&it);
- ngtcp2_frame_chain_del(frc, mem);
- }
-
- ngtcp2_ksl_free(&pktns->crypto.tx.frq);
- ngtcp2_rtb_free(&pktns->rtb);
- ngtcp2_strm_free(&pktns->crypto.strm);
- ngtcp2_acktr_free(&pktns->acktr);
- ngtcp2_gaptr_free(&pktns->rx.pngap);
-}
-
-static void pktns_del(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) {
- if (pktns == NULL) {
- return;
- }
-
- pktns_free(pktns, mem);
-
- ngtcp2_mem_free(mem, pktns);
-}
-
-static void cc_del(ngtcp2_cc *cc, ngtcp2_cc_algo cc_algo,
- const ngtcp2_mem *mem) {
- switch (cc_algo) {
- case NGTCP2_CC_ALGO_RENO:
- ngtcp2_cc_reno_cc_free(cc, mem);
- break;
- case NGTCP2_CC_ALGO_CUBIC:
- ngtcp2_cc_cubic_cc_free(cc, mem);
- break;
- default:
- break;
- }
-}
-
-static int cid_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return ngtcp2_cid_less(lhs, rhs);
-}
-
-static int ts_retired_less(const ngtcp2_pq_entry *lhs,
- const ngtcp2_pq_entry *rhs) {
- const ngtcp2_scid *a = ngtcp2_struct_of(lhs, ngtcp2_scid, pe);
- const ngtcp2_scid *b = ngtcp2_struct_of(rhs, ngtcp2_scid, pe);
-
- return a->ts_retired < b->ts_retired;
-}
-
-/*
- * conn_reset_conn_stat_cc resets congestion state in |cstat|.
- */
-static void conn_reset_conn_stat_cc(ngtcp2_conn *conn,
- ngtcp2_conn_stat *cstat) {
- cstat->latest_rtt = 0;
- cstat->min_rtt = UINT64_MAX;
- cstat->smoothed_rtt = conn->local.settings.initial_rtt;
- cstat->rttvar = conn->local.settings.initial_rtt / 2;
- cstat->pto_count = 0;
- cstat->loss_detection_timer = 0;
- cstat->cwnd =
- ngtcp2_cc_compute_initcwnd(conn->local.settings.max_udp_payload_size);
- cstat->ssthresh = UINT64_MAX;
- cstat->congestion_recovery_start_ts = 0;
- cstat->bytes_in_flight = 0;
- cstat->delivery_rate_sec = 0;
- cstat->recv_rate_sec = 0;
-}
-
-/*
- * reset_conn_stat_recovery resets the fields related to the recovery
- * function
- */
-static void reset_conn_stat_recovery(ngtcp2_conn_stat *cstat) {
- // Initializes them with UINT64_MAX.
- memset(cstat->loss_time, 0xff, sizeof(cstat->loss_time));
- memset(cstat->last_tx_pkt_ts, 0xff, sizeof(cstat->last_tx_pkt_ts));
-}
-
-/*
- * conn_reset_conn_stat resets |cstat|. The following fields are not
- * reset: initial_rtt, max_udp_payload_size, bytes_sent, and
- * bytes_recv.
- */
-static void conn_reset_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
- conn_reset_conn_stat_cc(conn, cstat);
- reset_conn_stat_recovery(cstat);
-}
-
-static void conn_reset_rx_rate(ngtcp2_conn *conn) {
- conn->rx.rate.start_ts = UINT64_MAX;
- conn->rx.rate.received = 0;
-}
-
-static void conn_update_recv_rate(ngtcp2_conn *conn, size_t datalen,
- ngtcp2_tstamp ts) {
- uint64_t bps;
- ngtcp2_duration window;
-
- conn->rx.rate.received += datalen;
-
- if (conn->rx.rate.start_ts == UINT64_MAX) {
- conn->rx.rate.start_ts = ts;
- return;
- }
-
- assert(conn->cstat.min_rtt);
-
- window = conn->cstat.min_rtt == UINT64_MAX ? conn->cstat.initial_rtt
- : conn->cstat.min_rtt * 2;
-
- /* If settings.initial_rtt is zero for whatever reason then window
- can be zero and we can end up with a division by zero error when
- bps is set below. If this assert fails, check that
- settings.initial_rtt is not zero. */
- assert(window);
-
- if (window > ts - conn->rx.rate.start_ts) {
- return;
- }
-
- bps = conn->rx.rate.received * NGTCP2_SECONDS / (ts - conn->rx.rate.start_ts);
-
- if (conn->cstat.recv_rate_sec == 0) {
- conn->cstat.recv_rate_sec = bps;
- } else {
- conn->cstat.recv_rate_sec = (conn->cstat.recv_rate_sec * 3 + bps) / 4;
- }
-
- conn_reset_rx_rate(conn);
-
- if (conn->cstat.min_rtt != UINT64_MAX) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "recv_rate_sec=%" PRIu64 " bytes/min_rtt=%" PRIu64,
- conn->cstat.recv_rate_sec,
- conn->cstat.recv_rate_sec * conn->cstat.min_rtt /
- NGTCP2_SECONDS);
- }
-}
-
-static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) {
- ngtcp2_ksl_it it;
-
- for (it = ngtcp2_ksl_begin(scids); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ngtcp2_mem_free(mem, ngtcp2_ksl_it_get(&it));
- }
-}
-
-static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_path *path,
- uint32_t version, const ngtcp2_conn_callbacks *callbacks,
- const ngtcp2_settings *settings, const ngtcp2_mem *mem,
- void *user_data, int server) {
- int rv;
- ngtcp2_scid *scident;
- const ngtcp2_transport_params *params = &settings->transport_params;
- uint8_t *buf;
-
- assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE);
-
- if (mem == NULL) {
- mem = ngtcp2_mem_default();
- }
-
- *pconn = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_conn));
- if (*pconn == NULL) {
- rv = NGTCP2_ERR_NOMEM;
- goto fail_conn;
- }
-
- rv = ngtcp2_ringbuf_init(&(*pconn)->dcid.unused, NGTCP2_MAX_DCID_POOL_SIZE,
- sizeof(ngtcp2_dcid), mem);
- if (rv != 0) {
- goto fail_dcid_unused_init;
- }
-
- rv =
- ngtcp2_ringbuf_init(&(*pconn)->dcid.retired, NGTCP2_MAX_DCID_RETIRED_SIZE,
- sizeof(ngtcp2_dcid), mem);
- if (rv != 0) {
- goto fail_dcid_retired_init;
- }
-
- rv = ngtcp2_gaptr_init(&(*pconn)->dcid.seqgap, mem);
- if (rv != 0) {
- goto fail_seqgap_init;
- }
-
- rv = ngtcp2_ksl_init(&(*pconn)->scid.set, cid_less, sizeof(ngtcp2_cid), mem);
- if (rv != 0) {
- goto fail_scid_set_init;
- }
-
- ngtcp2_pq_init(&(*pconn)->scid.used, ts_retired_less, mem);
-
- rv = ngtcp2_map_init(&(*pconn)->strms, mem);
- if (rv != 0) {
- goto fail_strms_init;
- }
-
- ngtcp2_pq_init(&(*pconn)->tx.strmq, cycle_less, mem);
-
- rv = ngtcp2_idtr_init(&(*pconn)->remote.bidi.idtr, !server, mem);
- if (rv != 0) {
- goto fail_remote_bidi_idtr_init;
- }
-
- rv = ngtcp2_idtr_init(&(*pconn)->remote.uni.idtr, !server, mem);
- if (rv != 0) {
- goto fail_remote_uni_idtr_init;
- }
-
- rv = ngtcp2_ringbuf_init(&(*pconn)->rx.path_challenge, 4,
- sizeof(ngtcp2_path_challenge_entry), mem);
- if (rv != 0) {
- goto fail_rx_path_challenge_init;
- }
-
- ngtcp2_log_init(&(*pconn)->log, scid, settings->log_printf,
- settings->initial_ts, user_data);
- ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog.write, settings->initial_ts,
- user_data);
- if ((*pconn)->qlog.write) {
- buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN);
- if (buf == NULL) {
- goto fail_qlog_buf;
- }
- ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN);
- }
-
- (*pconn)->local.settings = *settings;
-
- if (settings->token.len) {
- buf = ngtcp2_mem_malloc(mem, settings->token.len);
- if (buf == NULL) {
- goto fail_token;
- }
- memcpy(buf, settings->token.base, settings->token.len);
- (*pconn)->local.settings.token.base = buf;
- } else {
- (*pconn)->local.settings.token.base = NULL;
- (*pconn)->local.settings.token.len = 0;
- }
-
- if (settings->max_udp_payload_size == 0) {
- (*pconn)->local.settings.max_udp_payload_size = NGTCP2_DEFAULT_MAX_PKTLEN;
- }
-
- conn_reset_conn_stat(*pconn, &(*pconn)->cstat);
- (*pconn)->cstat.initial_rtt = settings->initial_rtt;
- (*pconn)->cstat.max_udp_payload_size =
- (*pconn)->local.settings.max_udp_payload_size;
-
- ngtcp2_rst_init(&(*pconn)->rst);
-
- (*pconn)->cc_algo = settings->cc_algo;
-
- switch (settings->cc_algo) {
- case NGTCP2_CC_ALGO_RENO:
- rv = ngtcp2_cc_reno_cc_init(&(*pconn)->cc, &(*pconn)->log, mem);
- if (rv != 0) {
- goto fail_cc_init;
- }
- break;
- case NGTCP2_CC_ALGO_CUBIC:
- rv = ngtcp2_cc_cubic_cc_init(&(*pconn)->cc, &(*pconn)->log, mem);
- if (rv != 0) {
- goto fail_cc_init;
- }
- break;
- case NGTCP2_CC_ALGO_CUSTOM:
- assert(settings->cc);
- (*pconn)->cc = *settings->cc;
- (*pconn)->cc.ccb->log = &(*pconn)->log;
- break;
- default:
- assert(0);
- }
-
- conn_reset_rx_rate(*pconn);
-
- rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_PKTNS_ID_INITIAL, &(*pconn)->rst,
- &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
- if (rv != 0) {
- goto fail_in_pktns_init;
- }
-
- rv = pktns_new(&(*pconn)->hs_pktns, NGTCP2_PKTNS_ID_HANDSHAKE, &(*pconn)->rst,
- &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
- if (rv != 0) {
- goto fail_hs_pktns_init;
- }
-
- rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APP, &(*pconn)->rst,
- &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem);
- if (rv != 0) {
- goto fail_pktns_init;
- }
-
- scident = ngtcp2_mem_malloc(mem, sizeof(*scident));
- if (scident == NULL) {
- rv = NGTCP2_ERR_NOMEM;
- goto fail_scident;
- }
-
- /* Set stateless reset token later if it is available in the local
- transport parameters */
- ngtcp2_scid_init(scident, 0, scid, NULL);
-
- rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL, &scident->cid, scident);
- if (rv != 0) {
- goto fail_scid_set_insert;
- }
-
- scident = NULL;
-
- ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL);
- ngtcp2_path_copy(&(*pconn)->dcid.current.ps.path, path);
-
- rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1);
- if (rv != 0) {
- goto fail_seqgap_push;
- }
-
- (*pconn)->server = server;
- (*pconn)->oscid = *scid;
- (*pconn)->callbacks = *callbacks;
- (*pconn)->version = version;
- (*pconn)->mem = mem;
- (*pconn)->user_data = user_data;
- (*pconn)->idle_ts = settings->initial_ts;
- (*pconn)->crypto.key_update.confirmed_ts = UINT64_MAX;
-
- ngtcp2_qlog_start(&(*pconn)->qlog, server ? &settings->qlog.odcid : dcid,
- server);
-
- return 0;
-
-fail_seqgap_push:
-fail_scid_set_insert:
- ngtcp2_mem_free(mem, scident);
-fail_scident:
- ngtcp2_mem_free(mem, (*pconn)->local.settings.token.base);
-fail_token:
- pktns_free(&(*pconn)->pktns, mem);
-fail_pktns_init:
- pktns_del((*pconn)->hs_pktns, mem);
-fail_hs_pktns_init:
- pktns_del((*pconn)->in_pktns, mem);
-fail_in_pktns_init:
- cc_del(&(*pconn)->cc, settings->cc_algo, mem);
-fail_cc_init:
- ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin);
-fail_qlog_buf:
- ngtcp2_ringbuf_free(&(*pconn)->rx.path_challenge);
-fail_rx_path_challenge_init:
- ngtcp2_idtr_free(&(*pconn)->remote.uni.idtr);
-fail_remote_uni_idtr_init:
- ngtcp2_idtr_free(&(*pconn)->remote.bidi.idtr);
-fail_remote_bidi_idtr_init:
- ngtcp2_map_free(&(*pconn)->strms);
-fail_strms_init:
- delete_scid(&(*pconn)->scid.set, mem);
- ngtcp2_ksl_free(&(*pconn)->scid.set);
-fail_scid_set_init:
- ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap);
-fail_seqgap_init:
- ngtcp2_ringbuf_free(&(*pconn)->dcid.retired);
-fail_dcid_retired_init:
- ngtcp2_ringbuf_free(&(*pconn)->dcid.unused);
-fail_dcid_unused_init:
- ngtcp2_mem_free(mem, *pconn);
-fail_conn:
- return rv;
-}
-
-int ngtcp2_conn_client_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_path *path,
- uint32_t version,
- const ngtcp2_conn_callbacks *callbacks,
- const ngtcp2_settings *settings,
- const ngtcp2_mem *mem, void *user_data) {
- int rv;
- rv = conn_new(pconn, dcid, scid, path, version, callbacks, settings, mem,
- user_data, 0);
- if (rv != 0) {
- return rv;
- }
- (*pconn)->rcid = *dcid;
- (*pconn)->state = NGTCP2_CS_CLIENT_INITIAL;
- (*pconn)->local.bidi.next_stream_id = 0;
- (*pconn)->local.uni.next_stream_id = 2;
-
- rv = ngtcp2_conn_commit_local_transport_params(*pconn);
- if (rv != 0) {
- ngtcp2_conn_del(*pconn);
- return rv;
- }
-
- ngtcp2_qlog_parameters_set_transport_params(
- &(*pconn)->qlog, &(*pconn)->local.settings.transport_params,
- (*pconn)->server, NGTCP2_QLOG_SIDE_LOCAL);
-
- return 0;
-}
-
-int ngtcp2_conn_server_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_path *path,
- uint32_t version,
- const ngtcp2_conn_callbacks *callbacks,
- const ngtcp2_settings *settings,
- const ngtcp2_mem *mem, void *user_data) {
- int rv;
- rv = conn_new(pconn, dcid, scid, path, version, callbacks, settings, mem,
- user_data, 1);
- if (rv != 0) {
- return rv;
- }
- (*pconn)->state = NGTCP2_CS_SERVER_INITIAL;
- (*pconn)->local.bidi.next_stream_id = 1;
- (*pconn)->local.uni.next_stream_id = 3;
-
- if ((*pconn)->local.settings.token.len) {
- /* Usage of token lifts amplification limit */
- (*pconn)->flags |= NGTCP2_CONN_FLAG_SADDR_VERIFIED;
- }
-
- return 0;
-}
-
-/*
- * conn_fc_credits returns the number of bytes allowed to be sent to
- * the given stream. Both connection and stream level flow control
- * credits are considered.
- */
-static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) {
- return ngtcp2_min(strm->tx.max_offset - strm->tx.offset,
- conn->tx.max_offset - conn->tx.offset);
-}
-
-/*
- * conn_enforce_flow_control returns the number of bytes allowed to be
- * sent to the given stream. |len| might be shorted because of
- * available flow control credits.
- */
-static size_t conn_enforce_flow_control(ngtcp2_conn *conn, ngtcp2_strm *strm,
- size_t len) {
- uint64_t fc_credits = conn_fc_credits(conn, strm);
- return (size_t)ngtcp2_min((uint64_t)len, fc_credits);
-}
-
-static int delete_strms_each(ngtcp2_map_entry *ent, void *ptr) {
- const ngtcp2_mem *mem = ptr;
- ngtcp2_strm *s = ngtcp2_struct_of(ent, ngtcp2_strm, me);
-
- ngtcp2_strm_free(s);
- ngtcp2_mem_free(mem, s);
-
- return 0;
-}
-
-void ngtcp2_conn_del(ngtcp2_conn *conn) {
- if (conn == NULL) {
- return;
- }
-
- ngtcp2_qlog_end(&conn->qlog);
-
- if (conn->early.ckm) {
- conn_call_delete_crypto_aead_ctx(conn, &conn->early.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->early.hp_ctx);
-
- if (conn->crypto.key_update.old_rx_ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx);
- }
- if (conn->crypto.key_update.new_rx_ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->crypto.key_update.new_rx_ckm->aead_ctx);
- }
- if (conn->crypto.key_update.new_tx_ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->crypto.key_update.new_tx_ckm->aead_ctx);
- }
-
- if (conn->pktns.crypto.rx.ckm) {
- conn_call_delete_crypto_aead_ctx(conn,
- &conn->pktns.crypto.rx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->pktns.crypto.rx.hp_ctx);
-
- if (conn->pktns.crypto.tx.ckm) {
- conn_call_delete_crypto_aead_ctx(conn,
- &conn->pktns.crypto.tx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->pktns.crypto.tx.hp_ctx);
-
- if (conn->hs_pktns) {
- if (conn->hs_pktns->crypto.rx.ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->hs_pktns->crypto.rx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.rx.hp_ctx);
-
- if (conn->hs_pktns->crypto.tx.ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->hs_pktns->crypto.tx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.tx.hp_ctx);
- }
- if (conn->in_pktns) {
- if (conn->in_pktns->crypto.rx.ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->in_pktns->crypto.rx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.rx.hp_ctx);
-
- if (conn->in_pktns->crypto.tx.ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->in_pktns->crypto.tx.ckm->aead_ctx);
- }
- conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.tx.hp_ctx);
- }
-
- conn_call_delete_crypto_aead_ctx(conn, &conn->crypto.retry_aead_ctx);
-
- ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base);
- ngtcp2_mem_free(conn->mem, conn->local.settings.token.base);
-
- ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem);
- ngtcp2_crypto_km_del(conn->crypto.key_update.new_rx_ckm, conn->mem);
- ngtcp2_crypto_km_del(conn->crypto.key_update.new_tx_ckm, conn->mem);
- ngtcp2_crypto_km_del(conn->early.ckm, conn->mem);
-
- pktns_free(&conn->pktns, conn->mem);
- pktns_del(conn->hs_pktns, conn->mem);
- pktns_del(conn->in_pktns, conn->mem);
-
- cc_del(&conn->cc, conn->cc_algo, conn->mem);
-
- ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin);
-
- ngtcp2_ringbuf_free(&conn->rx.path_challenge);
-
- ngtcp2_pv_del(conn->pv);
-
- ngtcp2_idtr_free(&conn->remote.uni.idtr);
- ngtcp2_idtr_free(&conn->remote.bidi.idtr);
- ngtcp2_mem_free(conn->mem, conn->tx.ack);
- ngtcp2_pq_free(&conn->tx.strmq);
- ngtcp2_map_each_free(&conn->strms, delete_strms_each, (void *)conn->mem);
- ngtcp2_map_free(&conn->strms);
-
- ngtcp2_pq_free(&conn->scid.used);
- delete_scid(&conn->scid.set, conn->mem);
- ngtcp2_ksl_free(&conn->scid.set);
- ngtcp2_gaptr_free(&conn->dcid.seqgap);
- ngtcp2_ringbuf_free(&conn->dcid.retired);
- ngtcp2_ringbuf_free(&conn->dcid.unused);
-
- ngtcp2_mem_free(conn->mem, conn);
-}
-
-/*
- * conn_ensure_ack_blks makes sure that conn->tx.ack->ack.blks can
- * contain at least |n| additional ngtcp2_ack_blk.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_ensure_ack_blks(ngtcp2_conn *conn, size_t n) {
- ngtcp2_frame *fr;
- size_t max = conn->tx.max_ack_blks;
-
- if (n <= max) {
- return 0;
- }
-
- max *= 2;
-
- assert(max >= n);
-
- fr = ngtcp2_mem_realloc(conn->mem, conn->tx.ack,
- sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * max);
- if (fr == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- conn->tx.ack = fr;
- conn->tx.max_ack_blks = max;
-
- return 0;
-}
-
-/*
- * conn_compute_ack_delay computes ACK delay for outgoing protected
- * ACK.
- */
-static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) {
- return ngtcp2_min(conn->local.settings.transport_params.max_ack_delay,
- conn->cstat.smoothed_rtt / 8);
-}
-
-/*
- * conn_create_ack_frame creates ACK frame, and assigns its pointer to
- * |*pfr| if there are any received packets to acknowledge. If there
- * are no packets to acknowledge, this function returns 0, and |*pfr|
- * is untouched. The caller is advised to set |*pfr| to NULL before
- * calling this function, and check it after this function returns.
- * If |nodelay| is nonzero, delayed ACK timer is ignored.
- *
- * The memory for ACK frame is dynamically allocated by this function.
- * A caller is responsible to free it.
- *
- * Call ngtcp2_acktr_commit_ack after a created ACK frame is
- * successfully serialized into a packet.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr,
- ngtcp2_pktns *pktns, uint8_t type,
- ngtcp2_tstamp ts, ngtcp2_duration ack_delay,
- uint64_t ack_delay_exponent) {
- /* TODO Measure an actual size of ACK blocks to find the best
- default value. */
- const size_t initial_max_ack_blks = 8;
- int64_t last_pkt_num;
- ngtcp2_acktr *acktr = &pktns->acktr;
- ngtcp2_ack_blk *blk;
- ngtcp2_ksl_it it;
- ngtcp2_acktr_entry *rpkt;
- ngtcp2_ack *ack;
- size_t blk_idx;
- ngtcp2_tstamp largest_ack_ts;
- int rv;
-
- if (acktr->flags & NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK) {
- ack_delay = 0;
- }
-
- if (!ngtcp2_acktr_require_active_ack(acktr, ack_delay, ts)) {
- return 0;
- }
-
- it = ngtcp2_acktr_get(acktr);
- if (ngtcp2_ksl_it_end(&it)) {
- ngtcp2_acktr_commit_ack(acktr);
- return 0;
- }
-
- if (conn->tx.ack == NULL) {
- conn->tx.ack = ngtcp2_mem_malloc(
- conn->mem,
- sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * initial_max_ack_blks);
- if (conn->tx.ack == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- conn->tx.max_ack_blks = initial_max_ack_blks;
- }
-
- ack = &conn->tx.ack->ack;
-
- ack->type = NGTCP2_FRAME_ACK;
- ack->num_blks = 0;
-
- rpkt = ngtcp2_ksl_it_get(&it);
-
- if (rpkt->pkt_num == pktns->rx.max_pkt_num) {
- last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1);
- largest_ack_ts = rpkt->tstamp;
- ack->largest_ack = rpkt->pkt_num;
- ack->first_ack_blklen = rpkt->len - 1;
-
- ngtcp2_ksl_it_next(&it);
- } else {
- assert(rpkt->pkt_num < pktns->rx.max_pkt_num);
-
- last_pkt_num = pktns->rx.max_pkt_num;
- largest_ack_ts = pktns->rx.max_pkt_ts;
- ack->largest_ack = pktns->rx.max_pkt_num;
- ack->first_ack_blklen = 0;
- }
-
- if (type == NGTCP2_PKT_SHORT) {
- ack->ack_delay_unscaled = ts - largest_ack_ts;
- ack->ack_delay = ack->ack_delay_unscaled / NGTCP2_MICROSECONDS /
- (1UL << ack_delay_exponent);
- } else {
- ack->ack_delay_unscaled = 0;
- ack->ack_delay = 0;
- }
-
- for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
- if (ack->num_blks == NGTCP2_MAX_ACK_BLKS) {
- break;
- }
-
- rpkt = ngtcp2_ksl_it_get(&it);
-
- blk_idx = ack->num_blks++;
- rv = conn_ensure_ack_blks(conn, ack->num_blks);
- if (rv != 0) {
- return rv;
- }
- ack = &conn->tx.ack->ack;
- blk = &ack->blks[blk_idx];
- blk->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2);
- blk->blklen = rpkt->len - 1;
-
- last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1);
- }
-
- /* TODO Just remove entries which cannot fit into a single ACK frame
- for now. */
- if (!ngtcp2_ksl_it_end(&it)) {
- ngtcp2_acktr_forget(acktr, ngtcp2_ksl_it_get(&it));
- }
-
- *pfr = conn->tx.ack;
-
- return 0;
-}
-
-/*
- * conn_ppe_write_frame writes |fr| to |ppe|. If |hd_logged| is not
- * NULL and |*hd_logged| is zero, packet header is logged, and 1 is
- * assigned to |*hd_logged|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer is too small.
- */
-static int conn_ppe_write_frame_hd_log(ngtcp2_conn *conn, ngtcp2_ppe *ppe,
- int *hd_logged, const ngtcp2_pkt_hd *hd,
- ngtcp2_frame *fr) {
- int rv;
-
- rv = ngtcp2_ppe_encode_frame(ppe, fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return rv;
- }
-
- if (hd_logged && !*hd_logged) {
- *hd_logged = 1;
- ngtcp2_log_tx_pkt_hd(&conn->log, hd);
- ngtcp2_qlog_pkt_sent_start(&conn->qlog, hd);
- }
-
- ngtcp2_log_tx_fr(&conn->log, hd, fr);
- ngtcp2_qlog_write_frame(&conn->qlog, fr);
-
- return 0;
-}
-
-/*
- * conn_ppe_write_frame writes |fr| to |ppe|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer is too small.
- */
-static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe,
- const ngtcp2_pkt_hd *hd, ngtcp2_frame *fr) {
- return conn_ppe_write_frame_hd_log(conn, ppe, NULL, hd, fr);
-}
-
-/*
- * conn_on_pkt_sent is called when new non-ACK-only packet is sent.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_rtb *rtb,
- ngtcp2_rtb_entry *ent) {
- int rv;
-
- /* This function implements OnPacketSent, but it handles only
- non-ACK-only packet. */
- rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat);
- if (rv != 0) {
- return rv;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- conn->cstat.last_tx_pkt_ts[rtb->pktns_id] = ent->ts;
- }
-
- ngtcp2_conn_set_loss_detection_timer(conn, ent->ts);
-
- return 0;
-}
-
-/*
- * pktns_select_pkt_numlen selects shortest packet number encoding for
- * the next packet number based on the largest acknowledged packet
- * number. It returns the number of bytes to encode the packet
- * number.
- */
-static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) {
- int64_t pkt_num = pktns->tx.last_pkt_num + 1;
- ngtcp2_rtb *rtb = &pktns->rtb;
- int64_t n = pkt_num - rtb->largest_acked_tx_pkt_num;
-
- if (NGTCP2_MAX_PKT_NUM / 2 <= pkt_num) {
- return 4;
- }
-
- n = n * 2 + 1;
-
- if (n > 0xffffff) {
- return 4;
- }
- if (n > 0xffff) {
- return 3;
- }
- if (n > 0xff) {
- return 2;
- }
- return 1;
-}
-
-/*
- * conn_cwnd_is_zero returns nonzero if the number of bytes the local
- * endpoint can sent at this time is zero.
- */
-static uint64_t conn_cwnd_is_zero(ngtcp2_conn *conn) {
- uint64_t bytes_in_flight = conn->cstat.bytes_in_flight;
- uint64_t cwnd =
- conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)
- ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_udp_payload_size)
- : conn->cstat.cwnd;
-
- return bytes_in_flight >= cwnd;
-}
-
-/*
- * conn_retry_early_payloadlen returns the estimated wire length of
- * the first STREAM frame of 0-RTT packet which should be
- * retransmitted due to Retry frame
- */
-static size_t conn_retry_early_payloadlen(ngtcp2_conn *conn) {
- ngtcp2_frame_chain *frc;
- ngtcp2_strm *strm;
-
- for (; !ngtcp2_pq_empty(&conn->tx.strmq);) {
- strm = ngtcp2_conn_tx_strmq_top(conn);
- if (ngtcp2_strm_streamfrq_empty(strm)) {
- ngtcp2_conn_tx_strmq_pop(conn);
- continue;
- }
-
- frc = ngtcp2_strm_streamfrq_top(strm);
- return ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt) +
- NGTCP2_STREAM_OVERHEAD;
- }
-
- return 0;
-}
-
-static void conn_cryptofrq_clear(ngtcp2_conn *conn, ngtcp2_pktns *pktns) {
- ngtcp2_frame_chain *frc;
- ngtcp2_ksl_it it;
-
- for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- frc = ngtcp2_ksl_it_get(&it);
- ngtcp2_frame_chain_del(frc, conn->mem);
- }
- ngtcp2_ksl_clear(&pktns->crypto.tx.frq);
-}
-
-/*
- * conn_cryptofrq_unacked_offset returns the CRYPTO frame offset by
- * taking into account acknowledged offset. If there is no data to
- * send, this function returns (uint64_t)-1.
- */
-static uint64_t conn_cryptofrq_unacked_offset(ngtcp2_conn *conn,
- ngtcp2_pktns *pktns) {
- ngtcp2_frame_chain *frc;
- ngtcp2_crypto *fr;
- ngtcp2_range gap;
- ngtcp2_rtb *rtb = &pktns->rtb;
- ngtcp2_ksl_it it;
- size_t datalen;
-
- (void)conn;
-
- for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- frc = ngtcp2_ksl_it_get(&it);
- fr = &frc->fr.crypto;
-
- gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->offset);
-
- datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
-
- if (gap.begin <= fr->offset) {
- return fr->offset;
- }
- if (gap.begin < fr->offset + datalen) {
- return gap.begin;
- }
- }
-
- return (uint64_t)-1;
-}
-
-static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_frame_chain **pfrc) {
- ngtcp2_frame_chain *frc, *nfrc;
- ngtcp2_crypto *fr, *nfr;
- uint64_t offset, end_offset;
- size_t idx, end_idx;
- uint64_t base_offset, end_base_offset;
- ngtcp2_range gap;
- ngtcp2_rtb *rtb = &pktns->rtb;
- ngtcp2_vec *v;
- int rv;
- ngtcp2_ksl_it it;
-
- *pfrc = NULL;
-
- for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it);) {
- frc = ngtcp2_ksl_it_get(&it);
- fr = &frc->fr.crypto;
-
- ngtcp2_ksl_remove(&pktns->crypto.tx.frq, &it, &fr->offset);
-
- idx = 0;
- offset = fr->offset;
- base_offset = 0;
-
- gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, offset);
- if (gap.begin < offset) {
- gap.begin = offset;
- }
-
- for (; idx < fr->datacnt && offset < gap.begin; ++idx) {
- v = &fr->data[idx];
- if (offset + v->len > gap.begin) {
- base_offset = gap.begin - offset;
- break;
- }
-
- offset += v->len;
- }
-
- if (idx == fr->datacnt) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
-
- assert(gap.begin == offset + base_offset);
-
- end_idx = idx;
- end_offset = offset;
- end_base_offset = 0;
-
- for (; end_idx < fr->datacnt; ++end_idx) {
- v = &fr->data[end_idx];
- if (end_offset + v->len > gap.end) {
- end_base_offset = gap.end - end_offset;
- break;
- }
-
- end_offset += v->len;
- }
-
- if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) {
- *pfrc = frc;
- return 0;
- }
-
- if (fr->datacnt == end_idx) {
- memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
-
- assert(fr->data[0].len > base_offset);
-
- fr->offset = offset + base_offset;
- fr->datacnt = end_idx - idx;
- fr->data[0].base += base_offset;
- fr->data[0].len -= (size_t)base_offset;
-
- *pfrc = frc;
- return 0;
- }
-
- rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, fr->datacnt - end_idx,
- conn->mem);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.crypto;
- nfr->type = NGTCP2_FRAME_CRYPTO;
- memcpy(nfr->data, fr->data + end_idx,
- sizeof(nfr->data[0]) * (fr->datacnt - end_idx));
-
- assert(nfr->data[0].len > end_base_offset);
-
- nfr->offset = end_offset + end_base_offset;
- nfr->datacnt = fr->datacnt - end_idx;
- nfr->data[0].base += end_base_offset;
- nfr->data[0].len -= (size_t)end_base_offset;
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- if (end_base_offset) {
- ++end_idx;
- }
-
- memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
-
- assert(fr->data[0].len > base_offset);
-
- fr->offset = offset + base_offset;
- fr->datacnt = end_idx - idx;
- if (end_base_offset) {
- assert(fr->data[fr->datacnt - 1].len > end_base_offset);
- fr->data[fr->datacnt - 1].len = (size_t)end_base_offset;
- }
- fr->data[0].base += base_offset;
- fr->data[0].len -= (size_t)base_offset;
-
- *pfrc = frc;
- return 0;
- }
-
- return 0;
-}
-static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc,
- ngtcp2_pktns *pktns, size_t left) {
- ngtcp2_crypto *fr, *nfr;
- ngtcp2_frame_chain *frc, *nfrc;
- int rv;
- size_t nmerged;
- size_t datalen;
- ngtcp2_vec a[NGTCP2_MAX_CRYPTO_DATACNT];
- ngtcp2_vec b[NGTCP2_MAX_CRYPTO_DATACNT];
- size_t acnt, bcnt;
- ngtcp2_ksl_it it;
-
- rv = conn_cryptofrq_unacked_pop(conn, pktns, &frc);
- if (rv != 0) {
- return rv;
- }
- if (frc == NULL) {
- *pfrc = NULL;
- return 0;
- }
-
- fr = &frc->fr.crypto;
- datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
-
- if (datalen > left) {
- ngtcp2_vec_copy(a, fr->data, fr->datacnt);
- acnt = fr->datacnt;
-
- bcnt = 0;
- ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_CRYPTO_DATACNT);
-
- assert(acnt > 0);
- assert(bcnt > 0);
-
- rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, bcnt, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.crypto;
- nfr->type = NGTCP2_FRAME_CRYPTO;
- nfr->offset = fr->offset + left;
- nfr->datacnt = bcnt;
- ngtcp2_vec_copy(nfr->data, b, bcnt);
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, acnt, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.crypto;
- *nfr = *fr;
- nfr->datacnt = acnt;
- ngtcp2_vec_copy(nfr->data, a, acnt);
-
- ngtcp2_frame_chain_del(frc, conn->mem);
-
- *pfrc = nfrc;
-
- return 0;
- }
-
- left -= datalen;
-
- ngtcp2_vec_copy(a, fr->data, fr->datacnt);
- acnt = fr->datacnt;
-
- for (; left && ngtcp2_ksl_len(&pktns->crypto.tx.frq);) {
- it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq);
- nfrc = ngtcp2_ksl_it_get(&it);
- nfr = &nfrc->fr.crypto;
-
- if (nfr->offset != fr->offset + datalen) {
- assert(fr->offset + datalen < nfr->offset);
- break;
- }
-
- rv = conn_cryptofrq_unacked_pop(conn, pktns, &nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- if (nfrc == NULL) {
- break;
- }
-
- nfr = &nfrc->fr.crypto;
-
- nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
- NGTCP2_MAX_CRYPTO_DATACNT);
- if (nmerged == 0) {
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- break;
- }
-
- datalen += nmerged;
- left -= nmerged;
-
- if (nfr->datacnt == 0) {
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- continue;
- }
-
- nfr->offset += nmerged;
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- break;
- }
-
- if (acnt == fr->datacnt) {
- assert(acnt > 0);
- fr->data[acnt - 1] = a[acnt - 1];
-
- *pfrc = frc;
- return 0;
- }
-
- assert(acnt > fr->datacnt);
-
- rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, acnt, conn->mem);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.crypto;
- *nfr = *fr;
- nfr->datacnt = acnt;
- ngtcp2_vec_copy(nfr->data, a, acnt);
-
- ngtcp2_frame_chain_del(frc, conn->mem);
-
- *pfrc = nfrc;
-
- return 0;
-}
-
-/*
- * conn_verify_dcid verifies that destination connection ID in |hd| is
- * valid for the connection. If it is successfully verified and the
- * remote endpoint uses new DCID in the packet, nonzero value is
- * assigned to |*pnew_cid_used| if it is not NULL. Otherwise 0 is
- * assigned to it.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_INVALID_ARGUMENT
- * |dcid| is not known to the local endpoint.
- */
-static int conn_verify_dcid(ngtcp2_conn *conn, int *pnew_cid_used,
- const ngtcp2_pkt_hd *hd) {
- ngtcp2_ksl_it it;
- ngtcp2_scid *scid;
- int rv;
-
- it = ngtcp2_ksl_lower_bound(&conn->scid.set, &hd->dcid);
- if (ngtcp2_ksl_it_end(&it)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- scid = ngtcp2_ksl_it_get(&it);
- if (!ngtcp2_cid_eq(&scid->cid, &hd->dcid)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if (!(scid->flags & NGTCP2_SCID_FLAG_USED)) {
- scid->flags |= NGTCP2_SCID_FLAG_USED;
-
- if (scid->pe.index == NGTCP2_PQ_BAD_INDEX) {
- rv = ngtcp2_pq_push(&conn->scid.used, &scid->pe);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (pnew_cid_used) {
- *pnew_cid_used = 1;
- }
- } else if (pnew_cid_used) {
- *pnew_cid_used = 0;
- }
-
- return 0;
-}
-
-/*
- * conn_should_pad_pkt returns nonzero if the packet should be padded.
- * |type| is the type of packet. |left| is the space left in packet
- * buffer. |early_datalen| is the number of bytes which will be sent
- * in the next, coalesced 0-RTT packet.
- */
-static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left,
- size_t early_datalen) {
- size_t min_payloadlen;
-
- if (conn->server) {
- return 0;
- }
-
- if (type == NGTCP2_PKT_HANDSHAKE) {
- return conn->in_pktns != NULL;
- }
-
- if (conn->hs_pktns->crypto.tx.ckm &&
- (conn->hs_pktns->rtb.probe_pkt_left ||
- ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) ||
- !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) {
- /* If we have something to send in Handshake packet, then add
- PADDING in Handshake packet. */
- min_payloadlen = 128;
- } else if (!conn->early.ckm || early_datalen == 0) {
- return 1;
- } else {
- /* If we have something to send in 0RTT packet, then add PADDING
- in 0RTT packet. */
- min_payloadlen = ngtcp2_min(early_datalen, 128);
- }
-
- return left <
- /* TODO Assuming that pkt_num is encoded in 1 byte. */
- NGTCP2_MIN_LONG_HEADERLEN + conn->dcid.current.cid.datalen +
- conn->oscid.datalen + 1 /* payloadlen bytes - 1 */ +
- min_payloadlen + NGTCP2_MAX_AEAD_OVERHEAD;
-}
-
-static void conn_restart_timer_on_write(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- conn->idle_ts = ts;
- conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE;
-}
-
-static void conn_restart_timer_on_read(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- conn->idle_ts = ts;
- conn->flags |= NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE;
-}
-
-/*
- * conn_write_handshake_pkt writes handshake packet in the buffer
- * pointed by |dest| whose length is |destlen|. |type| specifies long
- * packet type. It should be either NGTCP2_PKT_INITIAL or
- * NGTCP2_PKT_HANDSHAKE_PKT.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, uint8_t type,
- size_t early_datalen,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_ppe ppe;
- ngtcp2_pkt_hd hd;
- ngtcp2_frame_chain *frq = NULL, **pfrc = &frq;
- ngtcp2_frame_chain *nfrc;
- ngtcp2_frame *ackfr = NULL, lfr;
- ngtcp2_ssize spktlen;
- ngtcp2_crypto_cc cc;
- ngtcp2_rtb_entry *rtbent;
- ngtcp2_pktns *pktns;
- size_t left;
- uint8_t rtb_entry_flags = NGTCP2_RTB_FLAG_NONE;
- int pkt_empty = 1;
- int padded = 0;
- int hd_logged = 0;
- uint64_t crypto_offset;
- ngtcp2_ssize num_reclaimed;
-
- switch (type) {
- case NGTCP2_PKT_INITIAL:
- if (!conn->in_pktns) {
- return 0;
- }
- assert(conn->in_pktns->crypto.tx.ckm);
- pktns = conn->in_pktns;
- cc.aead_overhead = NGTCP2_INITIAL_AEAD_OVERHEAD;
- break;
- case NGTCP2_PKT_HANDSHAKE:
- if (!conn->hs_pktns || !conn->hs_pktns->crypto.tx.ckm) {
- return 0;
- }
- pktns = conn->hs_pktns;
- cc.aead_overhead = conn->crypto.aead_overhead;
- break;
- default:
- assert(0);
- }
-
- cc.aead = pktns->crypto.ctx.aead;
- cc.hp = pktns->crypto.ctx.hp;
- cc.ckm = pktns->crypto.tx.ckm;
- cc.hp_ctx = pktns->crypto.tx.hp_ctx;
- cc.encrypt = conn->callbacks.encrypt;
- cc.hp_mask = conn->callbacks.hp_mask;
-
- ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, type,
- &conn->dcid.current.cid, &conn->oscid,
- pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns),
- conn->version, 0);
-
- if (!conn->server && type == NGTCP2_PKT_INITIAL &&
- conn->local.settings.token.len) {
- hd.token = conn->local.settings.token;
- }
-
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
-
- rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return 0;
- }
-
- if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) {
- return 0;
- }
-
- rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts,
- /* ack_delay = */ 0,
- NGTCP2_DEFAULT_ACK_DELAY_EXPONENT);
- if (rv != 0) {
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return rv;
- }
-
- if (ackfr) {
- rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack);
- pkt_empty = 0;
- }
- }
-
-build_pkt:
- for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) {
- left = ngtcp2_ppe_left(&ppe);
-
- crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns);
- if (crypto_offset == (size_t)-1) {
- conn_cryptofrq_clear(conn, pktns);
- break;
- }
-
- left = ngtcp2_pkt_crypto_max_datalen(crypto_offset, left, left);
- if (left == (size_t)-1) {
- break;
- }
-
- rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return rv;
- }
-
- if (nfrc == NULL) {
- break;
- }
-
- rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &nfrc->fr);
- if (rv != 0) {
- assert(0);
- }
-
- *pfrc = nfrc;
- pfrc = &(*pfrc)->next;
-
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- }
-
- if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- pktns->rtb.num_retransmittable && pktns->rtb.probe_pkt_left) {
- num_reclaimed = ngtcp2_rtb_reclaim_on_pto(&pktns->rtb, conn, pktns,
- pktns->rtb.probe_pkt_left + 1);
- if (num_reclaimed < 0) {
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return rv;
- }
- if (num_reclaimed) {
- goto build_pkt;
- }
- /* We had pktns->rtb.num_retransmittable > 0 but the contents of
- those packets have been acknowledged (i.e., retransmission in
- another packet). For server, in this case, we don't have to
- send any probe packet. Client needs to send probe packets
- until it knows that server has completed address validation or
- handshake has been confirmed. */
- if (pktns->rtb.num_retransmittable == 0 &&
- (conn->server ||
- (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED |
- NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) {
- pktns->rtb.probe_pkt_left = 0;
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
- }
- }
-
- /* Don't send any PING frame if client Initial has not been
- acknowledged yet. */
- if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- pktns->rtb.probe_pkt_left &&
- (type != NGTCP2_PKT_INITIAL ||
- ngtcp2_strm_is_all_tx_data_acked(&pktns->crypto.strm))) {
- lfr.type = NGTCP2_FRAME_PING;
-
- rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr);
- if (rv != 0) {
- assert(rv == NGTCP2_ERR_NOBUF);
- } else {
- rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_PROBE;
- pkt_empty = 0;
- }
- }
-
- if (!pkt_empty) {
- if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
- /* The intention of smaller limit is get more chance to measure
- RTT samples in early phase. */
- if (pktns->rtb.probe_pkt_left || pktns->tx.num_non_ack_pkt >= 1) {
- lfr.type = NGTCP2_FRAME_PING;
-
- rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr);
- if (rv != 0) {
- assert(rv == NGTCP2_ERR_NOBUF);
- } else {
- rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING;
- pktns->tx.num_non_ack_pkt = 0;
- }
- } else {
- ++pktns->tx.num_non_ack_pkt;
- }
- } else {
- pktns->tx.num_non_ack_pkt = 0;
- }
- }
-
- if (pkt_empty) {
- return 0;
- }
-
- /* If we cannot write another packet, then we need to add padding to
- Initial here. */
- if (conn_should_pad_pkt(conn, type, ngtcp2_ppe_left(&ppe), early_datalen)) {
- lfr.type = NGTCP2_FRAME_PADDING;
- lfr.padding.len = ngtcp2_ppe_padding(&ppe);
- } else {
- lfr.type = NGTCP2_FRAME_PADDING;
- lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe);
- }
-
- if (lfr.padding.len) {
- padded = 1;
- ngtcp2_log_tx_fr(&conn->log, &hd, &lfr);
- ngtcp2_qlog_write_frame(&conn->qlog, &lfr);
- }
-
- spktlen = ngtcp2_ppe_final(&ppe, NULL);
- if (spktlen < 0) {
- assert(ngtcp2_err_is_fatal((int)spktlen));
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return spktlen;
- }
-
- ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)spktlen);
-
- if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) || padded) {
- rv = ngtcp2_rtb_entry_new(&rtbent, &hd, frq, ts, (size_t)spktlen,
- rtb_entry_flags, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_list_del(frq, conn->mem);
- return rv;
- }
-
- rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent);
- if (rv != 0) {
- ngtcp2_rtb_entry_del(rtbent, conn->mem);
- return rv;
- }
-
- if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) {
- conn_restart_timer_on_write(conn, ts);
- }
- }
-
- if (pktns->rtb.probe_pkt_left &&
- (rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
- --pktns->rtb.probe_pkt_left;
- }
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- ++pktns->tx.last_pkt_num;
-
- return spktlen;
-}
-
-/*
- * conn_write_ack_pkt writes QUIC packet for type |type| which only
- * includes ACK frame in the buffer pointed by |dest| whose length is
- * |destlen|.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, uint8_t type,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_frame *ackfr;
- ngtcp2_pktns *pktns;
- ngtcp2_duration ack_delay;
- uint64_t ack_delay_exponent;
-
- assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING));
-
- switch (type) {
- case NGTCP2_PKT_INITIAL:
- assert(conn->server);
- pktns = conn->in_pktns;
- ack_delay = 0;
- ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- break;
- case NGTCP2_PKT_HANDSHAKE:
- pktns = conn->hs_pktns;
- ack_delay = 0;
- ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- break;
- case NGTCP2_PKT_SHORT:
- pktns = &conn->pktns;
- ack_delay = conn_compute_ack_delay(conn);
- ack_delay_exponent =
- conn->local.settings.transport_params.ack_delay_exponent;
- break;
- default:
- assert(0);
- }
-
- if (!pktns->crypto.tx.ckm) {
- return 0;
- }
-
- ackfr = NULL;
- rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, ack_delay,
- ack_delay_exponent);
- if (rv != 0) {
- return rv;
- }
-
- if (!ackfr) {
- return 0;
- }
-
- return ngtcp2_conn_write_single_frame_pkt(conn, dest, destlen, type,
- &conn->dcid.current.cid, ackfr,
- NGTCP2_RTB_FLAG_NONE, ts);
-}
-
-static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns,
- ngtcp2_tstamp ts) {
- ngtcp2_pktns *pktns = *ppktns;
- uint64_t bytes_in_flight;
-
- bytes_in_flight = pktns->rtb.cc_bytes_in_flight;
-
- assert(conn->cstat.bytes_in_flight >= bytes_in_flight);
-
- conn->cstat.bytes_in_flight -= bytes_in_flight;
- conn->cstat.pto_count = 0;
- conn->cstat.last_tx_pkt_ts[pktns->rtb.pktns_id] = UINT64_MAX;
- conn->cstat.loss_time[pktns->rtb.pktns_id] = UINT64_MAX;
-
- conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.rx.ckm->aead_ctx);
- conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.rx.hp_ctx);
- conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx);
- conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.tx.hp_ctx);
-
- pktns_del(pktns, conn->mem);
- *ppktns = NULL;
-
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
-}
-
-/*
- * conn_discard_initial_state discards state for Initial packet number
- * space.
- */
-static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- if (!conn->in_pktns) {
- return;
- }
-
- conn_discard_pktns(conn, &conn->in_pktns, ts);
-}
-
-/*
- * conn_discard_handshake_state discards state for Handshake packet
- * number space.
- */
-static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- if (!conn->hs_pktns) {
- return;
- }
-
- conn_discard_pktns(conn, &conn->hs_pktns, ts);
-}
-
-/*
- * conn_write_handshake_ack_pkts writes packets which contain ACK
- * frame only. This function writes at most 2 packets for each
- * Initial and Handshake packet.
- */
-static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn,
- uint8_t *dest, size_t destlen,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize res = 0, nwrite = 0;
-
- /* In the most cases, client sends ACK in conn_write_handshake_pkt.
- This function is only called when it is CWND limited. It is not
- required for client to send ACK for server Initial. This is
- because once it gets server Initial, it gets Handshake tx key and
- discards Initial key. The only good reason to send ACK is give
- server RTT measurement early. */
- if (conn->server && conn->in_pktns) {
- nwrite = conn_write_ack_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
-
- if (conn->hs_pktns->crypto.tx.ckm) {
- nwrite = conn_write_ack_pkt(conn, dest, destlen, NGTCP2_PKT_HANDSHAKE, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
-
- if (!conn->server && nwrite) {
- conn_discard_initial_state(conn, ts);
- }
- }
-
- return res;
-}
-
-/*
- * conn_write_client_initial writes Initial packet in the buffer
- * pointed by |dest| whose length is |destlen|.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static ngtcp2_ssize conn_write_client_initial(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen,
- size_t early_datalen,
- ngtcp2_tstamp ts) {
- int rv;
-
- assert(conn->callbacks.client_initial);
-
- rv = conn->callbacks.client_initial(conn, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL,
- early_datalen, ts);
-}
-
-/*
- * conn_write_handshake_pkts writes Initial and Handshake packets in
- * the buffer pointed by |dest| whose length is |destlen|.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen,
- size_t early_datalen,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nwrite;
- ngtcp2_ssize res = 0;
-
- if (!conn->server && conn->hs_pktns->crypto.tx.ckm &&
- !ngtcp2_acktr_empty(&conn->hs_pktns->acktr)) {
- /* Discard Initial state here so that Handshake packet is not
- padded. */
- conn_discard_initial_state(conn, ts);
- } else {
- nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL,
- early_datalen, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
-
- nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_HANDSHAKE,
- 0, ts);
- if (nwrite < 0) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- return nwrite;
- }
-
- res += nwrite;
-
- if (!conn->server && conn->hs_pktns->crypto.tx.ckm && nwrite) {
- /* We don't need to send further Initial packet if we have
- Handshake key and sent something with it. So discard initial
- state here. */
- conn_discard_initial_state(conn, ts);
- }
-
- return res;
-}
-
-/*
- * conn_initial_stream_rx_offset returns the initial maximum offset of
- * data for a stream denoted by |stream_id|.
- */
-static uint64_t conn_initial_stream_rx_offset(ngtcp2_conn *conn,
- int64_t stream_id) {
- int local_stream = conn_local_stream(conn, stream_id);
-
- if (bidi_stream(stream_id)) {
- if (local_stream) {
- return conn->local.settings.transport_params
- .initial_max_stream_data_bidi_local;
- }
- return conn->local.settings.transport_params
- .initial_max_stream_data_bidi_remote;
- }
-
- if (local_stream) {
- return 0;
- }
- return conn->local.settings.transport_params.initial_max_stream_data_uni;
-}
-
-/*
- * conn_should_send_max_stream_data returns nonzero if MAX_STREAM_DATA
- * frame should be send for |strm|.
- */
-static int conn_should_send_max_stream_data(ngtcp2_conn *conn,
- ngtcp2_strm *strm) {
- uint64_t win = conn_initial_stream_rx_offset(conn, strm->stream_id);
- uint64_t inc = strm->rx.unsent_max_offset - strm->rx.max_offset;
- ngtcp2_conn_stat *cstat = &conn->cstat;
-
- return win < 2 * inc ||
- (cstat->min_rtt != UINT64_MAX &&
- 2 * cstat->recv_rate_sec * cstat->min_rtt / NGTCP2_SECONDS >
- win - inc);
-}
-
-/*
- * conn_should_send_max_data returns nonzero if MAX_DATA frame should
- * be sent.
- */
-static int conn_should_send_max_data(ngtcp2_conn *conn) {
- uint64_t inc = conn->rx.unsent_max_offset - conn->rx.max_offset;
- ngtcp2_conn_stat *cstat = &conn->cstat;
-
- return conn->local.settings.transport_params.initial_max_data < 2 * inc ||
- (cstat->min_rtt != UINT64_MAX &&
- 2 * cstat->recv_rate_sec * cstat->min_rtt / NGTCP2_SECONDS >
- conn->local.settings.transport_params.initial_max_data - inc);
-}
-
-/*
- * conn_required_num_new_connection_id returns the number of
- * additional connection ID the local endpoint has to provide to the
- * remote endpoint.
- */
-static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) {
- uint64_t n;
- size_t len = ngtcp2_ksl_len(&conn->scid.set);
-
- if (len >= NGTCP2_MAX_SCID_POOL_SIZE) {
- return 0;
- }
-
- /* len includes retired CID. We don't provide extra CID if doing so
- excceds NGTCP2_MAX_SCID_POOL_SIZE. */
-
- n = conn->remote.transport_params.active_connection_id_limit +
- conn->scid.num_retired;
-
- return (size_t)ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n) - len;
-}
-
-/*
- * conn_enqueue_new_connection_id generates additional connection IDs
- * and prepares to send them to the remote endpoint.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) {
- size_t i, need = conn_required_num_new_connection_id(conn);
- size_t cidlen = conn->oscid.datalen;
- ngtcp2_cid cid;
- uint64_t seq;
- int rv;
- uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN];
- ngtcp2_frame_chain *nfrc;
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_scid *scid;
- ngtcp2_ksl_it it;
-
- for (i = 0; i < need; ++i) {
- rv = conn_call_get_new_connection_id(conn, &cid, token, cidlen);
- if (rv != 0) {
- return rv;
- }
-
- if (cid.datalen != cidlen) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- /* Assert uniqueness */
- it = ngtcp2_ksl_lower_bound(&conn->scid.set, &cid);
- if (!ngtcp2_ksl_it_end(&it) &&
- ngtcp2_cid_eq(ngtcp2_ksl_it_key(&it), &cid)) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- seq = ++conn->scid.last_seq;
-
- scid = ngtcp2_mem_malloc(conn->mem, sizeof(*scid));
- if (scid == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_scid_init(scid, seq, &cid, token);
-
- rv = ngtcp2_ksl_insert(&conn->scid.set, NULL, &scid->cid, scid);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, scid);
- return rv;
- }
-
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr.type = NGTCP2_FRAME_NEW_CONNECTION_ID;
- nfrc->fr.new_connection_id.seq = seq;
- nfrc->fr.new_connection_id.retire_prior_to = 0;
- nfrc->fr.new_connection_id.cid = cid;
- memcpy(nfrc->fr.new_connection_id.stateless_reset_token, token,
- sizeof(token));
- nfrc->next = pktns->tx.frq;
- pktns->tx.frq = nfrc;
- }
-
- return 0;
-}
-
-/*
- * conn_compute_pto computes the current PTO.
- */
-static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn,
- ngtcp2_pktns *pktns) {
- ngtcp2_conn_stat *cstat = &conn->cstat;
- ngtcp2_duration var = ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY);
- ngtcp2_duration max_ack_delay =
- pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APP
- ? conn->remote.transport_params.max_ack_delay
- : 0;
- return cstat->smoothed_rtt + var + max_ack_delay;
-}
-
-/*
- * conn_remove_retired_connection_id removes the already retired
- * connection ID. It waits PTO before actually removing a connection
- * ID after it receives RETIRE_CONNECTION_ID from peer to catch
- * reordered packets.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_remove_retired_connection_id(ngtcp2_conn *conn,
- ngtcp2_tstamp ts) {
- ngtcp2_duration timeout = conn_compute_pto(conn, &conn->pktns);
- ngtcp2_scid *scid;
- ngtcp2_dcid *dcid;
- int rv;
-
- for (; !ngtcp2_pq_empty(&conn->scid.used);) {
- scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe);
-
- if (scid->ts_retired == UINT64_MAX || scid->ts_retired + timeout >= ts) {
- break;
- }
-
- assert(scid->flags & NGTCP2_SCID_FLAG_RETIRED);
-
- rv = conn_call_remove_connection_id(conn, &scid->cid);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_ksl_remove(&conn->scid.set, NULL, &scid->cid);
- ngtcp2_pq_pop(&conn->scid.used);
- ngtcp2_mem_free(conn->mem, scid);
-
- assert(conn->scid.num_retired);
- --conn->scid.num_retired;
- }
-
- for (; ngtcp2_ringbuf_len(&conn->dcid.retired);) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, 0);
- if (dcid->ts_retired + timeout >= ts) {
- break;
- }
-
- rv = conn_call_deactivate_dcid(conn, dcid);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_ringbuf_pop_front(&conn->dcid.retired);
- }
-
- return 0;
-}
-
-/*
- * conn_min_short_pktlen returns the minimum length of Short packet
- * this endpoint sends.
- */
-static size_t conn_min_short_pktlen(ngtcp2_conn *conn) {
- return conn->dcid.current.cid.datalen + NGTCP2_MIN_PKT_EXPANDLEN;
-}
-
-typedef enum {
- NGTCP2_WRITE_PKT_FLAG_NONE = 0x00,
- /* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING indicates that packet
- should be padded */
- NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING = 0x01,
- /* NGTCP2_WRITE_PKT_FLAG_MORE indicates that more frames might come
- and it should be encoded into the current packet. */
- NGTCP2_WRITE_PKT_FLAG_MORE = 0x02,
-} ngtcp2_write_pkt_flag;
-
-/*
- * conn_write_pkt writes a protected packet in the buffer pointed by
- * |dest| whose length if |destlen|. |type| specifies the type of
- * packet. It can be NGTCP2_PKT_SHORT or NGTCP2_PKT_0RTT.
- *
- * This function can send new stream data. In order to send stream
- * data, specify the underlying stream and parameters to
- * |vmsg|->stream. If |vmsg|->stream.fin is set to nonzero, it
- * signals that the given data is the final portion of the stream.
- * |vmsg|->stream.data vector of length |vmsg|->stream.datacnt
- * specifies stream data to send. The number of bytes sent to the
- * stream is assigned to *|vmsg|->stream.pdatalen. If 0 length STREAM
- * data is sent, 0 is assigned to it. The caller should initialize
- * *|vmsg|->stream.pdatalen to -1.
- *
- * If |require_padding| is nonzero, padding bytes are added to occupy
- * the remaining packet payload.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_STREAM_DATA_BLOCKED
- * Stream data could not be written because of flow control.
- */
-static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, ngtcp2_vmsg *vmsg,
- uint8_t type, uint8_t flags,
- ngtcp2_tstamp ts) {
- int rv = 0;
- ngtcp2_crypto_cc *cc = &conn->pkt.cc;
- ngtcp2_ppe *ppe = &conn->pkt.ppe;
- ngtcp2_pkt_hd *hd = &conn->pkt.hd;
- ngtcp2_frame *ackfr = NULL, lfr;
- ngtcp2_ssize nwrite;
- ngtcp2_frame_chain **pfrc, *nfrc, *frc;
- ngtcp2_rtb_entry *ent;
- ngtcp2_strm *strm;
- int pkt_empty = 1;
- size_t ndatalen = 0;
- int send_stream = 0;
- int stream_blocked = 0;
- ngtcp2_pktns *pktns = &conn->pktns;
- size_t left;
- size_t datalen = 0;
- ngtcp2_vec data[NGTCP2_MAX_STREAM_DATACNT];
- size_t datacnt;
- uint8_t rtb_entry_flags = NGTCP2_RTB_FLAG_NONE;
- int hd_logged = 0;
- ngtcp2_path_challenge_entry *pcent;
- uint8_t hd_flags;
- int require_padding = (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) != 0;
- int write_more = (flags & NGTCP2_WRITE_PKT_FLAG_MORE) != 0;
- int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) != 0;
- size_t min_pktlen = conn_min_short_pktlen(conn);
- int padded = 0;
- int credit_expanded = 0;
- ngtcp2_cc_pkt cc_pkt;
- uint64_t crypto_offset;
- uint64_t stream_offset;
- ngtcp2_ssize num_reclaimed;
- int fin;
-
- /* Return 0 if destlen is less than minimum packet length which can
- trigger Stateless Reset */
- if (destlen < min_pktlen) {
- return 0;
- }
-
- if (vmsg) {
- switch (vmsg->type) {
- case NGTCP2_VMSG_TYPE_STREAM:
- datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt);
- ndatalen = conn_enforce_flow_control(conn, vmsg->stream.strm, datalen);
- /* 0 length STREAM frame is allowed */
- if (ndatalen || datalen == 0) {
- send_stream = 1;
- } else {
- stream_blocked = 1;
- }
- break;
- default:
- break;
- }
- }
-
- if (!ppe_pending) {
- switch (type) {
- case NGTCP2_PKT_SHORT:
- hd_flags =
- (pktns->crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE)
- ? NGTCP2_PKT_FLAG_KEY_PHASE
- : NGTCP2_PKT_FLAG_NONE;
- cc->ckm = pktns->crypto.tx.ckm;
- cc->hp_ctx = pktns->crypto.tx.hp_ctx;
-
- /* transport parameter is only valid after handshake completion
- which means we don't know how many connection ID that remote
- peer can accept before handshake completion. */
- if (conn->oscid.datalen &&
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- rv = conn_enqueue_new_connection_id(conn);
- if (rv != 0) {
- return rv;
- }
- }
-
- break;
- case NGTCP2_PKT_0RTT:
- assert(!conn->server);
- if (!conn->early.ckm) {
- return 0;
- }
- hd_flags = NGTCP2_PKT_FLAG_LONG_FORM;
- cc->ckm = conn->early.ckm;
- cc->hp_ctx = conn->early.hp_ctx;
- break;
- default:
- /* Unreachable */
- assert(0);
- }
-
- cc->aead = pktns->crypto.ctx.aead;
- cc->hp = pktns->crypto.ctx.hp;
- cc->aead_overhead = conn->crypto.aead_overhead;
- cc->encrypt = conn->callbacks.encrypt;
- cc->hp_mask = conn->callbacks.hp_mask;
-
- /* TODO Take into account stream frames */
- if ((pktns->tx.frq || send_stream ||
- ngtcp2_ringbuf_len(&conn->rx.path_challenge) ||
- conn_should_send_max_data(conn)) &&
- conn->rx.unsent_max_offset > conn->rx.max_offset) {
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- return rv;
- }
- nfrc->fr.type = NGTCP2_FRAME_MAX_DATA;
- nfrc->fr.max_data.max_data = conn->rx.unsent_max_offset;
- nfrc->next = pktns->tx.frq;
- pktns->tx.frq = nfrc;
-
- conn->rx.max_offset = conn->rx.unsent_max_offset;
- credit_expanded = 1;
- }
-
- ngtcp2_pkt_hd_init(hd, hd_flags, type, &conn->dcid.current.cid,
- &conn->oscid, pktns->tx.last_pkt_num + 1,
- pktns_select_pkt_numlen(pktns), conn->version, 0);
-
- ngtcp2_ppe_init(ppe, dest, destlen, cc);
-
- rv = ngtcp2_ppe_encode_hd(ppe, hd);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return 0;
- }
-
- if (!ngtcp2_ppe_ensure_hp_sample(ppe)) {
- return 0;
- }
-
- if (ngtcp2_ringbuf_len(&conn->rx.path_challenge)) {
- pcent = ngtcp2_ringbuf_get(&conn->rx.path_challenge, 0);
-
- lfr.type = NGTCP2_FRAME_PATH_RESPONSE;
- memcpy(lfr.path_response.data, pcent->data,
- sizeof(lfr.path_response.data));
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_ringbuf_pop_front(&conn->rx.path_challenge);
-
- pkt_empty = 0;
- rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING;
- /* We don't retransmit PATH_RESPONSE. */
- }
- }
-
- rv = conn_create_ack_frame(
- conn, &ackfr, pktns, type, ts, conn_compute_ack_delay(conn),
- conn->local.settings.transport_params.ack_delay_exponent);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- if (ackfr) {
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num,
- ackfr->ack.largest_ack);
- pkt_empty = 0;
- }
- }
-
- build_pkt:
- for (pfrc = &pktns->tx.frq; *pfrc;) {
- if ((*pfrc)->binder &&
- ((*pfrc)->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK)) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
-
- switch ((*pfrc)->fr.type) {
- case NGTCP2_FRAME_STOP_SENDING:
- strm =
- ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id);
- if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD)) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
- break;
- case NGTCP2_FRAME_STREAM:
- assert(0);
- break;
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- if ((*pfrc)->fr.max_streams.max_streams <
- conn->remote.bidi.max_streams) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
- break;
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- if ((*pfrc)->fr.max_streams.max_streams <
- conn->remote.uni.max_streams) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
- break;
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- strm = ngtcp2_conn_find_stream(conn,
- (*pfrc)->fr.max_stream_data.stream_id);
- if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) ||
- (*pfrc)->fr.max_stream_data.max_stream_data < strm->rx.max_offset) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
- break;
- case NGTCP2_FRAME_MAX_DATA:
- if ((*pfrc)->fr.max_data.max_data < conn->rx.max_offset) {
- frc = *pfrc;
- *pfrc = (*pfrc)->next;
- ngtcp2_frame_chain_del(frc, conn->mem);
- continue;
- }
- break;
- case NGTCP2_FRAME_CRYPTO:
- assert(0);
- break;
- }
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- break;
- }
-
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- pfrc = &(*pfrc)->next;
- }
-
- if (rv != NGTCP2_ERR_NOBUF) {
- for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) {
- left = ngtcp2_ppe_left(ppe);
-
- crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns);
- if (crypto_offset == (size_t)-1) {
- conn_cryptofrq_clear(conn, pktns);
- break;
- }
-
- left = ngtcp2_pkt_crypto_max_datalen(crypto_offset, left, left);
-
- if (left == (size_t)-1) {
- break;
- }
-
- rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- if (nfrc == NULL) {
- break;
- }
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
- if (rv != 0) {
- assert(0);
- }
-
- *pfrc = nfrc;
- pfrc = &(*pfrc)->next;
-
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- }
- }
-
- /* Write MAX_STREAM_ID after RESET_STREAM so that we can extend stream
- ID space in one packet. */
- if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL &&
- conn->remote.bidi.unsent_max_streams > conn->remote.bidi.max_streams) {
- rv = conn_call_extend_max_remote_streams_bidi(
- conn, conn->remote.bidi.unsent_max_streams);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI;
- nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams;
- *pfrc = nfrc;
-
- conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams;
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- pfrc = &(*pfrc)->next;
- }
- }
-
- if (rv != NGTCP2_ERR_NOBUF && *pfrc == NULL) {
- if (conn->remote.uni.unsent_max_streams > conn->remote.uni.max_streams) {
- rv = conn_call_extend_max_remote_streams_uni(
- conn, conn->remote.uni.unsent_max_streams);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI;
- nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams;
- *pfrc = nfrc;
-
- conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams;
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd,
- &(*pfrc)->fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- pfrc = &(*pfrc)->next;
- }
- }
- }
-
- if (rv != NGTCP2_ERR_NOBUF) {
- for (; !ngtcp2_pq_empty(&conn->tx.strmq);) {
- strm = ngtcp2_conn_tx_strmq_top(conn);
-
- if (!(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- strm->rx.max_offset < strm->rx.unsent_max_offset) {
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- nfrc->fr.type = NGTCP2_FRAME_MAX_STREAM_DATA;
- nfrc->fr.max_stream_data.stream_id = strm->stream_id;
- nfrc->fr.max_stream_data.max_stream_data = strm->rx.unsent_max_offset;
- ngtcp2_list_insert(nfrc, pfrc);
-
- rv =
- conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- break;
- }
-
- pkt_empty = 0;
- credit_expanded = 1;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
- pfrc = &(*pfrc)->next;
- strm->rx.max_offset = strm->rx.unsent_max_offset;
- }
-
- if (ngtcp2_strm_streamfrq_empty(strm)) {
- ngtcp2_conn_tx_strmq_pop(conn);
- continue;
- }
-
- stream_offset = ngtcp2_strm_streamfrq_unacked_offset(strm);
- if (stream_offset == (uint64_t)-1) {
- ngtcp2_strm_streamfrq_clear(strm);
- ngtcp2_conn_tx_strmq_pop(conn);
- continue;
- }
-
- left = ngtcp2_ppe_left(ppe);
-
- left = ngtcp2_pkt_stream_max_datalen(strm->stream_id, stream_offset,
- left, left);
-
- if (left == (size_t)-1) {
- break;
- }
-
- rv = ngtcp2_strm_streamfrq_pop(strm, &nfrc, left);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- if (nfrc == NULL) {
- /* TODO Why? */
- break;
- }
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
- if (rv != 0) {
- assert(0);
- }
-
- *pfrc = nfrc;
- pfrc = &(*pfrc)->next;
-
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
-
- if (ngtcp2_strm_streamfrq_empty(strm)) {
- ngtcp2_conn_tx_strmq_pop(conn);
- continue;
- }
-
- ngtcp2_conn_tx_strmq_pop(conn);
- ++strm->cycle;
- rv = ngtcp2_conn_tx_strmq_push(conn, strm);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- }
- }
-
- /* Add ACK if MAX_DATA or MAX_STREAM_DATA frame is encoded to
- decrease packet count. */
- if (ackfr == NULL && credit_expanded) {
- rv = conn_create_ack_frame(
- conn, &ackfr, pktns, type, ts, /* ack_delay = */ 0,
- conn->local.settings.transport_params.ack_delay_exponent);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- if (ackfr) {
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- } else {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num,
- ackfr->ack.largest_ack);
- }
- }
- }
-
- if (rv != NGTCP2_ERR_NOBUF && !send_stream &&
- !(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- pktns->rtb.num_retransmittable && pktns->tx.frq == NULL &&
- pktns->rtb.probe_pkt_left) {
- num_reclaimed = ngtcp2_rtb_reclaim_on_pto(&pktns->rtb, conn, pktns,
- pktns->rtb.probe_pkt_left + 1);
- if (num_reclaimed < 0) {
- return rv;
- }
- if (num_reclaimed) {
- goto build_pkt;
- }
-
- /* We had pktns->rtb.num_retransmittable > 0 but the contents of
- those packets have been acknowledged (i.e., retransmission in
- another packet). In this case, we don't have to send any
- probe packet. */
- if (pktns->rtb.num_retransmittable == 0) {
- pktns->rtb.probe_pkt_left = 0;
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
- }
- }
- } else {
- pfrc = conn->pkt.pfrc;
- rtb_entry_flags |= conn->pkt.rtb_entry_flags;
- pkt_empty = conn->pkt.pkt_empty;
- hd_logged = conn->pkt.hd_logged;
- }
-
- left = ngtcp2_ppe_left(ppe);
-
- if (rv != NGTCP2_ERR_NOBUF && send_stream && *pfrc == NULL &&
- (ndatalen = ngtcp2_pkt_stream_max_datalen(
- vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen,
- left)) != (size_t)-1 &&
- (ndatalen || datalen == 0)) {
- datacnt = ngtcp2_vec_copy_at_most(
- data, &ndatalen, NGTCP2_MAX_STREAM_DATACNT, vmsg->stream.data,
- vmsg->stream.datacnt, ndatalen);
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, datacnt, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- nfrc->fr.stream.type = NGTCP2_FRAME_STREAM;
- nfrc->fr.stream.flags = 0;
- nfrc->fr.stream.stream_id = vmsg->stream.strm->stream_id;
- nfrc->fr.stream.offset = vmsg->stream.strm->tx.offset;
- nfrc->fr.stream.datacnt = datacnt;
- ngtcp2_vec_copy(nfrc->fr.stream.data, data, datacnt);
-
- fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN) &&
- ndatalen == datalen;
- nfrc->fr.stream.fin = (uint8_t)fin;
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr);
- if (rv != 0) {
- assert(0);
- }
-
- *pfrc = nfrc;
- pfrc = &(*pfrc)->next;
-
- pkt_empty = 0;
- rtb_entry_flags |=
- NGTCP2_RTB_FLAG_ACK_ELICITING | NGTCP2_RTB_FLAG_RETRANSMITTABLE;
-
- vmsg->stream.strm->tx.offset += ndatalen;
- conn->tx.offset += ndatalen;
-
- if (fin) {
- ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR);
- }
-
- if (vmsg->stream.pdatalen) {
- *vmsg->stream.pdatalen = (ngtcp2_ssize)ndatalen;
- }
- } else {
- send_stream = 0;
- }
-
- if (pkt_empty) {
- assert(rv == 0 || NGTCP2_ERR_NOBUF == rv);
- if (rv == 0 && stream_blocked && ngtcp2_conn_get_max_data_left(conn)) {
- return NGTCP2_ERR_STREAM_DATA_BLOCKED;
- }
-
- if (conn->pktns.rtb.probe_pkt_left == 0) {
- return 0;
- }
- } else if (write_more) {
- conn->pkt.pfrc = pfrc;
- conn->pkt.pkt_empty = pkt_empty;
- conn->pkt.rtb_entry_flags = rtb_entry_flags;
- conn->pkt.hd_logged = hd_logged;
- conn->flags |= NGTCP2_CONN_FLAG_PPE_PENDING;
-
- if (send_stream) {
- return NGTCP2_ERR_WRITE_MORE;
- }
-
- if (ngtcp2_conn_get_max_data_left(conn) && stream_blocked) {
- return NGTCP2_ERR_STREAM_DATA_BLOCKED;
- }
- }
-
- if (!(rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
- if (pktns->tx.num_non_ack_pkt >= NGTCP2_MAX_NON_ACK_TX_PKT) {
- lfr.type = NGTCP2_FRAME_PING;
-
- rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr);
- if (rv != 0) {
- assert(rv == NGTCP2_ERR_NOBUF);
- /* TODO If buffer is too small, PING cannot be written if
- packet is still empty. */
- } else {
- rtb_entry_flags |= NGTCP2_RTB_FLAG_ACK_ELICITING;
- pktns->tx.num_non_ack_pkt = 0;
- }
- } else {
- ++pktns->tx.num_non_ack_pkt;
- }
- } else {
- pktns->tx.num_non_ack_pkt = 0;
- }
-
- /* TODO Push STREAM frame back to ngtcp2_strm if there is an error
- before ngtcp2_rtb_entry is safely created and added. */
- lfr.type = NGTCP2_FRAME_PADDING;
- if ((require_padding ||
- /* Making full sized packet will help GSO a bit */
- ngtcp2_ppe_left(ppe) < 10 ||
- (type == NGTCP2_PKT_0RTT && conn->state == NGTCP2_CS_CLIENT_INITIAL)) &&
- ngtcp2_ppe_left(ppe)) {
- lfr.padding.len = ngtcp2_ppe_padding(ppe);
- } else {
- lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen);
- }
-
- if (lfr.padding.len) {
- padded = 1;
- ngtcp2_log_tx_fr(&conn->log, hd, &lfr);
- ngtcp2_qlog_write_frame(&conn->qlog, &lfr);
- }
-
- nwrite = ngtcp2_ppe_final(ppe, NULL);
- if (nwrite < 0) {
- assert(ngtcp2_err_is_fatal((int)nwrite));
- return nwrite;
- }
-
- ++cc->ckm->use_count;
-
- ngtcp2_qlog_pkt_sent_end(&conn->qlog, hd, (size_t)nwrite);
-
- /* TODO ack-eliciting vs needs-tracking */
- /* probe packet needs tracking but it does not need ACK, could be lost. */
- if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) || padded) {
- rv = ngtcp2_rtb_entry_new(&ent, hd, NULL, ts, (size_t)nwrite,
- rtb_entry_flags, conn->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal((int)nwrite));
- return rv;
- }
-
- if (*pfrc != pktns->tx.frq) {
- ent->frc = pktns->tx.frq;
- pktns->tx.frq = *pfrc;
- *pfrc = NULL;
- }
-
- if ((rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) {
- conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START,
- ts);
- }
-
- rv = conn_on_pkt_sent(conn, &pktns->rtb, ent);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_rtb_entry_del(ent, conn->mem);
- return rv;
- }
-
- if (rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- if (conn->cc.on_pkt_sent) {
- conn->cc.on_pkt_sent(&conn->cc, &conn->cstat,
- ngtcp2_cc_pkt_init(&cc_pkt, hd->pkt_num,
- (size_t)nwrite,
- NGTCP2_PKTNS_ID_APP, ts));
- }
-
- if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE) {
- conn_restart_timer_on_write(conn, ts);
- }
- }
- }
-
- conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_PPE_PENDING;
-
- if (pktns->rtb.probe_pkt_left &&
- (rtb_entry_flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
- --pktns->rtb.probe_pkt_left;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td",
- nwrite);
- }
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- ++pktns->tx.last_pkt_num;
-
- return nwrite;
-}
-
-ngtcp2_ssize
-ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, uint8_t type,
- const ngtcp2_cid *dcid, ngtcp2_frame *fr,
- uint8_t rtb_flags, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_ppe ppe;
- ngtcp2_pkt_hd hd;
- ngtcp2_frame lfr;
- ngtcp2_ssize nwrite;
- ngtcp2_crypto_cc cc;
- ngtcp2_pktns *pktns;
- uint8_t flags;
- ngtcp2_rtb_entry *rtbent;
- int padded = 0;
-
- switch (type) {
- case NGTCP2_PKT_INITIAL:
- pktns = conn->in_pktns;
- cc.aead_overhead = NGTCP2_INITIAL_AEAD_OVERHEAD;
- flags = NGTCP2_PKT_FLAG_LONG_FORM;
- break;
- case NGTCP2_PKT_HANDSHAKE:
- pktns = conn->hs_pktns;
- cc.aead_overhead = conn->crypto.aead_overhead;
- flags = NGTCP2_PKT_FLAG_LONG_FORM;
- break;
- case NGTCP2_PKT_SHORT:
- /* 0 means Short packet. */
- pktns = &conn->pktns;
- cc.aead_overhead = conn->crypto.aead_overhead;
- flags = (pktns->crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE)
- ? NGTCP2_PKT_FLAG_KEY_PHASE
- : NGTCP2_PKT_FLAG_NONE;
- break;
- default:
- /* We don't support 0-RTT packet in this function. */
- assert(0);
- }
-
- cc.aead = pktns->crypto.ctx.aead;
- cc.hp = pktns->crypto.ctx.hp;
- cc.ckm = pktns->crypto.tx.ckm;
- cc.hp_ctx = pktns->crypto.tx.hp_ctx;
- cc.encrypt = conn->callbacks.encrypt;
- cc.hp_mask = conn->callbacks.hp_mask;
-
- ngtcp2_pkt_hd_init(&hd, flags, type, dcid, &conn->oscid,
- pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns),
- conn->version, 0);
-
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
-
- rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return 0;
- }
-
- if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) {
- return 0;
- }
-
- ngtcp2_log_tx_pkt_hd(&conn->log, &hd);
- ngtcp2_qlog_pkt_sent_start(&conn->qlog, &hd);
-
- rv = conn_ppe_write_frame(conn, &ppe, &hd, fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return 0;
- }
-
- lfr.type = NGTCP2_FRAME_PADDING;
- if (type == NGTCP2_PKT_SHORT) {
- lfr.padding.len =
- ngtcp2_ppe_padding_size(&ppe, conn_min_short_pktlen(conn));
- } else {
- lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe);
- }
- if (lfr.padding.len) {
- padded = 1;
- ngtcp2_log_tx_fr(&conn->log, &hd, &lfr);
- ngtcp2_qlog_write_frame(&conn->qlog, &lfr);
- }
-
- nwrite = ngtcp2_ppe_final(&ppe, NULL);
- if (nwrite < 0) {
- return nwrite;
- }
-
- ++cc.ckm->use_count;
-
- ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)nwrite);
-
- /* Do this when we are sure that there is no error. */
- if (fr->type == NGTCP2_FRAME_ACK) {
- ngtcp2_acktr_commit_ack(&pktns->acktr);
- ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, fr->ack.largest_ack);
- }
-
- if ((rtb_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) || padded) {
- rv = ngtcp2_rtb_entry_new(&rtbent, &hd, NULL, ts, (size_t)nwrite, rtb_flags,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent);
- if (rv != 0) {
- ngtcp2_rtb_entry_del(rtbent, conn->mem);
- return rv;
- }
-
- if ((rtb_flags & NGTCP2_RTB_FLAG_ACK_ELICITING) &&
- (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE)) {
- conn_restart_timer_on_write(conn, ts);
- }
- }
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- ++pktns->tx.last_pkt_num;
-
- return nwrite;
-}
-
-/*
- * conn_process_early_rtb makes any pending 0RTT packet Short packet.
- */
-static void conn_process_early_rtb(ngtcp2_conn *conn) {
- ngtcp2_rtb_entry *ent;
- ngtcp2_rtb *rtb = &conn->pktns.rtb;
- ngtcp2_ksl_it it;
-
- for (it = ngtcp2_rtb_head(rtb); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ent = ngtcp2_ksl_it_get(&it);
-
- if ((ent->hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) == 0 ||
- ent->hd.type != NGTCP2_PKT_0RTT) {
- continue;
- }
-
- /* 0-RTT packet is retransmitted as a Short packet. */
- ent->hd.flags &= (uint8_t)~NGTCP2_PKT_FLAG_LONG_FORM;
- ent->hd.type = NGTCP2_PKT_SHORT;
- }
-}
-
-/*
- * conn_handshake_remnants_left returns nonzero if there may be
- * handshake packets the local endpoint has to send, including new
- * packets and lost ones.
- */
-static int conn_handshake_remnants_left(ngtcp2_conn *conn) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
-
- return !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) ||
- (in_pktns && (in_pktns->rtb.num_retransmittable ||
- ngtcp2_ksl_len(&in_pktns->crypto.tx.frq))) ||
- (hs_pktns && (hs_pktns->rtb.num_retransmittable ||
- ngtcp2_ksl_len(&hs_pktns->crypto.tx.frq)));
-}
-
-/*
- * conn_retire_dcid_seq retires destination connection ID denoted by
- * |seq|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) {
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_frame_chain *nfrc;
- int rv;
-
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
- nfrc->fr.retire_connection_id.seq = seq;
- nfrc->next = pktns->tx.frq;
- pktns->tx.frq = nfrc;
-
- ++conn->dcid.num_retire_queued;
-
- return 0;
-}
-
-/*
- * conn_retire_dcid retires |dcid|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-static int conn_retire_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid,
- ngtcp2_tstamp ts) {
- ngtcp2_ringbuf *rb = &conn->dcid.retired;
- ngtcp2_dcid *dest, *stale_dcid;
- int rv;
-
- if (ngtcp2_ringbuf_full(rb)) {
- stale_dcid = ngtcp2_ringbuf_get(rb, 0);
- rv = conn_call_deactivate_dcid(conn, stale_dcid);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_ringbuf_pop_front(rb);
- }
-
- dest = ngtcp2_ringbuf_push_back(rb);
- ngtcp2_dcid_copy(dest, dcid);
- dest->ts_retired = ts;
-
- return conn_retire_dcid_seq(conn, dcid->seq);
-}
-
-/*
- * conn_stop_pv stops the path validation which is currently running.
- * This function does nothing if no path validation is currently being
- * performed.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-static int conn_stop_pv(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- int rv = 0;
- ngtcp2_pv *pv = conn->pv;
-
- if (pv == NULL) {
- return 0;
- }
-
- if (pv->dcid.seq != conn->dcid.current.seq) {
- rv = conn_retire_dcid(conn, &pv->dcid, ts);
- if (rv != 0) {
- goto fin;
- }
- }
-
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->fallback_dcid.seq != conn->dcid.current.seq &&
- pv->fallback_dcid.seq != pv->dcid.seq) {
- rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts);
- if (rv != 0) {
- goto fin;
- }
- }
-
-fin:
- ngtcp2_pv_del(pv);
- conn->pv = NULL;
-
- return rv;
-}
-
-static void conn_reset_congestion_state(ngtcp2_conn *conn);
-
-/*
- * conn_on_path_validation_failed is called when path validation
- * fails. This function may delete |pv|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_on_path_validation_failed(ngtcp2_conn *conn, ngtcp2_pv *pv,
- ngtcp2_tstamp ts) {
- int rv;
-
- rv = conn_call_path_validation(conn, &pv->dcid.ps.path,
- NGTCP2_PATH_VALIDATION_RESULT_FAILURE);
- if (rv != 0) {
- return rv;
- }
-
- if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) {
- ngtcp2_dcid_copy(&conn->dcid.current, &pv->fallback_dcid);
- conn_reset_congestion_state(conn);
- }
-
- return conn_stop_pv(conn, ts);
-}
-
-/*
- * conn_write_path_challenge writes a packet which includes
- * PATH_CHALLENGE frame into |dest| of length |destlen|.
- *
- * This function returns the number of bytes written to |dest|, or one
- * of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn,
- ngtcp2_path *path, uint8_t *dest,
- size_t destlen,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_tstamp expiry;
- ngtcp2_pv *pv = conn->pv;
- ngtcp2_frame lfr;
-
- ngtcp2_pv_ensure_start(pv, ts);
-
- if (ngtcp2_pv_validation_timed_out(pv, ts)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV,
- "path validation was timed out");
- return conn_on_path_validation_failed(conn, pv, ts);
- }
-
- ngtcp2_pv_handle_entry_expiry(pv, ts);
-
- if (ngtcp2_pv_full(pv)) {
- return 0;
- }
-
- if (path) {
- ngtcp2_path_copy(path, &pv->dcid.ps.path);
- }
-
- assert(conn->callbacks.rand);
- rv = conn->callbacks.rand(lfr.path_challenge.data,
- sizeof(lfr.path_challenge.data),
- NGTCP2_RAND_CTX_PATH_CHALLENGE);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- lfr.type = NGTCP2_FRAME_PATH_CHALLENGE;
-
- /* TODO reconsider this. This might get larger pretty quickly than
- validation timeout which is just around 3*PTO. */
- expiry = ts + 6ULL * conn->cstat.initial_rtt * (1ULL << pv->loss_count);
-
- ngtcp2_pv_add_entry(pv, lfr.path_challenge.data, expiry);
-
- return ngtcp2_conn_write_single_frame_pkt(
- conn, dest, destlen, NGTCP2_PKT_SHORT, &pv->dcid.cid, &lfr,
- NGTCP2_RTB_FLAG_ACK_ELICITING, ts);
-}
-
-ngtcp2_ssize ngtcp2_conn_write_pkt(ngtcp2_conn *conn, ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_tstamp ts) {
- return ngtcp2_conn_writev_stream(conn, path, dest, destlen,
- /* pdatalen = */ NULL,
- NGTCP2_WRITE_STREAM_FLAG_NONE,
- /* stream_id = */ -1,
- /* datav = */ NULL, /* datavcnt = */ 0, ts);
-}
-
-/*
- * conn_on_version_negotiation is called when Version Negotiation
- * packet is received. The function decodes the data in the buffer
- * pointed by |payload| whose length is |payloadlen| as Version
- * Negotiation packet payload. The packet header is given in |hd|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Packet payload is badly formatted.
- */
-static int conn_on_version_negotiation(ngtcp2_conn *conn,
- const ngtcp2_pkt_hd *hd,
- const uint8_t *payload,
- size_t payloadlen) {
- uint32_t sv[16];
- uint32_t *p;
- int rv = 0;
- size_t nsv;
- size_t i;
-
- if (payloadlen % sizeof(uint32_t)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if (payloadlen > sizeof(sv)) {
- p = ngtcp2_mem_malloc(conn->mem, payloadlen);
- if (p == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- } else {
- p = sv;
- }
-
- nsv = ngtcp2_pkt_decode_version_negotiation(p, payload, payloadlen);
-
- ngtcp2_log_rx_vn(&conn->log, hd, p, nsv);
-
- for (i = 0; i < nsv; ++i) {
- if (p[i] == conn->version) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "ignore Version Negotiation because it contains version "
- "selected by client");
-
- rv = NGTCP2_ERR_INVALID_ARGUMENT;
- goto fin;
- }
- }
-
- if (conn->callbacks.recv_version_negotiation) {
- rv = conn->callbacks.recv_version_negotiation(conn, hd, p, nsv,
- conn->user_data);
- if (rv != 0) {
- rv = NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
-
- if (rv == 0) {
- /* TODO Just move to the terminal state for now in order not to
- send CONNECTION_CLOSE frame. */
- conn->state = NGTCP2_CS_DRAINING;
- }
-
-fin:
- if (p != sv) {
- ngtcp2_mem_free(conn->mem, p);
- }
-
- return rv;
-}
-
-static uint64_t conn_tx_strmq_first_cycle(ngtcp2_conn *conn) {
- ngtcp2_strm *strm;
-
- if (ngtcp2_pq_empty(&conn->tx.strmq)) {
- return 0;
- }
-
- strm = ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe);
- return strm->cycle;
-}
-
-uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn) {
- ngtcp2_strm *strm;
-
- if (ngtcp2_pq_empty(&conn->tx.strmq)) {
- return 0;
- }
-
- strm = ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe);
- return strm->cycle;
-}
-
-int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_frame_chain **pfrc) {
- ngtcp2_frame_chain **first = pfrc;
- ngtcp2_frame_chain *frc;
- ngtcp2_stream *sfr;
- ngtcp2_strm *strm;
- int rv;
-
- if (*pfrc == NULL) {
- return 0;
- }
-
- for (; *pfrc;) {
- switch ((*pfrc)->fr.type) {
- case NGTCP2_FRAME_STREAM:
- frc = *pfrc;
-
- *pfrc = frc->next;
- frc->next = NULL;
- sfr = &frc->fr.stream;
-
- strm = ngtcp2_conn_find_stream(conn, sfr->stream_id);
- if (!strm) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- break;
- }
- rv = ngtcp2_strm_streamfrq_push(strm, frc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- if (!ngtcp2_strm_is_tx_queued(strm)) {
- strm->cycle = conn_tx_strmq_first_cycle(conn);
- rv = ngtcp2_conn_tx_strmq_push(conn, strm);
- if (rv != 0) {
- return rv;
- }
- }
- break;
- case NGTCP2_FRAME_CRYPTO:
- frc = *pfrc;
-
- *pfrc = frc->next;
- frc->next = NULL;
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- &frc->fr.crypto.offset, frc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- break;
- default:
- pfrc = &(*pfrc)->next;
- }
- }
-
- *pfrc = pktns->tx.frq;
- pktns->tx.frq = *first;
-
- return 0;
-}
-
-/*
- * conn_on_retry is called when Retry packet is received. The
- * function decodes the data in the buffer pointed by |pkt| whose
- * length is |pktlen| as Retry packet. The length of long packet
- * header is given in |hdpktlen|. |pkt| includes packet header.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Packet payload is badly formatted.
- * NGTCP2_ERR_PROTO
- * ODCID does not match; or Token is empty.
- */
-static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
- size_t hdpktlen, const uint8_t *pkt, size_t pktlen) {
- int rv;
- ngtcp2_pkt_retry retry;
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_rtb *rtb = &conn->pktns.rtb;
- ngtcp2_rtb *in_rtb;
- uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1];
- ngtcp2_vec *token;
-
- if (!in_pktns || conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) {
- return 0;
- }
-
- in_rtb = &in_pktns->rtb;
-
- rv = ngtcp2_pkt_decode_retry(&retry, pkt + hdpktlen, pktlen - hdpktlen);
- if (rv != 0) {
- return rv;
- }
-
- retry.odcid = conn->dcid.current.cid;
-
- rv = ngtcp2_pkt_verify_retry_tag(&retry, pkt, pktlen, conn->callbacks.encrypt,
- &conn->crypto.retry_aead,
- &conn->crypto.retry_aead_ctx);
- if (rv != 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "unable to verify Retry packet integrity");
- return rv;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s",
- (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data,
- retry.odcid.datalen));
-
- if (retry.token.len == 0) {
- return NGTCP2_ERR_PROTO;
- }
-
- if (ngtcp2_cid_eq(&conn->dcid.current.cid, &hd->scid)) {
- return 0;
- }
-
- /* DCID must be updated before invoking callback because client
- generates new initial keys there. */
- conn->dcid.current.cid = hd->scid;
- conn->retry_scid = hd->scid;
-
- conn->flags |= NGTCP2_CONN_FLAG_RECV_RETRY;
-
- assert(conn->callbacks.recv_retry);
-
- rv = conn->callbacks.recv_retry(conn, hd, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- conn->state = NGTCP2_CS_CLIENT_INITIAL;
-
- /* Just freeing memory is dangerous because we might free twice. */
-
- rv = ngtcp2_rtb_remove_all(rtb, conn, &conn->pktns, &conn->cstat);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_rtb_remove_all(in_rtb, conn, in_pktns, &conn->cstat);
- if (rv != 0) {
- return rv;
- }
-
- token = &conn->local.settings.token;
-
- ngtcp2_mem_free(conn->mem, token->base);
- token->base = NULL;
- token->len = 0;
-
- token->base = ngtcp2_mem_malloc(conn->mem, retry.token.len);
- if (token->base == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- token->len = retry.token.len;
-
- ngtcp2_cpymem(token->base, retry.token.base, retry.token.len);
-
- reset_conn_stat_recovery(&conn->cstat);
- conn_reset_congestion_state(conn);
-
- return 0;
-}
-
-int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_duration pto = conn_compute_pto(conn, pktns);
-
- rv = ngtcp2_rtb_detect_lost_pkt(&pktns->rtb, conn, pktns, cstat, pto, ts);
- if (rv != 0) {
- return rv;
- }
-
- return 0;
-}
-
-/*
- * conn_recv_ack processes received ACK frame |fr|. |pkt_ts| is the
- * timestamp when packet is received. |ts| should be the current
- * time. Usually they are the same, but for buffered packets,
- * |pkt_ts| would be earlier than |ts|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_ACK_FRAME
- * ACK frame is malformed.
- * NGTCP2_ERR_PROTO
- * |fr| acknowledges a packet this endpoint has not sent.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- */
-static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr,
- ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_frame_chain *frc = NULL;
- ngtcp2_ssize num_acked;
- ngtcp2_conn_stat *cstat = &conn->cstat;
-
- if (pktns->tx.last_pkt_num < fr->largest_ack) {
- return NGTCP2_ERR_PROTO;
- }
-
- rv = ngtcp2_pkt_validate_ack(fr);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_acktr_recv_ack(&pktns->acktr, fr);
-
- num_acked =
- ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pkt_ts, ts);
- if (num_acked < 0) {
- /* TODO assert this */
- assert(ngtcp2_err_is_fatal((int)num_acked));
- ngtcp2_frame_chain_list_del(frc, conn->mem);
- return (int)num_acked;
- }
-
- if (num_acked == 0) {
- return 0;
- }
-
- rv = ngtcp2_conn_detect_lost_pkt(conn, pktns, &conn->cstat, ts);
- if (rv != 0) {
- return rv;
- }
-
- pktns->rtb.probe_pkt_left = 0;
-
- if (cstat->pto_count &&
- (conn->server || (conn->flags & NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED))) {
- /* Reset PTO count but no less than 2 to avoid frequent probe
- packet transmission. */
- cstat->pto_count = ngtcp2_min(cstat->pto_count, 2);
- }
-
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
-
- return 0;
-}
-
-/*
- * conn_assign_recved_ack_delay_unscaled assigns
- * fr->ack_delay_unscaled.
- */
-static void assign_recved_ack_delay_unscaled(ngtcp2_ack *fr,
- uint64_t ack_delay_exponent) {
- fr->ack_delay_unscaled =
- fr->ack_delay * (1UL << ack_delay_exponent) * NGTCP2_MICROSECONDS;
-}
-
-/*
- * conn_recv_max_stream_data processes received MAX_STREAM_DATA frame
- * |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_STREAM_STATE
- * Stream ID indicates that it is a local stream, and the local
- * endpoint has not initiated it; or stream is peer initiated
- * unidirectional stream.
- * NGTCP2_ERR_STREAM_LIMIT
- * Stream ID exceeds allowed limit.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_recv_max_stream_data(ngtcp2_conn *conn,
- const ngtcp2_max_stream_data *fr) {
- ngtcp2_strm *strm;
- ngtcp2_idtr *idtr;
- int local_stream = conn_local_stream(conn, fr->stream_id);
- int bidi = bidi_stream(fr->stream_id);
- int rv;
-
- if (bidi) {
- if (local_stream) {
- if (conn->local.bidi.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
- } else if (conn->remote.bidi.max_streams <
- ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.bidi.idtr;
- } else {
- if (!local_stream || conn->local.uni.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
-
- idtr = &conn->remote.uni.idtr;
- }
-
- strm = ngtcp2_conn_find_stream(conn, fr->stream_id);
- if (strm == NULL) {
- if (local_stream) {
- /* Stream has been closed. */
- return 0;
- }
-
- rv = ngtcp2_idtr_open(idtr, fr->stream_id);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- assert(rv == NGTCP2_ERR_STREAM_IN_USE);
- /* Stream has been closed. */
- return 0;
- }
-
- strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm));
- if (strm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, strm);
- return rv;
- }
- }
-
- if (strm->tx.max_offset < fr->max_stream_data) {
- strm->tx.max_offset = fr->max_stream_data;
-
- /* Don't call callback if stream is half-closed local */
- if (strm->flags & NGTCP2_STRM_FLAG_SHUT_WR) {
- return 0;
- }
-
- rv = conn_call_extend_max_stream_data(conn, strm, fr->stream_id,
- fr->max_stream_data);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_recv_max_data processes received MAX_DATA frame |fr|.
- */
-static void conn_recv_max_data(ngtcp2_conn *conn, const ngtcp2_max_data *fr) {
- conn->tx.max_offset = ngtcp2_max(conn->tx.max_offset, fr->max_data);
-}
-
-/*
- * conn_buffer_pkt buffers |pkt| of length |pktlen|, chaining it from
- * |*ppc|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_buffer_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- const ngtcp2_path *path, const uint8_t *pkt,
- size_t pktlen, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_pkt_chain **ppc = &pktns->rx.buffed_pkts, *pc;
- size_t i;
- for (i = 0; *ppc && i < NGTCP2_MAX_NUM_BUFFED_RX_PKTS;
- ppc = &(*ppc)->next, ++i)
- ;
-
- if (i == NGTCP2_MAX_NUM_BUFFED_RX_PKTS) {
- return 0;
- }
-
- rv = ngtcp2_pkt_chain_new(&pc, path, pkt, pktlen, ts, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- *ppc = pc;
-
- return 0;
-}
-
-/*
- * conn_ensure_decrypt_buffer ensures that conn->crypto.decrypt_buf
- * has at least |n| bytes space.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_ensure_decrypt_buffer(ngtcp2_conn *conn, size_t n) {
- uint8_t *nbuf;
- size_t len;
- ngtcp2_vec *decrypt_buf = &conn->crypto.decrypt_buf;
-
- if (decrypt_buf->len >= n) {
- return 0;
- }
-
- len = decrypt_buf->len == 0 ? 2048 : decrypt_buf->len * 2;
- for (; len < n; len *= 2)
- ;
- nbuf = ngtcp2_mem_realloc(conn->mem, decrypt_buf->base, len);
- if (nbuf == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- decrypt_buf->base = nbuf;
- decrypt_buf->len = len;
-
- return 0;
-}
-
-/*
- * decrypt_pkt decrypts the data pointed by |payload| whose length is
- * |payloadlen|, and writes plaintext data to the buffer pointed by
- * |dest|. The buffer pointed by |ad| is the Additional Data, and its
- * length is |adlen|. |pkt_num| is used to create a nonce. |ckm| is
- * the cryptographic key, and iv to use. |decrypt| is a callback
- * function which actually decrypts a packet.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- * NGTCP2_ERR_TLS_DECRYPT
- * TLS backend failed to decrypt data.
- */
-static ngtcp2_ssize decrypt_pkt(uint8_t *dest, const ngtcp2_crypto_aead *aead,
- const uint8_t *payload, size_t payloadlen,
- const uint8_t *ad, size_t adlen,
- int64_t pkt_num, ngtcp2_crypto_km *ckm,
- ngtcp2_decrypt decrypt, size_t aead_overhead) {
- /* TODO nonce is limited to 64 bytes. */
- uint8_t nonce[64];
- int rv;
-
- assert(sizeof(nonce) >= ckm->iv.len);
-
- ngtcp2_crypto_create_nonce(nonce, ckm->iv.base, ckm->iv.len, pkt_num);
-
- rv = decrypt(dest, aead, &ckm->aead_ctx, payload, payloadlen, nonce,
- ckm->iv.len, ad, adlen);
-
- if (rv != 0) {
- if (rv == NGTCP2_ERR_TLS_DECRYPT) {
- return rv;
- }
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- assert(payloadlen >= aead_overhead);
-
- return (ngtcp2_ssize)(payloadlen - aead_overhead);
-}
-
-/*
- * decrypt_hp decryptes packet header. The packet number starts at
- * |pkt| + |pkt_num_offset|. The entire plaintext QUIC packet header
- * will be written to the buffer pointed by |dest| whose capacity is
- * |destlen|.
- *
- * This function returns the number of bytes written to |dest|, or one
- * of the following negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * Packet is badly formatted
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed; or it does not return
- * expected result.
- */
-static ngtcp2_ssize decrypt_hp(ngtcp2_pkt_hd *hd, uint8_t *dest, size_t destlen,
- const ngtcp2_crypto_cipher *hp,
- const uint8_t *pkt, size_t pktlen,
- size_t pkt_num_offset, ngtcp2_crypto_km *ckm,
- const ngtcp2_crypto_cipher_ctx *hp_ctx,
- ngtcp2_hp_mask hp_mask) {
- size_t sample_offset;
- uint8_t *p = dest;
- uint8_t mask[NGTCP2_HP_MASKLEN];
- size_t i;
- int rv;
-
- assert(hp_mask);
- assert(ckm);
- assert(destlen >= pkt_num_offset + 4);
-
- if (pkt_num_offset + 4 + NGTCP2_HP_SAMPLELEN > pktlen) {
- return NGTCP2_ERR_PROTO;
- }
-
- p = ngtcp2_cpymem(p, pkt, pkt_num_offset);
-
- sample_offset = pkt_num_offset + 4;
-
- rv = hp_mask(mask, hp, hp_ctx, pkt + sample_offset);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- dest[0] = (uint8_t)(dest[0] ^ (mask[0] & 0x0f));
- } else {
- dest[0] = (uint8_t)(dest[0] ^ (mask[0] & 0x1f));
- if (dest[0] & NGTCP2_SHORT_KEY_PHASE_BIT) {
- hd->flags |= NGTCP2_PKT_FLAG_KEY_PHASE;
- }
- }
-
- hd->pkt_numlen = (size_t)((dest[0] & NGTCP2_PKT_NUMLEN_MASK) + 1);
-
- for (i = 0; i < hd->pkt_numlen; ++i) {
- *p++ = *(pkt + pkt_num_offset + i) ^ mask[i + 1];
- }
-
- hd->pkt_num = ngtcp2_get_pkt_num(p - hd->pkt_numlen, hd->pkt_numlen);
-
- return p - dest;
-}
-
-/*
- * conn_emit_pending_crypto_data delivers pending stream data to the
- * application due to packet reordering.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed
- * NGTCP2_ERR_CRYPTO
- * TLS backend reported error
- */
-static int conn_emit_pending_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- ngtcp2_strm *strm,
- uint64_t rx_offset) {
- size_t datalen;
- const uint8_t *data;
- int rv;
- uint64_t offset;
-
- if (!strm->rx.rob) {
- return 0;
- }
-
- for (;;) {
- datalen = ngtcp2_rob_data_at(strm->rx.rob, &data, rx_offset);
- if (datalen == 0) {
- assert(rx_offset == ngtcp2_strm_rx_offset(strm));
- return 0;
- }
-
- offset = rx_offset;
- rx_offset += datalen;
-
- rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen);
- }
-}
-
-/*
- * conn_recv_connection_close is called when CONNECTION_CLOSE or
- * APPLICATION_CLOSE frame is received.
- */
-static void conn_recv_connection_close(ngtcp2_conn *conn,
- ngtcp2_connection_close *fr) {
- conn->state = NGTCP2_CS_DRAINING;
- if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) {
- conn->rx.ccec.type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT;
- } else {
- conn->rx.ccec.type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION;
- }
- conn->rx.ccec.error_code = fr->error_code;
-}
-
-static void conn_recv_path_challenge(ngtcp2_conn *conn,
- ngtcp2_path_challenge *fr) {
- ngtcp2_path_challenge_entry *ent;
-
- ent = ngtcp2_ringbuf_push_front(&conn->rx.path_challenge);
- ngtcp2_path_challenge_entry_init(ent, fr->data);
-}
-
-/*
- * conn_reset_congestion_state resets congestion state.
- */
-static void conn_reset_congestion_state(ngtcp2_conn *conn) {
- conn_reset_conn_stat_cc(conn, &conn->cstat);
-
- conn_reset_rx_rate(conn);
-
- conn->cc.reset(&conn->cc);
-
- if (conn->hs_pktns) {
- ngtcp2_rtb_reset_cc_state(&conn->hs_pktns->rtb,
- conn->hs_pktns->tx.last_pkt_num + 1);
- }
- ngtcp2_rtb_reset_cc_state(&conn->pktns.rtb, conn->pktns.tx.last_pkt_num + 1);
- ngtcp2_rst_init(&conn->rst);
-}
-
-static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_pv *pv = conn->pv;
-
- if (!pv) {
- return 0;
- }
-
- rv = ngtcp2_pv_validate(pv, fr->data);
- if (rv != 0) {
- if (rv == NGTCP2_ERR_PATH_VALIDATION_FAILED) {
- return conn_on_path_validation_failed(conn, pv, ts);
- }
- return 0;
- }
-
- if (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)) {
- rv = conn_retire_dcid(conn, &conn->dcid.current, ts);
- if (rv != 0) {
- goto fail;
- }
- ngtcp2_dcid_copy(&conn->dcid.current, &pv->dcid);
- conn_reset_congestion_state(conn);
- }
-
- rv = conn_call_path_validation(conn, &pv->dcid.ps.path,
- NGTCP2_PATH_VALIDATION_RESULT_SUCCESS);
- if (rv != 0) {
- goto fail;
- }
-
-fail:
- return conn_stop_pv(conn, ts);
-}
-
-/*
- * pkt_num_bits returns the number of bits available when packet
- * number is encoded in |pkt_numlen| bytes.
- */
-static size_t pkt_num_bits(size_t pkt_numlen) {
- switch (pkt_numlen) {
- case 1:
- return 8;
- case 2:
- return 16;
- case 3:
- return 24;
- case 4:
- return 32;
- default:
- assert(0);
- }
-}
-
-/*
- * pktns_pkt_num_is_duplicate returns nonzero if |pkt_num| is
- * duplicated packet number.
- */
-static int pktns_pkt_num_is_duplicate(ngtcp2_pktns *pktns, int64_t pkt_num) {
- return ngtcp2_gaptr_is_pushed(&pktns->rx.pngap, (uint64_t)pkt_num, 1);
-}
-
-/*
- * pktns_commit_recv_pkt_num marks packet number |pkt_num| as
- * received.
- */
-static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num,
- ngtcp2_tstamp ts) {
- int rv;
-
- if (pktns->rx.max_pkt_num + 1 != pkt_num) {
- ngtcp2_acktr_immediate_ack(&pktns->acktr);
- }
- if (pktns->rx.max_pkt_num < pkt_num) {
- pktns->rx.max_pkt_num = pkt_num;
- pktns->rx.max_pkt_ts = ts;
- }
-
- rv = ngtcp2_gaptr_push(&pktns->rx.pngap, (uint64_t)pkt_num, 1);
- if (rv != 0) {
- return rv;
- }
-
- if (ngtcp2_ksl_len(&pktns->rx.pngap.gap) > 256) {
- ngtcp2_gaptr_drop_first_gap(&pktns->rx.pngap);
- }
-
- return 0;
-}
-
-/*
- * verify_token verifies |hd| contains |token| in its token field. It
- * returns 0 if it succeeds, or NGTCP2_ERR_PROTO.
- */
-static int verify_token(const ngtcp2_vec *token, const ngtcp2_pkt_hd *hd) {
- if (token->len == hd->token.len &&
- ngtcp2_cmemeq(token->base, hd->token.base, token->len)) {
- return 0;
- }
- return NGTCP2_ERR_PROTO;
-}
-
-static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
- ngtcp2_strm *strm, const ngtcp2_crypto *fr);
-
-static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts);
-
-static int conn_process_buffered_protected_pkt(ngtcp2_conn *conn,
- ngtcp2_pktns *pktns,
- ngtcp2_tstamp ts);
-
-/*
- * conn_recv_handshake_pkt processes received packet |pkt| whose
- * length is |pktlen| during handshake period. The buffer pointed by
- * |pkt| might contain multiple packets. This function only processes
- * one packet. |pkt_ts| is the timestamp when packet is received.
- * |ts| should be the current time. Usually they are the same, but
- * for buffered packets, |pkt_ts| would be earlier than |ts|.
- *
- * This function returns the number of bytes it reads if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_RECV_VERSION_NEGOTIATION
- * Version Negotiation packet is received.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_DISCARD_PKT
- * Packet was discarded because plain text header was malformed;
- * or its payload could not be decrypted.
- * NGTCP2_ERR_FRAME_FORMAT
- * Frame is badly formatted
- * NGTCP2_ERR_ACK_FRAME
- * ACK frame is malformed.
- * NGTCP2_ERR_CRYPTO
- * TLS stack reported error.
- * NGTCP2_ERR_PROTO
- * Generic QUIC protocol error.
- *
- * In addition to the above error codes, error codes returned from
- * conn_recv_pkt are also returned.
- */
-static ngtcp2_ssize conn_recv_handshake_pkt(ngtcp2_conn *conn,
- const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp pkt_ts,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nread;
- ngtcp2_pkt_hd hd;
- ngtcp2_max_frame mfr;
- ngtcp2_frame *fr = &mfr.fr;
- int rv;
- int require_ack = 0;
- size_t hdpktlen;
- const uint8_t *payload;
- size_t payloadlen;
- ngtcp2_ssize nwrite;
- uint8_t plain_hdpkt[1500];
- ngtcp2_crypto_aead *aead;
- ngtcp2_crypto_cipher *hp;
- ngtcp2_crypto_km *ckm;
- ngtcp2_crypto_cipher_ctx *hp_ctx;
- ngtcp2_hp_mask hp_mask;
- ngtcp2_decrypt decrypt;
- size_t aead_overhead;
- ngtcp2_pktns *pktns;
- ngtcp2_strm *crypto;
- ngtcp2_crypto_level crypto_level;
- int invalid_reserved_bits = 0;
-
- if (pktlen == 0) {
- return 0;
- }
-
- if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT)) {
- if (conn->state == NGTCP2_CS_SERVER_INITIAL) {
- /* Ignore Short packet unless server's first Handshake packet
- has been transmitted. */
- return (ngtcp2_ssize)pktlen;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "buffering Short packet len=%zu", pktlen);
-
- rv = conn_buffer_pkt(conn, &conn->pktns, path, pkt, pktlen, ts);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- return (ngtcp2_ssize)pktlen;
- }
-
- nread = ngtcp2_pkt_decode_hd_long(&hd, pkt, pktlen);
- if (nread < 0) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- switch (hd.type) {
- case NGTCP2_PKT_VERSION_NEGOTIATION:
- hdpktlen = (size_t)nread;
-
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
-
- if (conn->server) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- /* Receiving Version Negotiation packet after getting Handshake
- packet from server is invalid. */
- if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (!ngtcp2_cid_eq(&conn->oscid, &hd.dcid)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) {
- /* Just discard invalid Version Negotiation packet */
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched SCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- rv = conn_on_version_negotiation(conn, &hd, pkt + hdpktlen,
- pktlen - hdpktlen);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- return NGTCP2_ERR_DISCARD_PKT;
- }
- return NGTCP2_ERR_RECV_VERSION_NEGOTIATION;
- case NGTCP2_PKT_RETRY:
- hdpktlen = (size_t)nread;
-
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
-
- if (conn->server) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- /* Receiving Retry packet after getting Initial packet from server
- is invalid. */
- if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- rv = conn_on_retry(conn, &hd, hdpktlen, pkt, pktlen);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- return NGTCP2_ERR_DISCARD_PKT;
- }
- return (ngtcp2_ssize)pktlen;
- }
-
- if (pktlen < (size_t)nread + hd.len) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- pktlen = (size_t)nread + hd.len;
-
- if (conn->version != hd.version) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- /* Quoted from spec: if subsequent packets of those types include a
- different Source Connection ID, they MUST be discarded. */
- if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) &&
- !ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) {
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched SCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- switch (hd.type) {
- case NGTCP2_PKT_0RTT:
- if (!conn->server) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
- if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) {
- if (conn->early.ckm) {
- ngtcp2_ssize nread2;
- /* TODO Avoid to parse header twice. */
- nread2 = conn_recv_pkt(conn, &conn->dcid.current.ps.path, pkt, pktlen,
- pkt_ts, ts);
- if (nread2 < 0) {
- return nread2;
- }
- }
-
- /* Discard 0-RTT packet if we don't have a key to decrypt it. */
- return (ngtcp2_ssize)pktlen;
- }
-
- /* Buffer re-ordered 0-RTT packet. */
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "buffering 0-RTT packet len=%zu", pktlen);
-
- rv = conn_buffer_pkt(conn, conn->in_pktns, path, pkt, pktlen, ts);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
-
- return (ngtcp2_ssize)pktlen;
- case NGTCP2_PKT_INITIAL:
- if (!conn->in_pktns) {
- ngtcp2_log_info(
- &conn->log, NGTCP2_LOG_EVENT_PKT,
- "Initial packet is discarded because keys have been discarded");
- return (ngtcp2_ssize)pktlen;
- }
-
- assert(conn->in_pktns);
-
- if (conn->server) {
- if (conn->local.settings.token.len) {
- rv = verify_token(&conn->local.settings.token, &hd);
- if (rv != 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because token is invalid");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- }
- if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) == 0) {
- /* Set rcid here so that it is available to callback. If this
- packet is discarded later in this function and no packet is
- processed in this connection attempt so far, connection
- will be dropped. */
- conn->rcid = hd.dcid;
-
- rv = conn_call_recv_client_initial(conn, &hd.dcid);
- if (rv != 0) {
- return rv;
- }
- }
- } else if (hd.token.len != 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because token is not empty");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- pktns = conn->in_pktns;
- aead_overhead = NGTCP2_INITIAL_AEAD_OVERHEAD;
- crypto = &pktns->crypto.strm;
- crypto_level = NGTCP2_CRYPTO_LEVEL_INITIAL;
-
- break;
- case NGTCP2_PKT_HANDSHAKE:
- if (!conn->hs_pktns->crypto.rx.ckm) {
- if (conn->server) {
- ngtcp2_log_info(
- &conn->log, NGTCP2_LOG_EVENT_PKT,
- "Handshake packet at this point is unexpected and discarded");
- return (ngtcp2_ssize)pktlen;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "buffering Handshake packet len=%zu", pktlen);
-
- rv = conn_buffer_pkt(conn, conn->hs_pktns, path, pkt, pktlen, ts);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- return rv;
- }
- return (ngtcp2_ssize)pktlen;
- }
-
- pktns = conn->hs_pktns;
- aead_overhead = conn->crypto.aead_overhead;
- crypto = &pktns->crypto.strm;
- crypto_level = NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
-
- break;
- default:
- /* unknown packet type */
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of unknown packet type");
- return (ngtcp2_ssize)pktlen;
- }
-
- hp_mask = conn->callbacks.hp_mask;
- decrypt = conn->callbacks.decrypt;
- aead = &pktns->crypto.ctx.aead;
- hp = &pktns->crypto.ctx.hp;
- ckm = pktns->crypto.rx.ckm;
- hp_ctx = &pktns->crypto.rx.hp_ctx;
-
- assert(ckm);
- assert(hp_mask);
- assert(decrypt);
-
- nwrite = decrypt_hp(&hd, plain_hdpkt, sizeof(plain_hdpkt), hp, pkt, pktlen,
- (size_t)nread, ckm, hp_ctx, hp_mask);
- if (nwrite < 0) {
- if (ngtcp2_err_is_fatal((int)nwrite)) {
- return nwrite;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decrypt packet number");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- hdpktlen = (size_t)nwrite;
- payload = pkt + hdpktlen;
- payloadlen = hd.len - hd.pkt_numlen;
-
- hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num,
- pkt_num_bits(hd.pkt_numlen));
- if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num);
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
-
- rv = ngtcp2_pkt_verify_reserved_bits(plain_hdpkt[0]);
- if (rv != 0) {
- invalid_reserved_bits = 1;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet has incorrect reserved bits");
-
- /* Will return error after decrypting payload */
- }
-
- if (pktns_pkt_num_is_duplicate(pktns, hd.pkt_num)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was discarded because of duplicated packet number");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- rv = conn_ensure_decrypt_buffer(conn, payloadlen);
- if (rv != 0) {
- return rv;
- }
-
- nwrite = decrypt_pkt(conn->crypto.decrypt_buf.base, aead, payload, payloadlen,
- plain_hdpkt, hdpktlen, hd.pkt_num, ckm, decrypt,
- aead_overhead);
- if (nwrite < 0) {
- if (ngtcp2_err_is_fatal((int)nwrite)) {
- return nwrite;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decrypt packet payload");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (invalid_reserved_bits) {
- return NGTCP2_ERR_PROTO;
- }
-
- payload = conn->crypto.decrypt_buf.base;
- payloadlen = (size_t)nwrite;
-
- switch (hd.type) {
- case NGTCP2_PKT_INITIAL:
- if (!conn->server || ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED) &&
- !ngtcp2_cid_eq(&conn->rcid, &hd.dcid))) {
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- }
- break;
- case NGTCP2_PKT_HANDSHAKE:
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- break;
- default:
- assert(0);
- }
-
- if (payloadlen == 0) {
- /* QUIC packet must contain at least one frame */
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (hd.type == NGTCP2_PKT_INITIAL &&
- !(conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED)) {
- conn->flags |= NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED;
- if (!conn->server) {
- conn->dcid.current.cid = hd.scid;
- }
- }
-
- ngtcp2_qlog_pkt_received_start(&conn->qlog, &hd);
-
- for (; payloadlen;) {
- nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen);
- if (nread < 0) {
- return nread;
- }
-
- payload += nread;
- payloadlen -= (size_t)nread;
-
- if (fr->type == NGTCP2_FRAME_ACK) {
- fr->ack.ack_delay = 0;
- fr->ack.ack_delay_unscaled = 0;
- }
-
- ngtcp2_log_rx_fr(&conn->log, &hd, fr);
-
- switch (fr->type) {
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
- rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGTCP2_FRAME_PADDING:
- break;
- case NGTCP2_FRAME_CRYPTO:
- rv = conn_recv_crypto(conn, crypto_level, crypto, &fr->crypto);
- if (rv != 0) {
- return rv;
- }
- require_ack = 1;
- break;
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- conn_recv_connection_close(conn, &fr->connection_close);
- break;
- case NGTCP2_FRAME_PING:
- require_ack = 1;
- break;
- default:
- return NGTCP2_ERR_PROTO;
- }
-
- ngtcp2_qlog_write_frame(&conn->qlog, fr);
- }
-
- if (conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) {
- /* Successful processing of Handshake packet from client verifies
- source address. */
- conn->flags |= NGTCP2_CONN_FLAG_SADDR_VERIFIED;
- }
-
- ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen);
-
- rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- if (require_ack && ++pktns->acktr.rx_npkt >= NGTCP2_NUM_IMMEDIATE_ACK_PKT) {
- ngtcp2_acktr_immediate_ack(&pktns->acktr);
- }
-
- rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack,
- pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- conn_restart_timer_on_read(conn, ts);
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING
- : (ngtcp2_ssize)pktlen;
-}
-
-/*
- * conn_recv_handshake_cpkt processes compound packet during
- * handshake. The buffer pointed by |pkt| might contain multiple
- * packets. The Short packet must be the last one because it does not
- * have payload length field.
- *
- * This function returns the same error code returned by
- * conn_recv_handshake_pkt.
- */
-static int conn_recv_handshake_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nread;
-
- conn->cstat.bytes_recv += pktlen;
-
- while (pktlen) {
- nread = conn_recv_handshake_pkt(conn, path, pkt, pktlen, ts, ts);
- if (nread < 0) {
- if (ngtcp2_err_is_fatal((int)nread)) {
- return (int)nread;
- }
-
- if (nread == NGTCP2_ERR_DRAINING) {
- return NGTCP2_ERR_DRAINING;
- }
-
- if ((pkt[0] & NGTCP2_HEADER_FORM_BIT) &&
- /* Not a Version Negotiation packet */
- pktlen > 4 && ngtcp2_get_uint32(&pkt[1]) > 0 &&
- ngtcp2_pkt_get_type_long(pkt[0]) == NGTCP2_PKT_INITIAL) {
- if (conn->server) {
- /* If server discards first Initial, then drop connection
- state. This is because SCID in packet might be corrupted
- and the current connection state might wrongly discard
- valid packet and prevent the handshake from
- completing. */
- if (conn->in_pktns && conn->in_pktns->rx.max_pkt_num == -1) {
- /* If this is crypto related error, then return normally
- in order to send CONNECTION_CLOSE with TLS alert (e.g.,
- no_application_protocol). */
- if (nread == NGTCP2_ERR_CRYPTO) {
- return (int)nread;
- }
- return NGTCP2_ERR_DROP_CONN;
- }
- } else if (nread == NGTCP2_ERR_CRYPTO) {
- /* If client gets crypto error from TLS stack, it is
- unrecoverable, therefore drop connection. */
- return (int)nread;
- }
- return 0;
- }
-
- if (nread == NGTCP2_ERR_DISCARD_PKT) {
- return 0;
- }
-
- return (int)nread;
- }
-
- assert(pktlen >= (size_t)nread);
- pkt += nread;
- pktlen -= (size_t)nread;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "read packet %td left %zu", nread, pktlen);
- }
-
- return 0;
-}
-
-int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
- int64_t stream_id, void *stream_user_data) {
- int rv;
- uint64_t max_rx_offset;
- uint64_t max_tx_offset;
- int local_stream = conn_local_stream(conn, stream_id);
-
- if (bidi_stream(stream_id)) {
- if (local_stream) {
- max_rx_offset = conn->local.settings.transport_params
- .initial_max_stream_data_bidi_local;
- max_tx_offset =
- conn->remote.transport_params.initial_max_stream_data_bidi_remote;
- } else {
- max_rx_offset = conn->local.settings.transport_params
- .initial_max_stream_data_bidi_remote;
- max_tx_offset =
- conn->remote.transport_params.initial_max_stream_data_bidi_local;
- }
- } else if (local_stream) {
- max_rx_offset = 0;
- max_tx_offset = conn->remote.transport_params.initial_max_stream_data_uni;
- } else {
- max_rx_offset =
- conn->local.settings.transport_params.initial_max_stream_data_uni;
- max_tx_offset = 0;
- }
-
- rv = ngtcp2_strm_init(strm, stream_id, NGTCP2_STRM_FLAG_NONE, max_rx_offset,
- max_tx_offset, stream_user_data, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_map_insert(&conn->strms, &strm->me);
- if (rv != 0) {
- assert(rv != NGTCP2_ERR_INVALID_ARGUMENT);
- goto fail;
- }
-
- if (!conn_local_stream(conn, stream_id)) {
- rv = conn_call_stream_open(conn, strm);
- if (rv != 0) {
- goto fail;
- }
- }
-
- return 0;
-
-fail:
- ngtcp2_strm_free(strm);
- return rv;
-}
-
-/*
- * conn_emit_pending_stream_data passes buffered ordered stream data
- * to the application. |rx_offset| is the first offset to deliver to
- * the application. This function assumes that the data up to
- * |rx_offset| has been delivered already. This function only passes
- * the ordered data without any gap. If there is a gap, it stops
- * providing the data to the application, and returns.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t rx_offset) {
- size_t datalen;
- const uint8_t *data;
- int rv;
- uint64_t offset;
- uint32_t sdflags;
- int handshake_completed = conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED;
-
- if (!strm->rx.rob) {
- return 0;
- }
-
- for (;;) {
- /* Stop calling callback if application has called
- ngtcp2_conn_shutdown_stream_read() inside the callback.
- Because it doubly counts connection window. */
- if (strm->flags & (NGTCP2_STRM_FLAG_STOP_SENDING)) {
- return 0;
- }
-
- datalen = ngtcp2_rob_data_at(strm->rx.rob, &data, rx_offset);
- if (datalen == 0) {
- assert(rx_offset == ngtcp2_strm_rx_offset(strm));
- return 0;
- }
-
- offset = rx_offset;
- rx_offset += datalen;
-
- sdflags = NGTCP2_STREAM_DATA_FLAG_NONE;
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- rx_offset == strm->rx.last_offset) {
- sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN;
- }
- if (!handshake_completed) {
- sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT;
- }
-
- rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, datalen);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen);
- }
-}
-
-/*
- * conn_recv_crypto is called when CRYPTO frame |fr| is received.
- * |rx_offset_base| is the offset in the entire TLS handshake stream.
- * fr->offset specifies the offset in each encryption level.
- * |max_rx_offset| is, if it is nonzero, the maximum offset in the
- * entire TLS handshake stream that |fr| can carry. |crypto_level| is
- * the encryption level where this data is received.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * CRYPTO frame has invalid offset.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CRYPTO
- * TLS stack reported error.
- * NGTCP2_ERR_FRAME_ENCODING
- * The end offset exceeds the maximum value.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level,
- ngtcp2_strm *crypto, const ngtcp2_crypto *fr) {
- uint64_t fr_end_offset;
- uint64_t rx_offset;
- int rv;
-
- if (fr->datacnt == 0) {
- return 0;
- }
-
- fr_end_offset = fr->offset + fr->data[0].len;
-
- if (NGTCP2_MAX_VARINT < fr_end_offset) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- rx_offset = ngtcp2_strm_rx_offset(crypto);
-
- if (fr_end_offset <= rx_offset) {
- if (conn->server && crypto_level == NGTCP2_CRYPTO_LEVEL_INITIAL) {
- /* recovery draft: Speeding Up Handshake Completion
-
- When a server receives an Initial packet containing duplicate
- CRYPTO data, it can assume the client did not receive all of
- the server's CRYPTO data sent in Initial packets, or the
- client's estimated RTT is too small. ... To speed up
- handshake completion under these conditions, an endpoint MAY
- send a packet containing unacknowledged CRYPTO data earlier
- than the PTO expiry, subject to address validation limits;
- ... */
- conn->in_pktns->rtb.probe_pkt_left = 1;
- conn->hs_pktns->rtb.probe_pkt_left = 1;
- }
- return 0;
- }
-
- crypto->rx.last_offset = ngtcp2_max(crypto->rx.last_offset, fr_end_offset);
-
- /* TODO Before dispatching incoming data to TLS stack, make sure
- that previous data in previous encryption level has been
- completely sent to TLS stack. Usually, if data is left, it is an
- error because key is generated after consuming all data in the
- previous encryption level. */
- if (fr->offset <= rx_offset) {
- size_t ncut = (size_t)(rx_offset - fr->offset);
- const uint8_t *data = fr->data[0].base + ncut;
- size_t datalen = fr->data[0].len - ncut;
- uint64_t offset = rx_offset;
-
- rx_offset += datalen;
- rv = ngtcp2_strm_update_rx_offset(crypto, rx_offset);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_emit_pending_crypto_data(conn, crypto_level, crypto, rx_offset);
- if (rv != 0) {
- return rv;
- }
- } else if (fr_end_offset - rx_offset > NGTCP2_MAX_REORDERED_CRYPTO_DATA) {
- return NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED;
- } else {
- rv = ngtcp2_strm_recv_reordering(crypto, fr->data[0].base, fr->data[0].len,
- fr->offset);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_max_data_violated returns nonzero if receiving |datalen|
- * violates connection flow control on local endpoint.
- */
-static int conn_max_data_violated(ngtcp2_conn *conn, uint64_t datalen) {
- return conn->rx.max_offset - conn->rx.offset < datalen;
-}
-
-/*
- * conn_recv_stream is called when STREAM frame |fr| is received.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_STREAM_STATE
- * STREAM frame is received for a local stream which is not
- * initiated; or STREAM frame is received for a local
- * unidirectional stream
- * NGTCP2_ERR_STREAM_LIMIT
- * STREAM frame has remote stream ID which is strictly greater
- * than the allowed limit.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_FLOW_CONTROL
- * Flow control limit is violated; or the end offset of stream
- * data is beyond the NGTCP2_MAX_VARINT.
- * NGTCP2_ERR_FINAL_SIZE
- * STREAM frame has strictly larger end offset than it is
- * permitted.
- */
-static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_strm *strm;
- ngtcp2_idtr *idtr;
- uint64_t rx_offset, fr_end_offset;
- int local_stream;
- int bidi;
- size_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
- uint32_t sdflags = NGTCP2_STREAM_DATA_FLAG_NONE;
-
- local_stream = conn_local_stream(conn, fr->stream_id);
- bidi = bidi_stream(fr->stream_id);
-
- if (bidi) {
- if (local_stream) {
- if (conn->local.bidi.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
- } else if (conn->remote.bidi.max_streams <
- ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.bidi.idtr;
- } else {
- if (local_stream) {
- return NGTCP2_ERR_STREAM_STATE;
- }
- if (conn->remote.uni.max_streams < ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.uni.idtr;
- }
-
- if (NGTCP2_MAX_VARINT - datalen < fr->offset) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
-
- strm = ngtcp2_conn_find_stream(conn, fr->stream_id);
- if (strm == NULL) {
- if (local_stream) {
- /* TODO The stream has been closed. This should be responded
- with RESET_STREAM, or simply ignored. */
- return 0;
- }
-
- rv = ngtcp2_idtr_open(idtr, fr->stream_id);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- assert(rv == NGTCP2_ERR_STREAM_IN_USE);
- /* TODO The stream has been closed. This should be responded
- with RESET_STREAM, or simply ignored. */
- return 0;
- }
-
- strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm));
- if (strm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- /* TODO Perhaps, call new_stream callback? */
- rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, strm);
- return rv;
- }
- if (!bidi) {
- ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_WR);
- }
- }
-
- fr_end_offset = fr->offset + datalen;
-
- if (strm->rx.max_offset < fr_end_offset) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
-
- if (strm->rx.last_offset < fr_end_offset) {
- uint64_t len = fr_end_offset - strm->rx.last_offset;
-
- if (conn_max_data_violated(conn, len)) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
-
- conn->rx.offset += len;
-
- if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING) {
- ngtcp2_conn_extend_max_offset(conn, len);
- }
- }
-
- rx_offset = ngtcp2_strm_rx_offset(strm);
-
- if (fr->fin) {
- if (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) {
- if (strm->rx.last_offset != fr_end_offset) {
- return NGTCP2_ERR_FINAL_SIZE;
- }
-
- if (strm->flags &
- (NGTCP2_STRM_FLAG_STOP_SENDING | NGTCP2_STRM_FLAG_RECV_RST)) {
- return 0;
- }
-
- if (rx_offset == fr_end_offset) {
- return 0;
- }
- } else if (strm->rx.last_offset > fr_end_offset) {
- return NGTCP2_ERR_FINAL_SIZE;
- } else {
- strm->rx.last_offset = fr_end_offset;
-
- ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_RD);
-
- if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING) {
- return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm,
- strm->app_error_code);
- }
- }
- } else {
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- strm->rx.last_offset < fr_end_offset) {
- return NGTCP2_ERR_FINAL_SIZE;
- }
-
- strm->rx.last_offset = ngtcp2_max(strm->rx.last_offset, fr_end_offset);
-
- if (fr_end_offset <= rx_offset) {
- return 0;
- }
-
- if (strm->flags &
- (NGTCP2_STRM_FLAG_STOP_SENDING | NGTCP2_STRM_FLAG_RECV_RST)) {
- return 0;
- }
- }
-
- conn_update_recv_rate(conn, fr_end_offset - fr->offset, ts);
-
- if (fr->offset <= rx_offset) {
- size_t ncut = (size_t)(rx_offset - fr->offset);
- uint64_t offset = rx_offset;
- const uint8_t *data;
- int fin;
-
- if (fr->datacnt) {
- data = fr->data[0].base + ncut;
- datalen -= ncut;
-
- rx_offset += datalen;
- rv = ngtcp2_strm_update_rx_offset(strm, rx_offset);
- if (rv != 0) {
- return rv;
- }
- } else {
- data = NULL;
- datalen = 0;
- }
-
- fin = (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- rx_offset == strm->rx.last_offset;
-
- if (fin || datalen) {
- if (fin) {
- sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN;
- }
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- sdflags |= NGTCP2_STREAM_DATA_FLAG_0RTT;
- }
- rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data,
- datalen);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_emit_pending_stream_data(conn, strm, rx_offset);
- if (rv != 0) {
- return rv;
- }
- }
- } else if (fr->datacnt) {
- rv = ngtcp2_strm_recv_reordering(strm, fr->data[0].base, fr->data[0].len,
- fr->offset);
- if (rv != 0) {
- return rv;
- }
- }
- return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, NGTCP2_NO_ERROR);
-}
-
-/*
- * conn_reset_stream adds RESET_STREAM frame to the transmission
- * queue.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- int rv;
- ngtcp2_frame_chain *frc;
- ngtcp2_pktns *pktns = &conn->pktns;
-
- rv = ngtcp2_frame_chain_new(&frc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- frc->fr.type = NGTCP2_FRAME_RESET_STREAM;
- frc->fr.reset_stream.stream_id = strm->stream_id;
- frc->fr.reset_stream.app_error_code = app_error_code;
- frc->fr.reset_stream.final_size = strm->tx.offset;
-
- /* TODO This prepends RESET_STREAM to pktns->tx.frq. */
- frc->next = pktns->tx.frq;
- pktns->tx.frq = frc;
-
- return 0;
-}
-
-/*
- * conn_stop_sending adds STOP_SENDING frame to the transmission
- * queue.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_stop_sending(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- int rv;
- ngtcp2_frame_chain *frc;
- ngtcp2_pktns *pktns = &conn->pktns;
-
- rv = ngtcp2_frame_chain_new(&frc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- frc->fr.type = NGTCP2_FRAME_STOP_SENDING;
- frc->fr.stop_sending.stream_id = strm->stream_id;
- frc->fr.stop_sending.app_error_code = app_error_code;
-
- /* TODO This prepends STOP_SENDING to pktns->tx.frq. */
- frc->next = pktns->tx.frq;
- pktns->tx.frq = frc;
-
- return 0;
-}
-
-/*
- * handle_max_remote_streams_extension extends
- * |*punsent_max_remote_streams| by |n| if a condition allows it.
- */
-static void
-handle_max_remote_streams_extension(uint64_t *punsent_max_remote_streams,
- size_t n) {
- if (
-#if SIZE_MAX > UINT32_MAX
- NGTCP2_MAX_STREAMS < n ||
-#endif /* SIZE_MAX > UINT32_MAX */
- *punsent_max_remote_streams > (uint64_t)(NGTCP2_MAX_STREAMS - n)) {
- *punsent_max_remote_streams = NGTCP2_MAX_STREAMS;
- } else {
- *punsent_max_remote_streams += n;
- }
-}
-
-/*
- * conn_recv_reset_stream is called when RESET_STREAM |fr| is
- * received.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_STREAM_STATE
- * RESET_STREAM frame is received to the local stream which is not
- * initiated.
- * NGTCP2_ERR_STREAM_LIMIT
- * RESET_STREAM frame has remote stream ID which is strictly
- * greater than the allowed limit.
- * NGTCP2_ERR_PROTO
- * RESET_STREAM frame is received to the local unidirectional
- * stream
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_FLOW_CONTROL
- * Flow control limit is violated; or the final size is beyond the
- * NGTCP2_MAX_VARINT.
- * NGTCP2_ERR_FINAL_SIZE
- * The final offset is strictly larger than it is permitted.
- */
-static int conn_recv_reset_stream(ngtcp2_conn *conn,
- const ngtcp2_reset_stream *fr) {
- ngtcp2_strm *strm;
- int local_stream = conn_local_stream(conn, fr->stream_id);
- int bidi = bidi_stream(fr->stream_id);
- uint64_t datalen;
- ngtcp2_idtr *idtr;
- int rv;
-
- /* TODO share this piece of code */
- if (bidi) {
- if (local_stream) {
- if (conn->local.bidi.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
- } else if (conn->remote.bidi.max_streams <
- ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.bidi.idtr;
- } else {
- if (local_stream) {
- return NGTCP2_ERR_PROTO;
- }
- if (conn->remote.uni.max_streams < ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.uni.idtr;
- }
-
- if (NGTCP2_MAX_VARINT < fr->final_size) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
-
- strm = ngtcp2_conn_find_stream(conn, fr->stream_id);
- if (strm == NULL) {
- if (local_stream) {
- return 0;
- }
-
- if (conn_initial_stream_rx_offset(conn, fr->stream_id) < fr->final_size ||
- conn_max_data_violated(conn, fr->final_size)) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
- rv = ngtcp2_idtr_open(idtr, fr->stream_id);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- assert(rv == NGTCP2_ERR_STREAM_IN_USE);
- return 0;
- }
-
- /* Stream is reset before we create ngtcp2_strm object. */
- conn->rx.offset += fr->final_size;
- ngtcp2_conn_extend_max_offset(conn, fr->final_size);
-
- rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size,
- fr->app_error_code, NULL);
- if (rv != 0) {
- return rv;
- }
-
- /* There will be no activity in this stream because we got
- RESET_STREAM and don't write stream data any further. This
- effectively allows another new stream for peer. */
- if (bidi) {
- handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams,
- 1);
- } else {
- handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams,
- 1);
- }
-
- return 0;
- }
-
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD)) {
- if (strm->rx.last_offset != fr->final_size) {
- return NGTCP2_ERR_FINAL_SIZE;
- }
- } else if (strm->rx.last_offset > fr->final_size) {
- return NGTCP2_ERR_FINAL_SIZE;
- }
-
- datalen = fr->final_size - strm->rx.last_offset;
-
- if (strm->rx.max_offset < fr->final_size ||
- conn_max_data_violated(conn, datalen)) {
- return NGTCP2_ERR_FLOW_CONTROL;
- }
-
- if (!(strm->flags & NGTCP2_STRM_FLAG_RECV_RST)) {
- rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size,
- fr->app_error_code, strm->stream_user_data);
- if (rv != 0) {
- return rv;
- }
-
- /* Extend connection flow control window for the amount of data
- which are not passed to application. */
- if (!(strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING)) {
- ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset -
- ngtcp2_strm_rx_offset(strm));
- }
- }
-
- conn->rx.offset += datalen;
- ngtcp2_conn_extend_max_offset(conn, datalen);
-
- strm->rx.last_offset = fr->final_size;
- strm->flags |= NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_RECV_RST;
-
- return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, fr->app_error_code);
-}
-
-/*
- * conn_recv_stop_sending is called when STOP_SENDING |fr| is received.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_STREAM_STATE
- * STOP_SENDING frame is received for a local stream which is not
- * initiated; or STOP_SENDING frame is received for a local
- * unidirectional stream.
- * NGTCP2_ERR_STREAM_LIMIT
- * STOP_SENDING frame has remote stream ID which is strictly
- * greater than the allowed limit.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_recv_stop_sending(ngtcp2_conn *conn,
- const ngtcp2_stop_sending *fr) {
- int rv;
- ngtcp2_strm *strm;
- ngtcp2_idtr *idtr;
- int local_stream = conn_local_stream(conn, fr->stream_id);
- int bidi = bidi_stream(fr->stream_id);
-
- if (bidi) {
- if (local_stream) {
- if (conn->local.bidi.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
- } else if (conn->remote.bidi.max_streams <
- ngtcp2_ord_stream_id(fr->stream_id)) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
-
- idtr = &conn->remote.bidi.idtr;
- } else {
- if (!local_stream || conn->local.uni.next_stream_id <= fr->stream_id) {
- return NGTCP2_ERR_STREAM_STATE;
- }
-
- idtr = &conn->remote.uni.idtr;
- }
-
- strm = ngtcp2_conn_find_stream(conn, fr->stream_id);
- if (strm == NULL) {
- if (local_stream) {
- return 0;
- }
- rv = ngtcp2_idtr_open(idtr, fr->stream_id);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- assert(rv == NGTCP2_ERR_STREAM_IN_USE);
- return 0;
- }
-
- /* Frame is received reset before we create ngtcp2_strm
- object. */
- strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm));
- if (strm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, strm);
- return rv;
- }
- }
-
- /* No RESET_STREAM is required if we have sent FIN and all data have
- been acknowledged. */
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_WR) &&
- ngtcp2_strm_is_all_tx_data_acked(strm)) {
- return 0;
- }
-
- rv = conn_reset_stream(conn, strm, fr->app_error_code);
- if (rv != 0) {
- return rv;
- }
-
- strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_SENT_RST;
-
- ngtcp2_strm_streamfrq_clear(strm);
-
- return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, fr->app_error_code);
-}
-
-/*
- * check_stateless_reset returns nonzero if Stateless Reset |sr|
- * coming via |path| is valid against |dcid|.
- */
-static int check_stateless_reset(const ngtcp2_dcid *dcid,
- const ngtcp2_path *path,
- const ngtcp2_pkt_stateless_reset *sr) {
- return ngtcp2_path_eq(&dcid->ps.path, path) &&
- ngtcp2_verify_stateless_reset_token(dcid->token,
- sr->stateless_reset_token) == 0;
-}
-
-/*
- * conn_on_stateless_reset decodes Stateless Reset from the buffer
- * pointed by |payload| whose length is |payloadlen|. |payload|
- * should start after first byte of packet.
- *
- * If Stateless Reset is decoded, and the Stateless Reset Token is
- * validated, the connection is closed.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Could not decode Stateless Reset; or Stateless Reset Token does
- * not match; or No stateless reset token is available.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- */
-static int conn_on_stateless_reset(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *payload, size_t payloadlen) {
- int rv = 1;
- ngtcp2_pv *pv = conn->pv;
- ngtcp2_dcid *dcid;
- ngtcp2_pkt_stateless_reset sr;
- size_t len, i;
-
- rv = ngtcp2_pkt_decode_stateless_reset(&sr, payload, payloadlen);
- if (rv != 0) {
- return rv;
- }
-
- if (!check_stateless_reset(&conn->dcid.current, path, &sr) &&
- (!pv || (!check_stateless_reset(&pv->dcid, path, &sr) &&
- (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) ||
- !check_stateless_reset(&pv->fallback_dcid, path, &sr))))) {
- len = ngtcp2_ringbuf_len(&conn->dcid.retired);
- for (i = 0; i < len; ++i) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i);
- if (check_stateless_reset(dcid, path, &sr)) {
- break;
- }
- }
-
- if (i == len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- }
-
- conn->state = NGTCP2_CS_DRAINING;
-
- ngtcp2_log_rx_sr(&conn->log, &sr);
-
- if (!conn->callbacks.recv_stateless_reset) {
- return 0;
- }
-
- rv = conn->callbacks.recv_stateless_reset(conn, &sr, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- return 0;
-}
-
-/*
- * conn_recv_max_streams processes the incoming MAX_STREAMS frame
- * |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- * NGTCP2_ERR_FRAME_ENCODING
- * The maximum streams field exceeds the maximum value.
- */
-static int conn_recv_max_streams(ngtcp2_conn *conn,
- const ngtcp2_max_streams *fr) {
- uint64_t n;
-
- if (fr->max_streams > NGTCP2_MAX_STREAMS) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- n = ngtcp2_min(fr->max_streams, NGTCP2_MAX_STREAMS);
-
- if (fr->type == NGTCP2_FRAME_MAX_STREAMS_BIDI) {
- if (conn->local.bidi.max_streams < n) {
- conn->local.bidi.max_streams = n;
- return conn_call_extend_max_local_streams_bidi(conn, n);
- }
- return 0;
- }
-
- if (conn->local.uni.max_streams < n) {
- conn->local.uni.max_streams = n;
- return conn_call_extend_max_local_streams_uni(conn, n);
- }
- return 0;
-}
-
-static int conn_retire_dcid_prior_to(ngtcp2_conn *conn, ngtcp2_ringbuf *rb,
- uint64_t retire_prior_to) {
- size_t i;
- ngtcp2_dcid *dcid, *last;
- int rv;
-
- for (i = 0; i < ngtcp2_ringbuf_len(rb);) {
- dcid = ngtcp2_ringbuf_get(rb, i);
- if (dcid->seq >= retire_prior_to) {
- ++i;
- continue;
- }
-
- rv = conn_retire_dcid_seq(conn, dcid->seq);
- if (rv != 0) {
- return rv;
- }
- if (i == 0) {
- ngtcp2_ringbuf_pop_front(rb);
- } else if (i == ngtcp2_ringbuf_len(rb) - 1) {
- ngtcp2_ringbuf_pop_back(rb);
- break;
- } else {
- last = ngtcp2_ringbuf_get(rb, ngtcp2_ringbuf_len(rb) - 1);
- ngtcp2_dcid_copy(dcid, last);
- ngtcp2_ringbuf_pop_back(rb);
- }
- }
-
- return 0;
-}
-
-/*
- * conn_recv_new_connection_id processes the incoming
- * NEW_CONNECTION_ID frame |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * |fr| has the duplicated sequence number with different CID or
- * token; or DCID is zero-length.
- */
-static int conn_recv_new_connection_id(ngtcp2_conn *conn,
- const ngtcp2_new_connection_id *fr) {
- size_t i, len;
- ngtcp2_dcid *dcid;
- ngtcp2_pv *pv = conn->pv;
- int rv;
- int found = 0;
- size_t extra_dcid = 0;
-
- if (conn->dcid.current.cid.datalen == 0) {
- return NGTCP2_ERR_PROTO;
- }
-
- if (fr->retire_prior_to > fr->seq) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- rv = ngtcp2_dcid_verify_uniqueness(&conn->dcid.current, fr->seq, &fr->cid,
- fr->stateless_reset_token);
- if (rv != 0) {
- return rv;
- }
- if (ngtcp2_cid_eq(&conn->dcid.current.cid, &fr->cid)) {
- found = 1;
- }
-
- if (pv) {
- rv = ngtcp2_dcid_verify_uniqueness(&pv->dcid, fr->seq, &fr->cid,
- fr->stateless_reset_token);
- if (rv != 0) {
- return rv;
- }
- if (ngtcp2_cid_eq(&pv->dcid.cid, &fr->cid)) {
- found = 1;
- }
- }
-
- len = ngtcp2_ringbuf_len(&conn->dcid.unused);
-
- for (i = 0; i < len; ++i) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, i);
- rv = ngtcp2_dcid_verify_uniqueness(dcid, fr->seq, &fr->cid,
- fr->stateless_reset_token);
- if (rv != 0) {
- return NGTCP2_ERR_PROTO;
- }
- if (ngtcp2_cid_eq(&dcid->cid, &fr->cid)) {
- found = 1;
- }
- }
-
- if (conn->dcid.retire_prior_to < fr->retire_prior_to) {
- conn->dcid.retire_prior_to = fr->retire_prior_to;
-
- rv = conn_retire_dcid_prior_to(conn, &conn->dcid.unused,
- conn->dcid.retire_prior_to);
- if (rv != 0) {
- return rv;
- }
- } else if (fr->seq < conn->dcid.retire_prior_to) {
- /* If packets are reordered, we might have retire_prior_to which
- is larger than fr->seq.
-
- A malicious peer might send crafted NEW_CONNECTION_ID to force
- local endpoint to create lots of RETIRE_CONNECTION_ID frames.
- For example, a peer might send seq = 50000 and retire_prior_to
- = 50000. Then send NEW_CONNECTION_ID frames with seq <
- 50000. */
- if (conn->dcid.num_retire_queued < NGTCP2_MAX_DCID_POOL_SIZE * 2) {
- return conn_retire_dcid_seq(conn, fr->seq);
- }
- return 0;
- }
-
- if (found) {
- return 0;
- }
-
- if (ngtcp2_gaptr_is_pushed(&conn->dcid.seqgap, fr->seq, 1)) {
- return 0;
- }
-
- rv = ngtcp2_gaptr_push(&conn->dcid.seqgap, fr->seq, 1);
- if (rv != 0) {
- return rv;
- }
-
- if (ngtcp2_ksl_len(&conn->dcid.seqgap.gap) > 32) {
- ngtcp2_gaptr_drop_first_gap(&conn->dcid.seqgap);
- }
-
- len = ngtcp2_ringbuf_len(&conn->dcid.unused);
-
- if (conn->dcid.current.seq >= conn->dcid.retire_prior_to) {
- ++extra_dcid;
- }
- if (pv) {
- if (pv->dcid.seq != conn->dcid.current.seq &&
- pv->dcid.seq >= conn->dcid.retire_prior_to) {
- ++extra_dcid;
- }
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->fallback_dcid.seq != conn->dcid.current.seq &&
- pv->fallback_dcid.seq >= conn->dcid.retire_prior_to) {
- ++extra_dcid;
- }
- }
-
- if (conn->local.settings.transport_params.active_connection_id_limit <=
- len + extra_dcid) {
- return NGTCP2_ERR_CONNECTION_ID_LIMIT;
- }
-
- if (len >= NGTCP2_MAX_DCID_POOL_SIZE) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "too many connection ID");
- return 0;
- }
-
- dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused);
- ngtcp2_dcid_init(dcid, fr->seq, &fr->cid, fr->stateless_reset_token);
-
- return 0;
-}
-
-/*
- * conn_post_process_recv_new_connection_id handles retirement request
- * of active DCIDs.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_post_process_recv_new_connection_id(ngtcp2_conn *conn,
- ngtcp2_tstamp ts) {
- ngtcp2_pv *pv = conn->pv;
- ngtcp2_dcid *dcid;
- int rv;
-
- if (conn->dcid.current.seq < conn->dcid.retire_prior_to) {
- if (ngtcp2_ringbuf_len(&conn->dcid.unused) == 0) {
- return 0;
- }
-
- rv = conn_retire_dcid(conn, &conn->dcid.current, ts);
- if (rv != 0) {
- return rv;
- }
-
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
- if (pv) {
- if (conn->dcid.current.seq == pv->dcid.seq) {
- ngtcp2_dcid_copy_no_path(&pv->dcid, dcid);
- }
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- conn->dcid.current.seq == pv->fallback_dcid.seq) {
- ngtcp2_dcid_copy_no_path(&pv->fallback_dcid, dcid);
- }
- }
-
- ngtcp2_dcid_copy_no_path(&conn->dcid.current, dcid);
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
-
- rv = conn_call_activate_dcid(conn, &conn->dcid.current);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (pv) {
- if (pv->dcid.seq < conn->dcid.retire_prior_to) {
- if (ngtcp2_ringbuf_len(&conn->dcid.unused)) {
- rv = conn_retire_dcid(conn, &pv->dcid, ts);
- if (rv != 0) {
- return rv;
- }
-
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
-
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->dcid.seq == pv->fallback_dcid.seq) {
- ngtcp2_dcid_copy_no_path(&pv->fallback_dcid, dcid);
- }
-
- ngtcp2_dcid_copy_no_path(&pv->dcid, dcid);
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
-
- rv = conn_call_activate_dcid(conn, &pv->dcid);
- if (rv != 0) {
- return rv;
- }
- } else {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV,
- "path migration is aborted because connection ID is"
- "retired and no unused connection ID is available");
-
- return conn_stop_pv(conn, ts);
- }
- }
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->fallback_dcid.seq < conn->dcid.retire_prior_to) {
- if (ngtcp2_ringbuf_len(&conn->dcid.unused)) {
- rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts);
- if (rv != 0) {
- return rv;
- }
-
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
- ngtcp2_dcid_copy_no_path(&pv->fallback_dcid, dcid);
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
-
- rv = conn_call_activate_dcid(conn, &pv->fallback_dcid);
- if (rv != 0) {
- return rv;
- }
- } else {
- /* Now we have no fallback dcid. */
- return conn_stop_pv(conn, ts);
- }
- }
- }
-
- return 0;
-}
-
-/*
- * conn_recv_retire_connection_id processes the incoming
- * RETIRE_CONNECTION_ID frame |fr|. |hd| is a packet header which
- * |fr| is included.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_PROTO
- * SCID is zero-length.
- * NGTCP2_ERR_FRAME_ENCODING
- * Attempt to retire CID which is used as DCID to send this frame.
- */
-static int conn_recv_retire_connection_id(ngtcp2_conn *conn,
- const ngtcp2_pkt_hd *hd,
- const ngtcp2_retire_connection_id *fr,
- ngtcp2_tstamp ts) {
- ngtcp2_ksl_it it;
- ngtcp2_scid *scid;
-
- if (conn->oscid.datalen == 0 || conn->scid.last_seq < fr->seq) {
- return NGTCP2_ERR_PROTO;
- }
-
- for (it = ngtcp2_ksl_begin(&conn->scid.set); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- scid = ngtcp2_ksl_it_get(&it);
- if (scid->seq == fr->seq) {
- if (ngtcp2_cid_eq(&scid->cid, &hd->dcid)) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- if (!(scid->flags & NGTCP2_SCID_FLAG_RETIRED)) {
- scid->flags |= NGTCP2_SCID_FLAG_RETIRED;
- ++conn->scid.num_retired;
- }
-
- if (scid->pe.index != NGTCP2_PQ_BAD_INDEX) {
- ngtcp2_pq_remove(&conn->scid.used, &scid->pe);
- scid->pe.index = NGTCP2_PQ_BAD_INDEX;
- }
-
- scid->ts_retired = ts;
-
- return ngtcp2_pq_push(&conn->scid.used, &scid->pe);
- }
- }
-
- return 0;
-}
-
-/*
- * conn_recv_new_token processes the incoming NEW_TOKEN frame |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Token is empty
- * NGTCP2_ERR_PROTO:
- * Server received NEW_TOKEN.
- */
-static int conn_recv_new_token(ngtcp2_conn *conn, const ngtcp2_new_token *fr) {
- int rv;
-
- if (conn->server) {
- return NGTCP2_ERR_PROTO;
- }
-
- if (fr->token.len == 0) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- if (conn->callbacks.recv_new_token) {
- rv = conn->callbacks.recv_new_token(conn, &fr->token, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_select_preferred_addr asks a client application to select a
- * server address from preferred addresses received from server. If a
- * client chooses the address, path validation will start.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_select_preferred_addr(ngtcp2_conn *conn) {
- struct sockaddr_storage buf;
- ngtcp2_addr addr;
- int rv;
- ngtcp2_duration timeout;
- ngtcp2_pv *pv;
- ngtcp2_dcid *dcid;
-
- ngtcp2_addr_init(&addr, (struct sockaddr *)&buf, 0, NULL);
-
- if (ngtcp2_ringbuf_len(&conn->dcid.unused) == 0) {
- return 0;
- }
-
- rv = conn_call_select_preferred_addr(conn, &addr);
- if (rv != 0) {
- return rv;
- }
-
- if (addr.addrlen == 0 ||
- ngtcp2_addr_eq(&conn->dcid.current.ps.path.remote, &addr)) {
- return 0;
- }
-
- assert(conn->pv == NULL);
-
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
- timeout = 3 * conn_compute_pto(conn, &conn->pktns);
- timeout = ngtcp2_max(timeout, 6 * conn->cstat.initial_rtt);
-
- rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_NONE, &conn->log,
- conn->mem);
- if (rv != 0) {
- /* TODO Call ngtcp2_dcid_free here if it is introduced */
- return rv;
- }
-
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
- conn->pv = pv;
-
- ngtcp2_addr_copy(&pv->dcid.ps.path.local, &conn->dcid.current.ps.path.local);
- ngtcp2_addr_copy(&pv->dcid.ps.path.remote, &addr);
-
- return conn_call_activate_dcid(conn, &pv->dcid);
-}
-
-/*
- * conn_recv_handshake_done processes the incoming HANDSHAKE_DONE
- * frame |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * Server received HANDSHAKE_DONE frame.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- int rv;
-
- if (conn->server) {
- return NGTCP2_ERR_PROTO;
- }
-
- if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) {
- return 0;
- }
-
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED |
- NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
-
- conn->pktns.rtb.persistent_congestion_start_ts = ts;
-
- conn_discard_handshake_state(conn, ts);
-
- if (conn->remote.transport_params.preferred_address_present) {
- rv = conn_select_preferred_addr(conn);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (conn->callbacks.handshake_confirmed) {
- rv = conn->callbacks.handshake_confirmed(conn, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
-
- /* Re-arm loss detection timer after handshake has been
- confirmed. */
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
-
- return 0;
-}
-
-/*
- * conn_key_phase_changed returns nonzero if |hd| indicates that the
- * key phase has unexpected value.
- */
-static int conn_key_phase_changed(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd) {
- ngtcp2_pktns *pktns = &conn->pktns;
-
- return !(pktns->crypto.rx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE) ^
- !(hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE);
-}
-
-/*
- * conn_prepare_key_update installs new updated keys.
- */
-static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts;
- ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_crypto_km *rx_ckm = pktns->crypto.rx.ckm;
- ngtcp2_crypto_km *tx_ckm = pktns->crypto.tx.ckm;
- ngtcp2_crypto_km *new_rx_ckm, *new_tx_ckm;
- ngtcp2_crypto_aead_ctx rx_aead_ctx = {0}, tx_aead_ctx = {0};
- size_t secretlen, ivlen;
-
- if ((conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) &&
- (tx_ckm->use_count >= pktns->crypto.ctx.max_encryption ||
- rx_ckm->use_count >= pktns->crypto.ctx.max_decryption_failure)) {
- ngtcp2_conn_initiate_key_update(conn, ts);
- }
-
- if ((conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) ||
- (confirmed_ts != UINT64_MAX && confirmed_ts + pto > ts)) {
- return 0;
- }
-
- if (conn->crypto.key_update.new_rx_ckm ||
- conn->crypto.key_update.new_tx_ckm) {
- assert(conn->crypto.key_update.new_rx_ckm);
- assert(conn->crypto.key_update.new_tx_ckm);
- return 0;
- }
-
- secretlen = rx_ckm->secret.len;
- ivlen = rx_ckm->iv.len;
-
- rv = ngtcp2_crypto_km_nocopy_new(&conn->crypto.key_update.new_rx_ckm,
- secretlen, ivlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_crypto_km_nocopy_new(&conn->crypto.key_update.new_tx_ckm,
- secretlen, ivlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- new_rx_ckm = conn->crypto.key_update.new_rx_ckm;
- new_tx_ckm = conn->crypto.key_update.new_tx_ckm;
-
- assert(conn->callbacks.update_key);
-
- rv = conn->callbacks.update_key(
- conn, new_rx_ckm->secret.base, new_tx_ckm->secret.base, &rx_aead_ctx,
- new_rx_ckm->iv.base, &tx_aead_ctx, new_tx_ckm->iv.base,
- rx_ckm->secret.base, tx_ckm->secret.base, secretlen, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- new_rx_ckm->aead_ctx = rx_aead_ctx;
- new_tx_ckm->aead_ctx = tx_aead_ctx;
-
- if (!(rx_ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE)) {
- new_rx_ckm->flags |= NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE;
- new_tx_ckm->flags |= NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE;
- }
-
- if (conn->crypto.key_update.old_rx_ckm) {
- conn_call_delete_crypto_aead_ctx(
- conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx);
- ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem);
- conn->crypto.key_update.old_rx_ckm = NULL;
- }
-
- return 0;
-}
-
-/*
- * conn_rotate_keys rotates keys. The current key moves to old key,
- * and new key moves to the current key.
- */
-static void conn_rotate_keys(ngtcp2_conn *conn, int64_t pkt_num) {
- ngtcp2_pktns *pktns = &conn->pktns;
-
- assert(conn->crypto.key_update.new_rx_ckm);
- assert(conn->crypto.key_update.new_tx_ckm);
- assert(!conn->crypto.key_update.old_rx_ckm);
- assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING));
-
- conn->crypto.key_update.old_rx_ckm = pktns->crypto.rx.ckm;
-
- pktns->crypto.rx.ckm = conn->crypto.key_update.new_rx_ckm;
- conn->crypto.key_update.new_rx_ckm = NULL;
- pktns->crypto.rx.ckm->pkt_num = pkt_num;
-
- assert(pktns->crypto.tx.ckm);
-
- conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx);
- ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem);
-
- pktns->crypto.tx.ckm = conn->crypto.key_update.new_tx_ckm;
- conn->crypto.key_update.new_tx_ckm = NULL;
- pktns->crypto.tx.ckm->pkt_num = pktns->tx.last_pkt_num + 1;
-
- conn->flags |= NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED;
-}
-
-/*
- * conn_path_validation_in_progress returns nonzero if path validation
- * against |path| is underway.
- */
-static int conn_path_validation_in_progress(ngtcp2_conn *conn,
- const ngtcp2_path *path) {
- ngtcp2_pv *pv = conn->pv;
-
- return pv && ngtcp2_path_eq(&pv->dcid.ps.path, path);
-}
-
-/*
- * conn_recv_non_probing_pkt_on_new_path is called when non-probing
- * packet is received via new path. It starts path validation against
- * the new path.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_CONN_ID_BLOCKED
- * No DCID is available
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn,
- const ngtcp2_path *path,
- int new_cid_used,
- ngtcp2_tstamp ts) {
-
- ngtcp2_dcid dcid;
- ngtcp2_pv *pv;
- int rv;
- ngtcp2_duration timeout;
- int require_new_cid;
-
- assert(conn->server);
-
- if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- ngtcp2_path_eq(&conn->pv->fallback_dcid.ps.path, path)) {
- /* If new path equals fallback path, that means connection
- migrated back to the original path. Fallback path is
- considered to be validated. */
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV,
- "path is migrated back to the original path");
- ngtcp2_dcid_copy(&conn->dcid.current, &conn->pv->fallback_dcid);
- conn_reset_congestion_state(conn);
- rv = conn_stop_pv(conn, ts);
- if (rv != 0) {
- return rv;
- }
- return 0;
- }
-
- /* The transport specification draft-27 says:
- *
- * An endpoint MUST use a new connection ID if it initiates
- * connection migration as described in Section 9.2 or probes a new
- * network path as described in Section 9.1. An endpoint MUST use a
- * new connection ID in response to a change in the address of a
- * peer if the packet with the new peer address uses an active
- * connection ID that has not been previously used by the peer.
- */
- require_new_cid =
- (new_cid_used &&
- !ngtcp2_addr_eq(&conn->dcid.current.ps.path.remote, &path->remote)) ||
- !ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local);
-
- /* If the remote endpoint uses new DCID, server has to change its
- DCID as well. */
- if (require_new_cid && ngtcp2_ringbuf_len(&conn->dcid.unused) == 0) {
- return NGTCP2_ERR_CONN_ID_BLOCKED;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "non-probing packet was received from new remote address");
-
- timeout = 3 * conn_compute_pto(conn, &conn->pktns);
- timeout = ngtcp2_max(timeout, 6 * conn->cstat.initial_rtt);
-
- if (require_new_cid) {
- dcid = *(ngtcp2_dcid *)ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
-
- rv = conn_call_activate_dcid(conn, &dcid);
- if (rv != 0) {
- return rv;
- }
- } else {
- /* Use the current DCID if a remote endpoint does not change
- DCID. */
- dcid = conn->dcid.current;
- }
-
- ngtcp2_path_copy(&dcid.ps.path, path);
-
- rv = ngtcp2_pv_new(&pv, &dcid, timeout, NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE,
- &conn->log, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE)) {
- ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->pv->fallback_dcid);
- } else {
- ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->dcid.current);
- }
-
- ngtcp2_dcid_copy(&conn->dcid.current, &dcid);
-
- conn_reset_congestion_state(conn);
-
- if (conn->pv) {
- ngtcp2_log_info(
- &conn->log, NGTCP2_LOG_EVENT_PTV,
- "path migration is aborted because new migration has started");
- rv = conn_stop_pv(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- conn->pv = pv;
-
- return 0;
-}
-
-/*
- * conn_recv_delayed_handshake_pkt processes the received Handshake
- * packet which is received after handshake completed. This function
- * does the minimal job, and its purpose is send acknowledgement of
- * this packet to the peer. We assume that hd->type ==
- * NGTCP2_PKT_HANDSHAKE.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Frame is badly formatted; or frame type is unknown.
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_DISCARD_PKT
- * Packet was discarded.
- * NGTCP2_ERR_ACK_FRAME
- * ACK frame is malformed.
- * NGTCP2_ERR_PROTO
- * Frame that is not allowed in Handshake packet is received.
- */
-static int
-conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
- size_t pktlen, const uint8_t *payload,
- size_t payloadlen, ngtcp2_tstamp pkt_ts,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nread;
- ngtcp2_max_frame mfr;
- ngtcp2_frame *fr = &mfr.fr;
- int rv;
- int require_ack = 0;
- ngtcp2_pktns *pktns;
-
- assert(hd->type == NGTCP2_PKT_HANDSHAKE);
-
- pktns = conn->hs_pktns;
-
- if (payloadlen == 0) {
- /* QUIC packet must contain at least one frame */
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- ngtcp2_qlog_pkt_received_start(&conn->qlog, hd);
-
- for (; payloadlen;) {
- nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen);
- if (nread < 0) {
- return (int)nread;
- }
-
- payload += nread;
- payloadlen -= (size_t)nread;
-
- if (fr->type == NGTCP2_FRAME_ACK) {
- fr->ack.ack_delay = 0;
- fr->ack.ack_delay_unscaled = 0;
- }
-
- ngtcp2_log_rx_fr(&conn->log, hd, fr);
-
- switch (fr->type) {
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- if (!conn->server) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
- rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGTCP2_FRAME_PADDING:
- break;
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- conn_recv_connection_close(conn, &fr->connection_close);
- break;
- case NGTCP2_FRAME_CRYPTO:
- case NGTCP2_FRAME_PING:
- require_ack = 1;
- break;
- default:
- return NGTCP2_ERR_PROTO;
- }
-
- ngtcp2_qlog_write_frame(&conn->qlog, fr);
- }
-
- ngtcp2_qlog_pkt_received_end(&conn->qlog, hd, pktlen);
-
- rv = pktns_commit_recv_pkt_num(pktns, hd->pkt_num, pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- if (require_ack && ++pktns->acktr.rx_npkt >= NGTCP2_NUM_IMMEDIATE_ACK_PKT) {
- ngtcp2_acktr_immediate_ack(&pktns->acktr);
- }
-
- rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd->pkt_num, require_ack,
- pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- conn_restart_timer_on_read(conn, ts);
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- return 0;
-}
-
-/*
- * conn_recv_pkt processes a packet contained in the buffer pointed by
- * |pkt| of length |pktlen|. |pkt| may contain multiple QUIC packets.
- * This function only processes the first packet. |pkt_ts| is the
- * timestamp when packet is received. |ts| should be the current
- * time. Usually they are the same, but for buffered packets,
- * |pkt_ts| would be earlier than |ts|.
- *
- * This function returns the number of bytes processed if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_DISCARD_PKT
- * Packet was discarded because plain text header was malformed;
- * or its payload could not be decrypted.
- * NGTCP2_ERR_PROTO
- * Packet is badly formatted; or 0RTT packet contains other than
- * PADDING or STREAM frames; or other QUIC protocol violation is
- * found.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_FRAME_ENCODING
- * Frame is badly formatted; or frame type is unknown.
- * NGTCP2_ERR_ACK_FRAME
- * ACK frame is malformed.
- * NGTCP2_ERR_STREAM_STATE
- * Frame is received to the local stream which is not initiated.
- * NGTCP2_ERR_STREAM_LIMIT
- * Frame has remote stream ID which is strictly greater than the
- * allowed limit.
- * NGTCP2_ERR_FLOW_CONTROL
- * Flow control limit is violated.
- * NGTCP2_ERR_FINAL_SIZE
- * Frame has strictly larger end offset than it is permitted.
- */
-static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) {
- ngtcp2_pkt_hd hd;
- int rv = 0;
- size_t hdpktlen;
- const uint8_t *payload;
- size_t payloadlen;
- ngtcp2_ssize nread, nwrite;
- ngtcp2_max_frame mfr;
- ngtcp2_frame *fr = &mfr.fr;
- int require_ack = 0;
- ngtcp2_crypto_aead *aead;
- ngtcp2_crypto_cipher *hp;
- ngtcp2_crypto_km *ckm;
- ngtcp2_crypto_cipher_ctx *hp_ctx;
- uint8_t plain_hdpkt[1500];
- ngtcp2_hp_mask hp_mask;
- ngtcp2_decrypt decrypt;
- size_t aead_overhead;
- ngtcp2_pktns *pktns;
- int non_probing_pkt = 0;
- int key_phase_bit_changed = 0;
- int force_decrypt_failure = 0;
- int recv_ncid = 0;
- int new_cid_used = 0;
-
- if (pkt[0] & NGTCP2_HEADER_FORM_BIT) {
- nread = ngtcp2_pkt_decode_hd_long(&hd, pkt, pktlen);
- if (nread < 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decode long header");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (pktlen < (size_t)nread + hd.len || conn->version != hd.version) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- pktlen = (size_t)nread + hd.len;
-
- /* Quoted from spec: if subsequent packets of those types include
- a different Source Connection ID, they MUST be discarded. */
- if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) {
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched SCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- switch (hd.type) {
- case NGTCP2_PKT_INITIAL:
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "delayed Initial packet was discarded");
- return (ngtcp2_ssize)pktlen;
- case NGTCP2_PKT_HANDSHAKE:
- if (!conn->hs_pktns) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "delayed Handshake packet was discarded");
- return (ngtcp2_ssize)pktlen;
- }
-
- pktns = conn->hs_pktns;
- ckm = pktns->crypto.rx.ckm;
- hp_ctx = &pktns->crypto.rx.hp_ctx;
- hp_mask = conn->callbacks.hp_mask;
- decrypt = conn->callbacks.decrypt;
- aead_overhead = conn->crypto.aead_overhead;
- break;
- case NGTCP2_PKT_0RTT:
- if (!conn->server || !conn->early.ckm) {
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- pktns = &conn->pktns;
- ckm = conn->early.ckm;
- hp_ctx = &conn->early.hp_ctx;
- hp_mask = conn->callbacks.hp_mask;
- decrypt = conn->callbacks.decrypt;
- aead_overhead = conn->crypto.aead_overhead;
- break;
- default:
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet type 0x%02x was ignored", hd.type);
- return (ngtcp2_ssize)pktlen;
- }
- } else {
- nread = ngtcp2_pkt_decode_hd_short(&hd, pkt, pktlen, conn->oscid.datalen);
- if (nread < 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decode short header");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- pktns = &conn->pktns;
- ckm = pktns->crypto.rx.ckm;
- hp_ctx = &pktns->crypto.rx.hp_ctx;
- hp_mask = conn->callbacks.hp_mask;
- decrypt = conn->callbacks.decrypt;
- aead_overhead = conn->crypto.aead_overhead;
- }
-
- aead = &pktns->crypto.ctx.aead;
- hp = &pktns->crypto.ctx.hp;
-
- nwrite = decrypt_hp(&hd, plain_hdpkt, sizeof(plain_hdpkt), hp, pkt, pktlen,
- (size_t)nread, ckm, hp_ctx, hp_mask);
- if (nwrite < 0) {
- if (ngtcp2_err_is_fatal((int)nwrite)) {
- return nwrite;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decrypt packet number");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- hdpktlen = (size_t)nwrite;
- payload = pkt + hdpktlen;
- payloadlen = pktlen - hdpktlen;
-
- hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num,
- pkt_num_bits(hd.pkt_numlen));
- if (hd.pkt_num > NGTCP2_MAX_PKT_NUM) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "pkn=%" PRId64 " is greater than maximum pkn", hd.pkt_num);
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- ngtcp2_log_rx_pkt_hd(&conn->log, &hd);
-
- if (hd.type == NGTCP2_PKT_SHORT) {
- key_phase_bit_changed = conn_key_phase_changed(conn, &hd);
- }
-
- rv = conn_ensure_decrypt_buffer(conn, payloadlen);
- if (rv != 0) {
- return rv;
- }
-
- if (key_phase_bit_changed) {
- assert(hd.type == NGTCP2_PKT_SHORT);
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "unexpected KEY_PHASE");
-
- if (ckm->pkt_num > hd.pkt_num) {
- if (conn->crypto.key_update.old_rx_ckm) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "decrypting with old key");
- ckm = conn->crypto.key_update.old_rx_ckm;
- } else {
- force_decrypt_failure = 1;
- }
- } else if (pktns->rx.max_pkt_num < hd.pkt_num) {
- assert(ckm->pkt_num < hd.pkt_num);
- if (!conn->crypto.key_update.new_rx_ckm) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "new key is not available");
- force_decrypt_failure = 1;
- } else {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "decrypting with new key");
- ckm = conn->crypto.key_update.new_rx_ckm;
- }
- } else {
- force_decrypt_failure = 1;
- }
- }
-
- nwrite = decrypt_pkt(conn->crypto.decrypt_buf.base, aead, payload, payloadlen,
- plain_hdpkt, hdpktlen, hd.pkt_num, ckm, decrypt,
- aead_overhead);
-
- if (force_decrypt_failure) {
- nwrite = NGTCP2_ERR_TLS_DECRYPT;
- }
-
- if (nwrite < 0) {
- if (ngtcp2_err_is_fatal((int)nwrite)) {
- return nwrite;
- }
-
- assert(NGTCP2_ERR_TLS_DECRYPT == nwrite);
-
- ++ckm->use_count;
-
- if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decrypt packet payload");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "could not decrypt packet payload");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- rv = ngtcp2_pkt_verify_reserved_bits(plain_hdpkt[0]);
- if (rv != 0) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet has incorrect reserved bits");
-
- return NGTCP2_ERR_PROTO;
- }
-
- if (pktns_pkt_num_is_duplicate(pktns, hd.pkt_num)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was discarded because of duplicated packet number");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- payload = conn->crypto.decrypt_buf.base;
- payloadlen = (size_t)nwrite;
-
- if (payloadlen == 0) {
- /* QUIC packet must contain at least one frame */
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- switch (hd.type) {
- case NGTCP2_PKT_HANDSHAKE:
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- rv = conn_recv_delayed_handshake_pkt(conn, &hd, pktlen, payload,
- payloadlen, pkt_ts, ts);
- if (rv < 0) {
- return (ngtcp2_ssize)rv;
- }
-
- return (ngtcp2_ssize)pktlen;
- case NGTCP2_PKT_0RTT:
- if (!ngtcp2_cid_eq(&conn->rcid, &hd.dcid)) {
- rv = conn_verify_dcid(conn, NULL, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
- }
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- } else {
- rv = conn_verify_dcid(conn, &new_cid_used, &hd);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "packet was ignored because of mismatched DCID");
- return NGTCP2_ERR_DISCARD_PKT;
- }
-
- conn->flags |= NGTCP2_CONN_FLAG_RECV_PROTECTED_PKT;
- }
-
- ngtcp2_qlog_pkt_received_start(&conn->qlog, &hd);
-
- for (; payloadlen;) {
- nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen);
- if (nread < 0) {
- return nread;
- }
-
- payload += nread;
- payloadlen -= (size_t)nread;
-
- if (fr->type == NGTCP2_FRAME_ACK) {
- if ((hd.flags & NGTCP2_PKT_FLAG_LONG_FORM) &&
- hd.type == NGTCP2_PKT_0RTT) {
- return NGTCP2_ERR_PROTO;
- }
- assign_recved_ack_delay_unscaled(
- &fr->ack, conn->remote.transport_params.ack_delay_exponent);
- }
-
- ngtcp2_log_rx_fr(&conn->log, &hd, fr);
-
- if (hd.type == NGTCP2_PKT_0RTT) {
- switch (fr->type) {
- case NGTCP2_FRAME_PADDING:
- case NGTCP2_FRAME_PING:
- case NGTCP2_FRAME_RESET_STREAM:
- case NGTCP2_FRAME_STOP_SENDING:
- case NGTCP2_FRAME_STREAM:
- case NGTCP2_FRAME_MAX_DATA:
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- case NGTCP2_FRAME_DATA_BLOCKED:
- case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- case NGTCP2_FRAME_PATH_CHALLENGE:
- case NGTCP2_FRAME_PATH_RESPONSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- break;
- default:
- return NGTCP2_ERR_PROTO;
- }
- }
-
- switch (fr->type) {
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- case NGTCP2_FRAME_PADDING:
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- break;
- default:
- require_ack = 1;
- }
-
- switch (fr->type) {
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- if (!conn->server) {
- conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED;
- }
- rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_STREAM:
- rv = conn_recv_stream(conn, &fr->stream, ts);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_CRYPTO:
- rv = conn_recv_crypto(conn, NGTCP2_CRYPTO_LEVEL_APP, &pktns->crypto.strm,
- &fr->crypto);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_RESET_STREAM:
- rv = conn_recv_reset_stream(conn, &fr->reset_stream);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_STOP_SENDING:
- rv = conn_recv_stop_sending(conn, &fr->stop_sending);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- rv = conn_recv_max_stream_data(conn, &fr->max_stream_data);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_MAX_DATA:
- conn_recv_max_data(conn, &fr->max_data);
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- rv = conn_recv_max_streams(conn, &fr->max_streams);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- conn_recv_connection_close(conn, &fr->connection_close);
- break;
- case NGTCP2_FRAME_PING:
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_PATH_CHALLENGE:
- conn_recv_path_challenge(conn, &fr->path_challenge);
- break;
- case NGTCP2_FRAME_PATH_RESPONSE:
- rv = conn_recv_path_response(conn, &fr->path_response, ts);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- rv = conn_recv_new_connection_id(conn, &fr->new_connection_id);
- if (rv != 0) {
- return rv;
- }
- recv_ncid = 1;
- break;
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- rv = conn_recv_retire_connection_id(conn, &hd, &fr->retire_connection_id,
- ts);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_NEW_TOKEN:
- rv = conn_recv_new_token(conn, &fr->new_token);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_HANDSHAKE_DONE:
- rv = conn_recv_handshake_done(conn, ts);
- if (rv != 0) {
- return rv;
- }
- non_probing_pkt = 1;
- break;
- case NGTCP2_FRAME_DATA_BLOCKED:
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- /* TODO Not implemented yet */
- non_probing_pkt = 1;
- break;
- }
-
- ngtcp2_qlog_write_frame(&conn->qlog, fr);
- }
-
- ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen);
-
- if (recv_ncid) {
- rv = conn_post_process_recv_new_connection_id(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (conn->server && hd.type == NGTCP2_PKT_SHORT && non_probing_pkt &&
- pktns->rx.max_pkt_num < hd.pkt_num &&
- !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) &&
- !conn_path_validation_in_progress(conn, path)) {
- rv = conn_recv_non_probing_pkt_on_new_path(conn, path, new_cid_used, ts);
- if (rv != 0) {
- if (ngtcp2_err_is_fatal(rv)) {
- return rv;
- }
-
- /* DCID is not available. Just continue. */
- assert(NGTCP2_ERR_CONN_ID_BLOCKED == rv);
- }
- }
-
- if (hd.type == NGTCP2_PKT_SHORT) {
- if (ckm == conn->crypto.key_update.new_rx_ckm) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "rotate keys");
- conn_rotate_keys(conn, hd.pkt_num);
- } else if (ckm->pkt_num > hd.pkt_num) {
- ckm->pkt_num = hd.pkt_num;
- }
- }
-
- rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- if (require_ack && ++pktns->acktr.rx_npkt >= NGTCP2_NUM_IMMEDIATE_ACK_PKT) {
- ngtcp2_acktr_immediate_ack(&pktns->acktr);
- }
-
- rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack,
- pkt_ts);
- if (rv != 0) {
- return rv;
- }
-
- conn_restart_timer_on_read(conn, ts);
-
- ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat);
-
- return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING
- : (ngtcp2_ssize)pktlen;
-}
-
-/*
- * conn_process_buffered_protected_pkt processes buffered 0RTT or
- * Short packets.
- *
- * This function returns 0 if it succeeds, or the same negative error
- * codes from conn_recv_pkt.
- */
-static int conn_process_buffered_protected_pkt(ngtcp2_conn *conn,
- ngtcp2_pktns *pktns,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nread;
- ngtcp2_pkt_chain **ppc, *next;
- int rv;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "processing buffered protected packet");
-
- for (ppc = &pktns->rx.buffed_pkts; *ppc;) {
- next = (*ppc)->next;
- nread = conn_recv_pkt(conn, &(*ppc)->path.path, (*ppc)->pkt, (*ppc)->pktlen,
- (*ppc)->ts, ts);
- if (nread < 0 && !ngtcp2_err_is_fatal((int)nread) &&
- nread != NGTCP2_ERR_DRAINING) {
- /* TODO We don't know this is the first QUIC packet in a
- datagram. */
- rv = conn_on_stateless_reset(conn, &(*ppc)->path.path, (*ppc)->pkt,
- (*ppc)->pktlen);
- if (rv == 0) {
- ngtcp2_pkt_chain_del(*ppc, conn->mem);
- *ppc = next;
- return NGTCP2_ERR_DRAINING;
- }
- }
-
- ngtcp2_pkt_chain_del(*ppc, conn->mem);
- *ppc = next;
- if (nread < 0) {
- if (nread == NGTCP2_ERR_DISCARD_PKT) {
- continue;
- }
- return (int)nread;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_process_buffered_handshake_pkt processes buffered Handshake
- * packets.
- *
- * This function returns 0 if it succeeds, or the same negative error
- * codes from conn_recv_handshake_pkt.
- */
-static int conn_process_buffered_handshake_pkt(ngtcp2_conn *conn,
- ngtcp2_tstamp ts) {
- ngtcp2_pktns *pktns = conn->hs_pktns;
- ngtcp2_ssize nread;
- ngtcp2_pkt_chain **ppc, *next;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "processing buffered handshake packet");
-
- for (ppc = &pktns->rx.buffed_pkts; *ppc;) {
- next = (*ppc)->next;
- nread = conn_recv_handshake_pkt(conn, &(*ppc)->path.path, (*ppc)->pkt,
- (*ppc)->pktlen, (*ppc)->ts, ts);
- ngtcp2_pkt_chain_del(*ppc, conn->mem);
- *ppc = next;
- if (nread < 0) {
- if (nread == NGTCP2_ERR_DISCARD_PKT) {
- continue;
- }
- return (int)nread;
- }
- }
-
- return 0;
-}
-
-static void conn_sync_stream_id_limit(ngtcp2_conn *conn) {
- ngtcp2_transport_params *params = &conn->remote.transport_params;
-
- conn->local.bidi.max_streams = params->initial_max_streams_bidi;
- conn->local.uni.max_streams = params->initial_max_streams_uni;
-}
-
-/*
- * conn_handshake_completed is called once cryptographic handshake has
- * completed.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed.
- */
-static int conn_handshake_completed(ngtcp2_conn *conn) {
- int rv;
-
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED;
-
- rv = conn_call_handshake_completed(conn);
- if (rv != 0) {
- return rv;
- }
-
- if (conn->local.bidi.max_streams > 0) {
- rv = conn_call_extend_max_local_streams_bidi(conn,
- conn->local.bidi.max_streams);
- if (rv != 0) {
- return rv;
- }
- }
- if (conn->local.uni.max_streams > 0) {
- rv = conn_call_extend_max_local_streams_uni(conn,
- conn->local.uni.max_streams);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_recv_cpkt processes compound packet after handshake. The
- * buffer pointed by |pkt| might contain multiple packets. The Short
- * packet must be the last one because it does not have payload length
- * field.
- *
- * This function returns 0 if it succeeds, or the same negative error
- * codes from conn_recv_pkt except for NGTCP2_ERR_DISCARD_PKT.
- */
-static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts) {
- ngtcp2_ssize nread;
- int rv;
- const uint8_t *origpkt = pkt;
- size_t origpktlen = pktlen;
-
- conn->cstat.bytes_recv += pktlen;
-
- while (pktlen) {
- nread = conn_recv_pkt(conn, path, pkt, pktlen, ts, ts);
- if (nread < 0) {
- if (ngtcp2_err_is_fatal((int)nread)) {
- return (int)nread;
- }
-
- if (nread == NGTCP2_ERR_DRAINING) {
- return NGTCP2_ERR_DRAINING;
- }
-
- if (origpkt == pkt) {
- rv = conn_on_stateless_reset(conn, path, origpkt, origpktlen);
- if (rv == 0) {
- return NGTCP2_ERR_DRAINING;
- }
- }
- if (nread == NGTCP2_ERR_DISCARD_PKT) {
- return 0;
- }
- return (int)nread;
- }
-
- assert(pktlen >= (size_t)nread);
- pkt += nread;
- pktlen -= (size_t)nread;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT,
- "read packet %td left %zu", nread, pktlen);
- }
-
- return 0;
-}
-
-/*
- * conn_is_retired_path returns nonzero if |path| is included in
- * retired path list.
- */
-static int conn_is_retired_path(ngtcp2_conn *conn, const ngtcp2_path *path) {
- size_t i, len = ngtcp2_ringbuf_len(&conn->dcid.retired);
- ngtcp2_dcid *dcid;
-
- for (i = 0; i < len; ++i) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i);
- if (ngtcp2_path_eq(&dcid->ps.path, path)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- * conn_enqueue_handshake_done enqueues HANDSHAKE_DONE frame for
- * transmission.
- */
-static int conn_enqueue_handshake_done(ngtcp2_conn *conn) {
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_frame_chain *nfrc;
- int rv;
-
- assert(conn->server);
-
- rv = ngtcp2_frame_chain_new(&nfrc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr.type = NGTCP2_FRAME_HANDSHAKE_DONE;
- nfrc->next = pktns->tx.frq;
- pktns->tx.frq = nfrc;
-
- return 0;
-}
-
-/**
- * @function
- *
- * `conn_read_handshake` performs QUIC cryptographic handshake by
- * reading given data. |pkt| points to the buffer to read and
- * |pktlen| is the length of the buffer. |path| is the network path.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes: (TBD).
- */
-static int conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_tstamp ts) {
- int rv;
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- /* TODO Better to log something when we ignore input */
- return 0;
- case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- rv = conn_recv_handshake_cpkt(conn, path, pkt, pktlen, ts);
- if (rv < 0) {
- return rv;
- }
-
- if (conn->state == NGTCP2_CS_CLIENT_INITIAL) {
- /* Retry packet was received */
- return 0;
- }
-
- assert(conn->hs_pktns);
-
- if (conn->hs_pktns->crypto.rx.ckm && conn->in_pktns) {
- rv = conn_process_buffered_handshake_pkt(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
- case NGTCP2_CS_SERVER_INITIAL:
- rv = conn_recv_handshake_cpkt(conn, path, pkt, pktlen, ts);
- if (rv < 0) {
- return rv;
- }
-
- /*
- * Client ServerHello might not fit into single Initial packet
- * (e.g., resuming session with client authentication). If we get
- * Client Initial which does not increase offset or it is 0RTT
- * packet buffered, perform address validation in order to buffer
- * validated data only.
- */
- if (ngtcp2_strm_rx_offset(&conn->in_pktns->crypto.strm) == 0) {
- if (conn->in_pktns->crypto.strm.rx.rob &&
- ngtcp2_rob_data_buffered(conn->in_pktns->crypto.strm.rx.rob)) {
- /* Address has been validated with token */
- if (conn->local.settings.token.len) {
- return 0;
- }
- return NGTCP2_ERR_RETRY;
- }
- if (conn->in_pktns->rx.buffed_pkts) {
- /* 0RTT is buffered, force retry */
- return NGTCP2_ERR_RETRY;
- }
- /* If neither CRYPTO frame nor 0RTT packet is processed, just
- drop connection. */
- return NGTCP2_ERR_PROTO;
- }
-
- /* Process re-ordered 0-RTT packets which arrived before Initial
- packet. */
- if (conn->early.ckm) {
- assert(conn->in_pktns);
-
- rv = conn_process_buffered_protected_pkt(conn, conn->in_pktns, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
- case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
- rv = conn_recv_handshake_cpkt(conn, path, pkt, pktlen, ts);
- if (rv < 0) {
- return rv;
- }
-
- if (conn->hs_pktns->crypto.rx.ckm) {
- rv = conn_process_buffered_handshake_pkt(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (conn->hs_pktns->rx.max_pkt_num != -1) {
- conn_discard_initial_state(conn, ts);
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- /* If server hits amplification limit, it cancels loss detection
- timer. If server receives a packet from client, the limit is
- increased and server can send more. If server has
- ack-eliciting Initial or Handshake packets, it should resend
- it if timer fired but timer is not armed in this case. So
- instead of resending Initial/Handshake packets, if server has
- 1RTT data to send, it might send them and then might hit
- amplification limit again until it hits stream data limit.
- Initial/Handshake data is not resent. In order to avoid this
- situation, try to arm loss detection and check the expiry
- here so that on next write call, we can resend
- Initial/Handshake first. */
- if (!conn->cstat.loss_detection_timer) {
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
- if (ngtcp2_conn_loss_detection_expiry(conn) <= ts) {
- rv = ngtcp2_conn_on_loss_detection_timer(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
- }
-
- return 0;
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED)) {
- return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
- }
-
- rv = conn_handshake_completed(conn);
- if (rv != 0) {
- return rv;
- }
- conn->state = NGTCP2_CS_POST_HANDSHAKE;
-
- rv = conn_call_activate_dcid(conn, &conn->dcid.current);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_process_buffered_protected_pkt(conn, &conn->pktns, ts);
- if (rv != 0) {
- return rv;
- }
-
- conn_discard_handshake_state(conn, ts);
-
- rv = conn_enqueue_handshake_done(conn);
- if (rv != 0) {
- return rv;
- }
-
- conn->pktns.rtb.persistent_congestion_start_ts = ts;
-
- /* Re-arm loss detection timer here after handshake has been
- confirmed. */
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
-
- return 0;
- case NGTCP2_CS_CLOSING:
- return NGTCP2_ERR_CLOSING;
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_DRAINING;
- default:
- return 0;
- }
-}
-
-int ngtcp2_conn_read_pkt(ngtcp2_conn *conn, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts) {
- int rv = 0;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu",
- pktlen);
-
- if (pktlen == 0) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- /* client does not expect a packet from unknown path. */
- if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) &&
- (!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)) &&
- !conn_is_retired_path(conn, path)) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "ignore packet from unknown path");
- return 0;
- }
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
- case NGTCP2_CS_SERVER_INITIAL:
- case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
- case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
- return conn_read_handshake(conn, path, pkt, pktlen, ts);
- case NGTCP2_CS_CLOSING:
- return NGTCP2_ERR_CLOSING;
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_DRAINING;
- case NGTCP2_CS_POST_HANDSHAKE:
- rv = conn_prepare_key_update(conn, ts);
- if (rv != 0) {
- return rv;
- }
- return conn_recv_cpkt(conn, path, pkt, pktlen, ts);
- default:
- assert(0);
- }
-}
-
-/*
- * conn_check_pkt_num_exhausted returns nonzero if packet number is
- * exhausted in at least one of packet number space.
- */
-static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
-
- return (in_pktns && in_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
- (hs_pktns && hs_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM) ||
- conn->pktns.tx.last_pkt_num == NGTCP2_MAX_PKT_NUM;
-}
-
-/*
- * conn_server_hs_tx_left returns the maximum number of bytes that
- * server is allowed to send during handshake.
- */
-static size_t conn_server_hs_tx_left(ngtcp2_conn *conn) {
- if (conn->flags & NGTCP2_CONN_FLAG_SADDR_VERIFIED) {
- return SIZE_MAX;
- }
- /* From QUIC spec: Prior to validating the client address, servers
- MUST NOT send more than three times as many bytes as the number
- of bytes they have received. */
- assert(conn->cstat.bytes_recv * 3 >= conn->cstat.bytes_sent);
-
- return conn->cstat.bytes_recv * 3 - conn->cstat.bytes_sent;
-}
-
-/*
- * conn_retransmit_retry_early retransmits 0RTT packet after Retry is
- * received from server.
- */
-static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn,
- uint8_t *dest, size_t destlen,
- ngtcp2_tstamp ts) {
- return conn_write_pkt(conn, dest, destlen, NULL, NGTCP2_PKT_0RTT,
- NGTCP2_WRITE_PKT_FLAG_NONE, ts);
-}
-
-/*
- * conn_handshake_probe_left returns nonzero if there are probe
- * packets to be sent for Initial or Handshake packet number space
- * left.
- */
-static int conn_handshake_probe_left(ngtcp2_conn *conn) {
- return (conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) ||
- conn->hs_pktns->rtb.probe_pkt_left;
-}
-
-/*
- * conn_write_handshake writes QUIC handshake packets to the buffer
- * pointed by |dest| of length |destlen|. |early_datalen| specifies
- * the expected length of early data to send. Specify 0 to
- * |early_datalen| if there is no early data.
- *
- * This function returns the number of bytes written to the buffer, or
- * one of the following negative error codes:
- *
- * NGTCP2_ERR_PKT_NUM_EXHAUSTED
- * Packet number is exhausted.
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM
- * Required transport parameter is missing.
- * NGTCP2_CS_CLOSING
- * Connection is in closing state.
- * NGTCP2_CS_DRAINING
- * Connection is in draining state.
- *
- * In addition to the above negative error codes, the same error codes
- * from conn_recv_pkt may also be returned.
- */
-static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, size_t early_datalen,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_ssize res = 0, nwrite = 0, early_spktlen = 0;
- size_t origlen = destlen;
- size_t server_hs_tx_left;
- ngtcp2_conn_stat *cstat = &conn->cstat;
- size_t pending_early_datalen;
- ngtcp2_dcid *dcid;
- ngtcp2_preferred_addr *paddr;
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- pending_early_datalen = conn_retry_early_payloadlen(conn);
- if (pending_early_datalen) {
- early_datalen = pending_early_datalen;
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY)) {
- nwrite =
- conn_write_client_initial(conn, dest, destlen, early_datalen, ts);
- if (nwrite <= 0) {
- return nwrite;
- }
- } else {
- nwrite = conn_write_handshake_pkt(conn, dest, destlen, NGTCP2_PKT_INITIAL,
- early_datalen, ts);
- if (nwrite < 0) {
- return nwrite;
- }
- }
-
- if (pending_early_datalen) {
- early_spktlen = conn_retransmit_retry_early(conn, dest + nwrite,
- destlen - (size_t)nwrite, ts);
-
- if (early_spktlen < 0) {
- assert(ngtcp2_err_is_fatal((int)early_spktlen));
- return early_spktlen;
- }
- }
-
- conn->state = NGTCP2_CS_CLIENT_WAIT_HANDSHAKE;
-
- res = nwrite + early_spktlen;
- cstat->bytes_sent += (size_t)res;
-
- return res;
- case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- if (!conn_handshake_probe_left(conn) && conn_cwnd_is_zero(conn)) {
- destlen = 0;
- } else {
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) {
- pending_early_datalen = conn_retry_early_payloadlen(conn);
- if (pending_early_datalen) {
- early_datalen = pending_early_datalen;
- }
- }
-
- nwrite =
- conn_write_handshake_pkts(conn, dest, destlen, early_datalen, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- nwrite = conn_retransmit_retry_early(conn, dest, destlen, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
-
- if (res == 0) {
- nwrite = conn_write_handshake_ack_pkts(conn, dest, origlen, ts);
- if (nwrite < 0) {
- return nwrite;
- }
- res = nwrite;
- }
-
- cstat->bytes_sent += (size_t)res;
-
- return res;
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED)) {
- return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
- }
-
- rv = conn_handshake_completed(conn);
- if (rv != 0) {
- return (ngtcp2_ssize)rv;
- }
-
- conn->state = NGTCP2_CS_POST_HANDSHAKE;
-
- if (conn->remote.transport_params.preferred_address_present) {
- assert(!ngtcp2_ringbuf_full(&conn->dcid.unused));
-
- paddr = &conn->remote.transport_params.preferred_address;
- dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused);
- ngtcp2_dcid_init(dcid, 1, &paddr->cid, paddr->stateless_reset_token);
-
- rv = ngtcp2_gaptr_push(&conn->dcid.seqgap, 1, 1);
- if (rv != 0) {
- return (ngtcp2_ssize)rv;
- }
- }
-
- if (conn->remote.transport_params.stateless_reset_token_present) {
- assert(conn->dcid.current.seq == 0);
- memcpy(conn->dcid.current.token,
- conn->remote.transport_params.stateless_reset_token,
- sizeof(conn->dcid.current.token));
- }
-
- rv = conn_call_activate_dcid(conn, &conn->dcid.current);
- if (rv != 0) {
- return rv;
- }
-
- conn_process_early_rtb(conn);
-
- rv = conn_process_buffered_protected_pkt(conn, &conn->pktns, ts);
- if (rv != 0) {
- return (ngtcp2_ssize)rv;
- }
-
- cstat->bytes_sent += (size_t)res;
-
- return res;
- case NGTCP2_CS_SERVER_INITIAL:
- nwrite = conn_write_handshake_pkts(conn, dest, destlen,
- /* early_datalen = */ 0, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- if (nwrite) {
- conn->state = NGTCP2_CS_SERVER_WAIT_HANDSHAKE;
- cstat->bytes_sent += (size_t)nwrite;
- }
-
- return nwrite;
- case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- server_hs_tx_left = conn_server_hs_tx_left(conn);
- if (server_hs_tx_left == 0) {
- if (cstat->loss_detection_timer) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "loss detection timer canceled");
- cstat->loss_detection_timer = 0;
- cstat->pto_count = 0;
- }
- return 0;
- }
-
- if (conn_handshake_probe_left(conn) || !conn_cwnd_is_zero(conn)) {
- nwrite = conn_write_handshake_pkts(conn, dest, destlen,
- /* early_datalen = */ 0, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
-
- if (res == 0) {
- nwrite = conn_write_handshake_ack_pkts(conn, dest, origlen, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
- dest += nwrite;
- origlen -= (size_t)nwrite;
- }
-
- cstat->bytes_sent += (size_t)res;
- return res;
- }
-
- return 0;
- case NGTCP2_CS_CLOSING:
- return NGTCP2_ERR_CLOSING;
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_DRAINING;
- default:
- return 0;
- }
-}
-
-/**
- * @function
- *
- * `conn_client_write_handshake` writes client side handshake data and
- * 0RTT packet.
- *
- * In order to send STREAM data in 0RTT packet, specify
- * |vmsg|->stream. |vmsg|->stream.strm, |vmsg|->stream.fin,
- * |vmsg|->stream.data, and |vmsg|->stream.datacnt are stream to which
- * 0-RTT data is sent, whether it is a last data chunk in this stream,
- * a vector of 0-RTT data, and its number of elements respectively.
- * The amount of 0RTT data sent is assigned to
- * *|vmsg|->stream.pdatalen. If no data is sent, -1 is assigned.
- * Note that 0 length STREAM frame is allowed in QUIC, so 0 might be
- * assigned to *|vmsg|->stream.pdatalen.
- *
- * This function returns 0 if it cannot write any frame because buffer
- * is too small, or packet is congestion limited. Application should
- * keep reading and wait for congestion window to grow.
- *
- * This function returns the number of bytes written to the buffer
- * pointed by |dest| if it succeeds, or one of the following negative
- * error codes: (TBD).
- */
-static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn,
- uint8_t *dest, size_t destlen,
- ngtcp2_vmsg *vmsg,
- ngtcp2_tstamp ts) {
- int send_stream = 0;
- ngtcp2_ssize spktlen, early_spktlen;
- int was_client_initial;
- size_t datalen;
- size_t early_datalen = 0;
- uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE;
- int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) != 0;
-
- assert(!conn->server);
-
- /* conn->early.ckm might be created in the first call of
- conn_handshake(). Check it later. */
- if (vmsg && vmsg->type == NGTCP2_VMSG_TYPE_STREAM &&
- !(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) {
- datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt);
- send_stream =
- conn_retry_early_payloadlen(conn) == 0 &&
- /* 0 length STREAM frame is allowed */
- (datalen == 0 ||
- (datalen > 0 &&
- (vmsg->stream.strm->tx.max_offset - vmsg->stream.strm->tx.offset) &&
- (conn->tx.max_offset - conn->tx.offset)));
- if (send_stream) {
- early_datalen =
- conn_enforce_flow_control(conn, vmsg->stream.strm, datalen) +
- NGTCP2_STREAM_OVERHEAD;
-
- if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) {
- wflags |= NGTCP2_WRITE_PKT_FLAG_MORE;
- }
- } else {
- vmsg = NULL;
- }
- }
-
- if (!ppe_pending) {
- was_client_initial = conn->state == NGTCP2_CS_CLIENT_INITIAL;
- spktlen = conn_write_handshake(conn, dest, destlen, early_datalen, ts);
-
- if (spktlen < 0) {
- return spktlen;
- }
-
- if (conn->pktns.crypto.tx.ckm || !conn->early.ckm || !send_stream) {
- return spktlen;
- }
- } else {
- assert(!conn->pktns.crypto.tx.ckm);
- assert(conn->early.ckm);
-
- was_client_initial = conn->pkt.was_client_initial;
- spktlen = conn->pkt.hs_spktlen;
- }
-
- /* If spktlen > 0, we are making a compound packet. If Initial
- packet is written, we have to pad bytes to 0-RTT packet. */
-
- if (spktlen && was_client_initial) {
- wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING;
- }
-
- dest += spktlen;
- destlen -= (size_t)spktlen;
-
- if (conn_cwnd_is_zero(conn)) {
- return spktlen;
- }
-
- early_spktlen =
- conn_write_pkt(conn, dest, destlen, vmsg, NGTCP2_PKT_0RTT, wflags, ts);
-
- if (early_spktlen < 0) {
- switch (early_spktlen) {
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
- return spktlen;
- case NGTCP2_ERR_WRITE_MORE:
- conn->pkt.was_client_initial = was_client_initial;
- conn->pkt.hs_spktlen = spktlen;
- break;
- }
- return early_spktlen;
- }
-
- conn->cstat.bytes_sent += (size_t)early_spktlen;
-
- return spktlen + early_spktlen;
-}
-
-void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn) {
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED;
- if (conn->server) {
- conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED;
- }
-}
-
-int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn) {
- return (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) &&
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED);
-}
-
-int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr,
- int64_t pkt_num, int active_ack, ngtcp2_tstamp ts) {
- int rv;
- (void)conn;
-
- rv = ngtcp2_acktr_add(acktr, pkt_num, active_ack, ts);
- if (rv != 0) {
- assert(rv != NGTCP2_ERR_INVALID_ARGUMENT);
- return rv;
- }
-
- return 0;
-}
-
-int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) {
- ngtcp2_ssize nread;
- ngtcp2_pkt_hd hd, *p;
-
- if (dest) {
- p = dest;
- } else {
- p = &hd;
- }
-
- if (pktlen == 0 || (pkt[0] & NGTCP2_HEADER_FORM_BIT) == 0) {
- return -1;
- }
-
- nread = ngtcp2_pkt_decode_hd_long(p, pkt, pktlen);
- if (nread < 0) {
- return -1;
- }
-
- switch (p->type) {
- case NGTCP2_PKT_INITIAL:
- if (pktlen < NGTCP2_MIN_INITIAL_PKTLEN) {
- return -1;
- }
- if (p->token.len == 0 && p->dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN) {
- return -1;
- }
- break;
- case NGTCP2_PKT_0RTT:
- /* 0-RTT packet may arrive before Initial packet due to
- re-ordering. */
- break;
- default:
- return -1;
- }
-
- switch (p->version) {
- case NGTCP2_PROTO_VER:
- break;
- default:
- return 1;
- }
-
- return 0;
-}
-
-void ngtcp2_conn_set_aead_overhead(ngtcp2_conn *conn, size_t aead_overhead) {
- conn->crypto.aead_overhead = aead_overhead;
-}
-
-size_t ngtcp2_conn_get_aead_overhead(ngtcp2_conn *conn) {
- return conn->crypto.aead_overhead;
-}
-
-int ngtcp2_conn_install_initial_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx,
- const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx,
- const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv,
- const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) {
- ngtcp2_pktns *pktns = conn->in_pktns;
- int rv;
-
- assert(pktns);
-
- conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.rx.hp_ctx);
- pktns->crypto.rx.hp_ctx.native_handle = NULL;
-
- if (pktns->crypto.rx.ckm) {
- conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.rx.ckm->aead_ctx);
- ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem);
- pktns->crypto.rx.ckm = NULL;
- }
-
- conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.tx.hp_ctx);
- pktns->crypto.tx.hp_ctx.native_handle = NULL;
-
- if (pktns->crypto.tx.ckm) {
- conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx);
- ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem);
- pktns->crypto.tx.ckm = NULL;
- }
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL, 0, NULL, rx_iv, ivlen,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, NULL, tx_iv, ivlen,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- /* Take owner ship after we are sure that no failure occurs, so that
- caller can delete these contexts on failure. */
- pktns->crypto.rx.ckm->aead_ctx = *rx_aead_ctx;
- pktns->crypto.rx.hp_ctx = *rx_hp_ctx;
- pktns->crypto.tx.ckm->aead_ctx = *tx_aead_ctx;
- pktns->crypto.tx.hp_ctx = *tx_hp_ctx;
-
- return 0;
-}
-
-int ngtcp2_conn_install_rx_handshake_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- ngtcp2_pktns *pktns = conn->hs_pktns;
- int rv;
-
- assert(pktns);
- assert(!pktns->crypto.rx.hp_ctx.native_handle);
- assert(!pktns->crypto.rx.ckm);
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL, 0, aead_ctx, iv, ivlen,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- pktns->crypto.rx.hp_ctx = *hp_ctx;
-
- return 0;
-}
-
-int ngtcp2_conn_install_tx_handshake_key(
- ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- ngtcp2_pktns *pktns = conn->hs_pktns;
- int rv;
-
- assert(pktns);
- assert(!pktns->crypto.tx.hp_ctx.native_handle);
- assert(!pktns->crypto.tx.ckm);
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL, 0, aead_ctx, iv, ivlen,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- pktns->crypto.tx.hp_ctx = *hp_ctx;
-
- if (conn->server) {
- return ngtcp2_conn_commit_local_transport_params(conn);
- }
-
- return 0;
-}
-
-int ngtcp2_conn_install_early_key(ngtcp2_conn *conn,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen,
- const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- int rv;
-
- assert(!conn->early.hp_ctx.native_handle);
- assert(!conn->early.ckm);
-
- rv = ngtcp2_crypto_km_new(&conn->early.ckm, NULL, 0, aead_ctx, iv, ivlen,
- conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- conn->early.hp_ctx = *hp_ctx;
-
- return 0;
-}
-
-int ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret,
- size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen,
- const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- ngtcp2_pktns *pktns = &conn->pktns;
- int rv;
-
- assert(!pktns->crypto.rx.hp_ctx.native_handle);
- assert(!pktns->crypto.rx.ckm);
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, secret, secretlen, aead_ctx,
- iv, ivlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- pktns->crypto.rx.hp_ctx = *hp_ctx;
-
- return 0;
-}
-
-int ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret,
- size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen,
- const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- ngtcp2_pktns *pktns = &conn->pktns;
- int rv;
-
- assert(!pktns->crypto.tx.hp_ctx.native_handle);
- assert(!pktns->crypto.tx.ckm);
-
- rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, secret, secretlen, aead_ctx,
- iv, ivlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- pktns->crypto.tx.hp_ctx = *hp_ctx;
-
- conn->remote.transport_params = conn->remote.pending_transport_params;
- conn_sync_stream_id_limit(conn);
- conn->tx.max_offset = conn->remote.transport_params.initial_max_data;
-
- return 0;
-}
-
-int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts;
- ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
-
- assert(conn->state == NGTCP2_CS_POST_HANDSHAKE);
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) ||
- (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) ||
- !conn->crypto.key_update.new_tx_ckm ||
- !conn->crypto.key_update.new_rx_ckm ||
- (confirmed_ts != UINT64_MAX && confirmed_ts + 3 * pto > ts)) {
- return NGTCP2_ERR_INVALID_STATE;
- }
-
- conn_rotate_keys(conn, NGTCP2_MAX_PKT_NUM);
-
- return 0;
-}
-
-ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) {
- if (conn->cstat.loss_detection_timer) {
- return conn->cstat.loss_detection_timer;
- }
- return UINT64_MAX;
-}
-
-ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) {
- ngtcp2_tstamp res = UINT64_MAX;
- ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns);
- ngtcp2_scid *scid;
- ngtcp2_dcid *dcid;
-
- if (conn->pv) {
- res = ngtcp2_pv_next_expiry(conn->pv);
- }
-
- if (!ngtcp2_pq_empty(&conn->scid.used)) {
- scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe);
- if (scid->ts_retired != UINT64_MAX) {
- res = ngtcp2_min(res, scid->ts_retired + pto);
- }
- }
-
- if (ngtcp2_ringbuf_len(&conn->dcid.retired)) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, 0);
- res = ngtcp2_min(res, dcid->ts_retired + pto);
- }
-
- return res;
-}
-
-ngtcp2_tstamp ngtcp2_conn_ack_delay_expiry(ngtcp2_conn *conn) {
- ngtcp2_acktr *acktr = &conn->pktns.acktr;
-
- if (!(acktr->flags & NGTCP2_ACKTR_FLAG_CANCEL_TIMER) &&
- acktr->first_unacked_ts != UINT64_MAX) {
- return acktr->first_unacked_ts + conn_compute_ack_delay(conn);
- }
- return UINT64_MAX;
-}
-
-ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) {
- ngtcp2_tstamp t1 = ngtcp2_conn_loss_detection_expiry(conn);
- ngtcp2_tstamp t2 = ngtcp2_conn_ack_delay_expiry(conn);
- ngtcp2_tstamp t3 = ngtcp2_conn_internal_expiry(conn);
- ngtcp2_tstamp t4 = ngtcp2_conn_lost_pkt_expiry(conn);
- ngtcp2_tstamp res = ngtcp2_min(t1, t2);
- res = ngtcp2_min(res, t3);
- return ngtcp2_min(res, t4);
-}
-
-int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- int rv;
-
- ngtcp2_conn_cancel_expired_ack_delay_timer(conn, ts);
-
- ngtcp2_conn_remove_lost_pkt(conn, ts);
-
- if (ngtcp2_conn_loss_detection_expiry(conn) <= ts) {
- rv = ngtcp2_conn_on_loss_detection_timer(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-static void acktr_cancel_expired_ack_delay_timer(ngtcp2_acktr *acktr,
- ngtcp2_tstamp ts) {
- if (!(acktr->flags & NGTCP2_ACKTR_FLAG_CANCEL_TIMER) &&
- acktr->first_unacked_ts <= ts) {
- acktr->flags |= NGTCP2_ACKTR_FLAG_CANCEL_TIMER;
- }
-}
-
-void ngtcp2_conn_cancel_expired_ack_delay_timer(ngtcp2_conn *conn,
- ngtcp2_tstamp ts) {
- if (conn->in_pktns) {
- acktr_cancel_expired_ack_delay_timer(&conn->in_pktns->acktr, ts);
- }
- if (conn->hs_pktns) {
- acktr_cancel_expired_ack_delay_timer(&conn->hs_pktns->acktr, ts);
- }
- acktr_cancel_expired_ack_delay_timer(&conn->pktns.acktr, ts);
-}
-
-ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn) {
- ngtcp2_tstamp res = UINT64_MAX, ts;
-
- if (conn->in_pktns) {
- ts = ngtcp2_rtb_lost_pkt_ts(&conn->in_pktns->rtb);
- if (ts != UINT64_MAX) {
- ts += conn_compute_pto(conn, conn->in_pktns);
- res = ngtcp2_min(res, ts);
- }
- }
-
- if (conn->hs_pktns) {
- ts = ngtcp2_rtb_lost_pkt_ts(&conn->hs_pktns->rtb);
- if (ts != UINT64_MAX) {
- ts += conn_compute_pto(conn, conn->hs_pktns);
- res = ngtcp2_min(res, ts);
- }
- }
-
- ts = ngtcp2_rtb_lost_pkt_ts(&conn->pktns.rtb);
- if (ts != UINT64_MAX) {
- ts += conn_compute_pto(conn, &conn->pktns);
- res = ngtcp2_min(res, ts);
- }
-
- return res;
-}
-
-void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_tstamp pto;
-
- if (conn->in_pktns) {
- pto = conn_compute_pto(conn, conn->in_pktns);
- ngtcp2_rtb_remove_expired_lost_pkt(&conn->in_pktns->rtb, pto, ts);
- }
- if (conn->hs_pktns) {
- pto = conn_compute_pto(conn, conn->hs_pktns);
- ngtcp2_rtb_remove_expired_lost_pkt(&conn->hs_pktns->rtb, pto, ts);
- }
- pto = conn_compute_pto(conn, &conn->pktns);
- ngtcp2_rtb_remove_expired_lost_pkt(&conn->pktns.rtb, pto, ts);
-}
-
-/*
- * conn_client_validate_transport_params validates |params| as client.
- * |params| must be sent with Encrypted Extensions.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * Validation against either of original_dcid and retry_scid is
- * failed.
- * NGTCP2_ERR_TRANSPORT_PARAM
- * params contains preferred address but server chose zero-length
- * connection ID.
- */
-static int
-conn_client_validate_transport_params(ngtcp2_conn *conn,
- const ngtcp2_transport_params *params) {
- if (!ngtcp2_cid_eq(&conn->rcid, &params->original_dcid)) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
-
- if (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) {
- if (!params->retry_scid_present) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
- if (!ngtcp2_cid_eq(&conn->retry_scid, &params->retry_scid)) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
- } else if (params->retry_scid_present) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
-
- if (params->preferred_address_present &&
- conn->dcid.current.cid.datalen == 0) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
-
- return 0;
-}
-
-int ngtcp2_conn_set_remote_transport_params(
- ngtcp2_conn *conn, const ngtcp2_transport_params *params) {
- int rv;
-
- assert(!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED));
-
- /* Assume that ngtcp2_decode_transport_params sets default value if
- active_connection_id_limit is omitted. */
- if (params->active_connection_id_limit <
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
-
- /* We assume that conn->dcid.current.cid is still the initial one.
- This requires that transport parameter must be fed into
- ngtcp2_conn as early as possible. */
- if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &params->initial_scid)) {
- return NGTCP2_ERR_TRANSPORT_PARAM;
- }
-
- if (!conn->server) {
- rv = conn_client_validate_transport_params(conn, params);
- if (rv != 0) {
- return rv;
- }
- }
-
- ngtcp2_log_remote_tp(&conn->log,
- conn->server
- ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO
- : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
- params);
-
- ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server,
- NGTCP2_QLOG_SIDE_REMOTE);
-
- if (conn->pktns.crypto.tx.ckm) {
- conn->remote.transport_params = *params;
- conn_sync_stream_id_limit(conn);
- conn->tx.max_offset = conn->remote.transport_params.initial_max_data;
- } else {
- conn->remote.pending_transport_params = *params;
- }
-
- conn->flags |= NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED;
-
- return 0;
-}
-
-void ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn,
- ngtcp2_transport_params *params) {
- if (conn->pktns.crypto.rx.ckm) {
- *params = conn->remote.transport_params;
- } else {
- *params = conn->remote.pending_transport_params;
- }
-}
-
-void ngtcp2_conn_set_early_remote_transport_params(
- ngtcp2_conn *conn, const ngtcp2_transport_params *params) {
- ngtcp2_transport_params *p = &conn->remote.transport_params;
-
- assert(!conn->server);
-
- memset(p, 0, sizeof(*p));
-
- p->initial_max_streams_bidi = params->initial_max_streams_bidi;
- p->initial_max_streams_uni = params->initial_max_streams_uni;
- p->initial_max_stream_data_bidi_local =
- params->initial_max_stream_data_bidi_local;
- p->initial_max_stream_data_bidi_remote =
- params->initial_max_stream_data_bidi_remote;
- p->initial_max_stream_data_uni = params->initial_max_stream_data_uni;
- p->initial_max_data = params->initial_max_data;
-
- conn_sync_stream_id_limit(conn);
-
- conn->tx.max_offset = p->initial_max_data;
-
- ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, p, conn->server,
- NGTCP2_QLOG_SIDE_REMOTE);
-}
-
-int ngtcp2_conn_set_local_transport_params(
- ngtcp2_conn *conn, const ngtcp2_transport_params *params) {
- assert(conn->server);
- assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE);
-
- if (conn->hs_pktns == NULL || conn->hs_pktns->crypto.tx.ckm) {
- return NGTCP2_ERR_INVALID_STATE;
- }
-
- conn->local.settings.transport_params = *params;
-
- return 0;
-}
-
-int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn) {
- const ngtcp2_mem *mem = conn->mem;
- ngtcp2_transport_params *params = &conn->local.settings.transport_params;
- ngtcp2_scid *scident;
- ngtcp2_ksl_it it;
- int rv;
-
- assert(1 == ngtcp2_ksl_len(&conn->scid.set));
-
- if (params->active_connection_id_limit == 0) {
- params->active_connection_id_limit =
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
- }
-
- params->initial_scid = conn->oscid;
-
- if (conn->oscid.datalen == 0) {
- params->preferred_address_present = 0;
- }
-
- if (conn->server) {
- if (params->stateless_reset_token_present) {
- it = ngtcp2_ksl_begin(&conn->scid.set);
- scident = ngtcp2_ksl_it_get(&it);
-
- memcpy(scident->token, params->stateless_reset_token,
- NGTCP2_STATELESS_RESET_TOKENLEN);
- }
-
- if (params->preferred_address_present) {
- scident = ngtcp2_mem_malloc(mem, sizeof(*scident));
- if (scident == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_scid_init(scident, 1, &params->preferred_address.cid,
- params->preferred_address.stateless_reset_token);
-
- rv = ngtcp2_ksl_insert(&conn->scid.set, NULL, &scident->cid, scident);
- if (rv != 0) {
- ngtcp2_mem_free(mem, scident);
- return rv;
- }
-
- conn->scid.last_seq = 1;
- }
- }
-
- conn->rx.unsent_max_offset = conn->rx.max_offset = params->initial_max_data;
- conn->remote.bidi.unsent_max_streams = params->initial_max_streams_bidi;
- conn->remote.bidi.max_streams = params->initial_max_streams_bidi;
- conn->remote.uni.unsent_max_streams = params->initial_max_streams_uni;
- conn->remote.uni.max_streams = params->initial_max_streams_uni;
-
- ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server,
- NGTCP2_QLOG_SIDE_LOCAL);
-
- return 0;
-}
-
-void ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn,
- ngtcp2_transport_params *params) {
- *params = conn->local.settings.transport_params;
-}
-
-int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id,
- void *stream_user_data) {
- int rv;
- ngtcp2_strm *strm;
-
- if (ngtcp2_conn_get_streams_bidi_left(conn) == 0) {
- return NGTCP2_ERR_STREAM_ID_BLOCKED;
- }
-
- strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm));
- if (strm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_conn_init_stream(conn, strm, conn->local.bidi.next_stream_id,
- stream_user_data);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, strm);
- return rv;
- }
-
- *pstream_id = conn->local.bidi.next_stream_id;
- conn->local.bidi.next_stream_id += 4;
-
- return 0;
-}
-
-int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, int64_t *pstream_id,
- void *stream_user_data) {
- int rv;
- ngtcp2_strm *strm;
-
- if (ngtcp2_conn_get_streams_uni_left(conn) == 0) {
- return NGTCP2_ERR_STREAM_ID_BLOCKED;
- }
-
- strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm));
- if (strm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_conn_init_stream(conn, strm, conn->local.uni.next_stream_id,
- stream_user_data);
- if (rv != 0) {
- ngtcp2_mem_free(conn->mem, strm);
- return rv;
- }
- ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_RD);
-
- *pstream_id = conn->local.uni.next_stream_id;
- conn->local.uni.next_stream_id += 4;
-
- return 0;
-}
-
-ngtcp2_strm *ngtcp2_conn_find_stream(ngtcp2_conn *conn, int64_t stream_id) {
- ngtcp2_map_entry *me;
-
- me = ngtcp2_map_find(&conn->strms, (uint64_t)stream_id);
- if (me == NULL) {
- return NULL;
- }
-
- return ngtcp2_struct_of(me, ngtcp2_strm, me);
-}
-
-ngtcp2_ssize ngtcp2_conn_write_stream(ngtcp2_conn *conn, ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags,
- int64_t stream_id, const uint8_t *data,
- size_t datalen, ngtcp2_tstamp ts) {
- ngtcp2_vec datav;
-
- datav.len = datalen;
- datav.base = (uint8_t *)data;
-
- return ngtcp2_conn_writev_stream(conn, path, dest, destlen, pdatalen, flags,
- stream_id, &datav, 1, ts);
-}
-
-ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_ssize *pdatalen, uint32_t flags,
- int64_t stream_id,
- const ngtcp2_vec *datav, size_t datavcnt,
- ngtcp2_tstamp ts) {
- ngtcp2_vmsg vmsg, *pvmsg;
- ngtcp2_strm *strm;
-
- if (pdatalen) {
- *pdatalen = -1;
- }
-
- if (stream_id != -1) {
- strm = ngtcp2_conn_find_stream(conn, stream_id);
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- if (strm->flags & NGTCP2_STRM_FLAG_SHUT_WR) {
- return NGTCP2_ERR_STREAM_SHUT_WR;
- }
-
- vmsg.type = NGTCP2_VMSG_TYPE_STREAM;
- vmsg.stream.strm = strm;
- vmsg.stream.flags = flags;
- vmsg.stream.data = datav;
- vmsg.stream.datacnt = datavcnt;
- vmsg.stream.pdatalen = pdatalen;
-
- pvmsg = &vmsg;
- } else {
- pvmsg = NULL;
- }
-
- return ngtcp2_conn_write_vmsg(conn, path, dest, destlen, pvmsg, ts);
-}
-
-ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_vmsg *vmsg, ngtcp2_tstamp ts) {
- ngtcp2_ssize nwrite;
- ngtcp2_pktns *pktns = &conn->pktns;
- size_t origlen = destlen;
- int rv;
- uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE;
- int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) != 0;
- ngtcp2_ssize res = 0;
- size_t server_hs_tx_left;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- if (path) {
- ngtcp2_path_copy(path, &conn->dcid.current.ps.path);
- }
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE:
- case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED:
- nwrite = conn_client_write_handshake(conn, dest, destlen, vmsg, ts);
- if (nwrite < 0 || conn->state != NGTCP2_CS_POST_HANDSHAKE) {
- return nwrite;
- }
- res = nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- /* Break here so that we can coalesces Short packets. */
- break;
- case NGTCP2_CS_SERVER_INITIAL:
- case NGTCP2_CS_SERVER_WAIT_HANDSHAKE:
- case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED:
- if (!ppe_pending) {
- server_hs_tx_left = conn_server_hs_tx_left(conn);
- destlen = ngtcp2_min(destlen, server_hs_tx_left);
-
- nwrite = conn_write_handshake(conn, dest, destlen, 0, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- if (conn->flags & NGTCP2_CONN_FLAG_SADDR_VERIFIED) {
- destlen = origlen;
- } else {
- origlen = destlen;
- }
-
- res = nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
- if (conn->state != NGTCP2_CS_POST_HANDSHAKE &&
- conn->pktns.crypto.tx.ckm == NULL) {
- return res;
- }
- break;
- case NGTCP2_CS_POST_HANDSHAKE:
- break;
- case NGTCP2_CS_CLOSING:
- return NGTCP2_ERR_CLOSING;
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_DRAINING;
- default:
- return 0;
- }
-
- assert(pktns->crypto.tx.ckm);
-
- if (conn_check_pkt_num_exhausted(conn)) {
- return NGTCP2_ERR_PKT_NUM_EXHAUSTED;
- }
-
- rv = conn_remove_retired_connection_id(conn, ts);
- if (rv != 0) {
- return rv;
- }
-
- if (vmsg) {
- switch (vmsg->type) {
- case NGTCP2_VMSG_TYPE_STREAM:
- if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) {
- wflags |= NGTCP2_WRITE_PKT_FLAG_MORE;
- }
- break;
- default:
- break;
- }
- }
-
- if (ppe_pending) {
- res = conn->pkt.hs_spktlen;
- conn->pkt.hs_spktlen = 0;
- /* dest and destlen have already been adjusted in ppe in the first
- run. They are adjusted for probe packet later. */
- nwrite =
- conn_write_pkt(conn, dest, destlen, vmsg, NGTCP2_PKT_SHORT, wflags, ts);
- goto fin;
- } else {
- if (conn->state == NGTCP2_CS_POST_HANDSHAKE) {
- rv = conn_prepare_key_update(conn, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- if (!conn->pktns.rtb.probe_pkt_left && conn_cwnd_is_zero(conn)) {
- destlen = 0;
- } else if (conn->pv) {
- nwrite = conn_write_path_challenge(conn, path, dest, destlen, ts);
- if (nwrite) {
- goto fin;
- }
- }
- }
-
- if (res == 0) {
- if (conn_handshake_remnants_left(conn)) {
- if (conn_handshake_probe_left(conn)) {
- destlen = origlen;
- }
- nwrite = conn_write_handshake_pkts(conn, dest, destlen, 0, ts);
- if (nwrite < 0) {
- return nwrite;
- }
- if (nwrite > 0) {
- res = nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
- }
- }
-
- if (conn->pktns.rtb.probe_pkt_left) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON,
- "transmit probe pkt left=%zu",
- conn->pktns.rtb.probe_pkt_left);
-
- nwrite =
- conn_write_pkt(conn, dest, destlen, vmsg, NGTCP2_PKT_SHORT, wflags, ts);
-
- goto fin;
- }
-
- nwrite =
- conn_write_pkt(conn, dest, destlen, vmsg, NGTCP2_PKT_SHORT, wflags, ts);
- if (nwrite) {
- assert(nwrite != NGTCP2_ERR_NOBUF);
- goto fin;
- }
-
- if (res == 0) {
- nwrite = conn_write_ack_pkt(conn, dest, origlen, NGTCP2_PKT_SHORT, ts);
- }
-
-fin:
- conn->pkt.hs_spktlen = 0;
-
- if (nwrite >= 0) {
- conn->cstat.bytes_sent += (size_t)nwrite;
- return res + nwrite;
- }
- /* NGTCP2_CONN_FLAG_PPE_PENDING is set in conn_write_pkt above.
- ppe_pending cannot be used here. */
- if (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING) {
- conn->pkt.hs_spktlen = res;
- }
-
- return nwrite;
-}
-
-static ngtcp2_ssize conn_write_connection_close(ngtcp2_conn *conn,
- uint8_t *dest, size_t destlen,
- uint8_t pkt_type,
- uint64_t error_code,
- ngtcp2_tstamp ts) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- ngtcp2_ssize res = 0, nwrite;
- ngtcp2_frame fr;
-
- fr.type = NGTCP2_FRAME_CONNECTION_CLOSE;
- fr.connection_close.error_code = error_code;
- fr.connection_close.frame_type = 0;
- fr.connection_close.reasonlen = 0;
- fr.connection_close.reason = NULL;
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED) &&
- pkt_type != NGTCP2_PKT_INITIAL) {
- if (in_pktns && conn->server) {
- nwrite = ngtcp2_conn_write_single_frame_pkt(
- conn, dest, destlen, NGTCP2_PKT_INITIAL, &conn->dcid.current.cid, &fr,
- NGTCP2_RTB_FLAG_NONE, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- dest += nwrite;
- destlen -= (size_t)nwrite;
- res += nwrite;
- }
-
- if (pkt_type != NGTCP2_PKT_HANDSHAKE && hs_pktns &&
- hs_pktns->crypto.tx.ckm) {
- nwrite = ngtcp2_conn_write_single_frame_pkt(
- conn, dest, destlen, NGTCP2_PKT_HANDSHAKE, &conn->dcid.current.cid,
- &fr, NGTCP2_RTB_FLAG_NONE, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- dest += nwrite;
- destlen -= (size_t)nwrite;
- res += nwrite;
- }
- }
-
- nwrite = ngtcp2_conn_write_single_frame_pkt(conn, dest, destlen, pkt_type,
- &conn->dcid.current.cid, &fr,
- NGTCP2_RTB_FLAG_NONE, ts);
-
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
-
- if (res == 0) {
- return NGTCP2_ERR_NOBUF;
- }
-
- return res;
-}
-
-ngtcp2_ssize ngtcp2_conn_write_connection_close(ngtcp2_conn *conn,
- ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- uint64_t error_code,
- ngtcp2_tstamp ts) {
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- uint8_t pkt_type;
- ngtcp2_ssize nwrite;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- if (conn_check_pkt_num_exhausted(conn)) {
- return NGTCP2_ERR_PKT_NUM_EXHAUSTED;
- }
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- case NGTCP2_CS_CLOSING:
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_INVALID_STATE;
- default:
- break;
- }
-
- if (path) {
- ngtcp2_path_copy(path, &conn->dcid.current.ps.path);
- }
-
- if (conn->state == NGTCP2_CS_POST_HANDSHAKE ||
- (conn->server && conn->pktns.crypto.tx.ckm)) {
- pkt_type = NGTCP2_PKT_SHORT;
- } else if (hs_pktns && hs_pktns->crypto.tx.ckm) {
- pkt_type = NGTCP2_PKT_HANDSHAKE;
- } else if (in_pktns && in_pktns->crypto.tx.ckm) {
- pkt_type = NGTCP2_PKT_INITIAL;
- } else {
- /* This branch is taken if server has not read any Initial packet
- from client. */
- return NGTCP2_ERR_INVALID_STATE;
- }
-
- nwrite = conn_write_connection_close(conn, dest, destlen, pkt_type,
- error_code, ts);
- if (nwrite < 0) {
- return nwrite;
- }
-
- conn->state = NGTCP2_CS_CLOSING;
-
- return nwrite;
-}
-
-ngtcp2_ssize ngtcp2_conn_write_application_close(ngtcp2_conn *conn,
- ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- uint64_t app_error_code,
- ngtcp2_tstamp ts) {
- ngtcp2_ssize nwrite;
- ngtcp2_ssize res = 0;
- ngtcp2_frame fr;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- if (conn_check_pkt_num_exhausted(conn)) {
- return NGTCP2_ERR_PKT_NUM_EXHAUSTED;
- }
-
- switch (conn->state) {
- case NGTCP2_CS_CLIENT_INITIAL:
- case NGTCP2_CS_CLOSING:
- case NGTCP2_CS_DRAINING:
- return NGTCP2_ERR_INVALID_STATE;
- default:
- break;
- }
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)) {
- nwrite = conn_write_connection_close(conn, dest, destlen,
- conn->hs_pktns->crypto.tx.ckm
- ? NGTCP2_PKT_HANDSHAKE
- : NGTCP2_PKT_INITIAL,
- NGTCP2_APPLICATION_ERROR, ts);
- if (nwrite < 0) {
- return nwrite;
- }
- res = nwrite;
- dest += nwrite;
- destlen -= (size_t)nwrite;
- }
-
- if (conn->state != NGTCP2_CS_POST_HANDSHAKE) {
- assert(res);
-
- if (!conn->server || !conn->pktns.crypto.tx.ckm) {
- return res;
- }
- }
-
- assert(conn->pktns.crypto.tx.ckm);
-
- if (path) {
- ngtcp2_path_copy(path, &conn->dcid.current.ps.path);
- }
-
- fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP;
- fr.connection_close.error_code = app_error_code;
- fr.connection_close.frame_type = 0;
- fr.connection_close.reasonlen = 0;
- fr.connection_close.reason = NULL;
-
- nwrite = ngtcp2_conn_write_single_frame_pkt(
- conn, dest, destlen, NGTCP2_PKT_SHORT, &conn->dcid.current.cid, &fr,
- NGTCP2_RTB_FLAG_NONE, ts);
-
- if (nwrite < 0) {
- return nwrite;
- }
-
- res += nwrite;
-
- if (res == 0) {
- return NGTCP2_ERR_NOBUF;
- }
-
- conn->state = NGTCP2_CS_CLOSING;
-
- return res;
-}
-
-int ngtcp2_conn_is_in_closing_period(ngtcp2_conn *conn) {
- return conn->state == NGTCP2_CS_CLOSING;
-}
-
-int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn) {
- return conn->state == NGTCP2_CS_DRAINING;
-}
-
-int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- int rv;
-
- if (!strm->app_error_code) {
- app_error_code = strm->app_error_code;
- }
-
- rv = ngtcp2_map_remove(&conn->strms, strm->me.key);
- if (rv != 0) {
- assert(rv != NGTCP2_ERR_INVALID_ARGUMENT);
- return rv;
- }
-
- rv = conn_call_stream_close(conn, strm, app_error_code);
- if (rv != 0) {
- goto fin;
- }
-
- if (ngtcp2_strm_is_tx_queued(strm)) {
- ngtcp2_pq_remove(&conn->tx.strmq, &strm->pe);
- }
-
-fin:
- ngtcp2_strm_free(strm);
- ngtcp2_mem_free(conn->mem, strm);
-
- return rv;
-}
-
-int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RDWR) ==
- NGTCP2_STRM_FLAG_SHUT_RDWR &&
- ((strm->flags & NGTCP2_STRM_FLAG_RECV_RST) ||
- ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) &&
- (((strm->flags & NGTCP2_STRM_FLAG_SENT_RST) &&
- (strm->flags & NGTCP2_STRM_FLAG_RST_ACKED)) ||
- (!(strm->flags & NGTCP2_STRM_FLAG_SENT_RST) &&
- ngtcp2_strm_is_all_tx_data_acked(strm)))) {
- return ngtcp2_conn_close_stream(conn, strm, app_error_code);
- }
- return 0;
-}
-
-/*
- * conn_shutdown_stream_write closes send stream with error code
- * |app_error_code|. RESET_STREAM frame is scheduled.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- if (strm->flags & NGTCP2_STRM_FLAG_SENT_RST) {
- return 0;
- }
-
- /* Set this flag so that we don't accidentally send DATA to this
- stream. */
- strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_SENT_RST;
- strm->app_error_code = app_error_code;
-
- ngtcp2_strm_streamfrq_clear(strm);
-
- return conn_reset_stream(conn, strm, app_error_code);
-}
-
-/*
- * conn_shutdown_stream_read closes read stream with error code
- * |app_error_code|. STOP_SENDING frame is scheduled.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code) {
- if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING) {
- return 0;
- }
- if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) &&
- ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) {
- return 0;
- }
-
- /* Extend connection flow control window for the amount of data
- which are not passed to application. */
- if (!(strm->flags &
- (NGTCP2_STRM_FLAG_STOP_SENDING | NGTCP2_STRM_FLAG_RECV_RST))) {
- ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset -
- ngtcp2_strm_rx_offset(strm));
- }
-
- strm->flags |= NGTCP2_STRM_FLAG_STOP_SENDING;
- strm->app_error_code = app_error_code;
-
- return conn_stop_sending(conn, strm, app_error_code);
-}
-
-int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t app_error_code) {
- int rv;
- ngtcp2_strm *strm;
-
- strm = ngtcp2_conn_find_stream(conn, stream_id);
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- rv = conn_shutdown_stream_read(conn, strm, app_error_code);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_shutdown_stream_write(conn, strm, app_error_code);
- if (rv != 0) {
- return rv;
- }
-
- return 0;
-}
-
-int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t app_error_code) {
- ngtcp2_strm *strm;
-
- strm = ngtcp2_conn_find_stream(conn, stream_id);
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- return conn_shutdown_stream_write(conn, strm, app_error_code);
-}
-
-int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t app_error_code) {
- ngtcp2_strm *strm;
-
- strm = ngtcp2_conn_find_stream(conn, stream_id);
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- return conn_shutdown_stream_read(conn, strm, app_error_code);
-}
-
-/*
- * conn_extend_max_stream_offset extends stream level flow control
- * window by |datalen| of the stream denoted by |strm|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int conn_extend_max_stream_offset(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t datalen) {
- ngtcp2_strm *top;
-
- if (datalen > NGTCP2_MAX_VARINT ||
- strm->rx.unsent_max_offset > NGTCP2_MAX_VARINT - datalen) {
- strm->rx.unsent_max_offset = NGTCP2_MAX_VARINT;
- } else {
- strm->rx.unsent_max_offset += datalen;
- }
-
- if (!(strm->flags &
- (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)) &&
- !ngtcp2_strm_is_tx_queued(strm) &&
- conn_should_send_max_stream_data(conn, strm)) {
- if (!ngtcp2_pq_empty(&conn->tx.strmq)) {
- top = ngtcp2_conn_tx_strmq_top(conn);
- strm->cycle = top->cycle;
- }
- strm->cycle = conn_tx_strmq_first_cycle(conn);
- return ngtcp2_conn_tx_strmq_push(conn, strm);
- }
-
- return 0;
-}
-
-int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id,
- uint64_t datalen) {
- ngtcp2_strm *strm;
-
- strm = ngtcp2_conn_find_stream(conn, stream_id);
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- return conn_extend_max_stream_offset(conn, strm, datalen);
-}
-
-void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, uint64_t datalen) {
- if (NGTCP2_MAX_VARINT < datalen ||
- conn->rx.unsent_max_offset > NGTCP2_MAX_VARINT - datalen) {
- conn->rx.unsent_max_offset = NGTCP2_MAX_VARINT;
- return;
- }
-
- conn->rx.unsent_max_offset += datalen;
-}
-
-void ngtcp2_conn_extend_max_streams_bidi(ngtcp2_conn *conn, size_t n) {
- handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams, n);
-}
-
-void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn, size_t n) {
- handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, n);
-}
-
-const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn) {
- return &conn->dcid.current.cid;
-}
-
-uint32_t ngtcp2_conn_get_negotiated_version(ngtcp2_conn *conn) {
- return conn->version;
-}
-
-int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) {
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_rtb *rtb = &conn->pktns.rtb;
- int rv;
-
- conn->flags |= NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED;
-
- rv = ngtcp2_rtb_remove_all(rtb, conn, pktns, &conn->cstat);
- if (rv != 0) {
- return rv;
- }
-
- return rv;
-}
-
-void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
- ngtcp2_duration ack_delay) {
- ngtcp2_conn_stat *cstat = &conn->cstat;
-
- rtt = ngtcp2_max(rtt, NGTCP2_GRANULARITY);
-
- cstat->latest_rtt = rtt;
-
- if (cstat->min_rtt == UINT64_MAX) {
- cstat->min_rtt = rtt;
- cstat->smoothed_rtt = rtt;
- cstat->rttvar = rtt / 2;
- } else {
- cstat->min_rtt = ngtcp2_min(cstat->min_rtt, rtt);
- if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) {
- ack_delay =
- ngtcp2_min(ack_delay, conn->remote.transport_params.max_ack_delay);
- } else {
- ack_delay = ngtcp2_min(ack_delay, NGTCP2_DEFAULT_MAX_ACK_DELAY);
- }
- if (rtt > cstat->min_rtt + ack_delay) {
- rtt -= ack_delay;
- }
-
- cstat->rttvar = (cstat->rttvar * 3 + (cstat->smoothed_rtt < rtt
- ? rtt - cstat->smoothed_rtt
- : cstat->smoothed_rtt - rtt)) /
- 4;
- cstat->smoothed_rtt = (cstat->smoothed_rtt * 7 + rtt) / 8;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "latest_rtt=%" PRIu64 " min_rtt=%" PRIu64
- " smoothed_rtt=%" PRIu64 " rttvar=%" PRIu64
- " ack_delay=%" PRIu64,
- (uint64_t)(cstat->latest_rtt / NGTCP2_MILLISECONDS),
- (uint64_t)(cstat->min_rtt / NGTCP2_MILLISECONDS),
- cstat->smoothed_rtt / NGTCP2_MILLISECONDS,
- cstat->rttvar / NGTCP2_MILLISECONDS,
- (uint64_t)(ack_delay / NGTCP2_MILLISECONDS));
-}
-
-void ngtcp2_conn_get_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) {
- *cstat = conn->cstat;
-}
-
-static ngtcp2_pktns *conn_get_earliest_pktns(ngtcp2_conn *conn,
- ngtcp2_tstamp *pts,
- const ngtcp2_tstamp *times) {
- ngtcp2_pktns *ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns};
- ngtcp2_pktns *res = ns[0];
- size_t i;
- ngtcp2_tstamp earliest_ts = times[NGTCP2_PKTNS_ID_INITIAL];
-
- for (i = NGTCP2_PKTNS_ID_HANDSHAKE; i < NGTCP2_PKTNS_ID_MAX; ++i) {
- if (ns[i] == NULL || ns[i]->rtb.num_retransmittable == 0 ||
- (times[i] == UINT64_MAX ||
- (earliest_ts != UINT64_MAX && times[i] >= earliest_ts) ||
- (i == NGTCP2_PKTNS_ID_APP &&
- !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) {
- continue;
- }
-
- earliest_ts = times[i];
- res = ns[i];
- }
-
- if (res == NULL && !conn->server) {
- earliest_ts = UINT64_MAX;
-
- if (conn->hs_pktns && conn->hs_pktns->crypto.tx.ckm) {
- res = conn->hs_pktns;
- } else {
- res = conn->in_pktns;
- }
- }
-
- if (pts) {
- *pts = earliest_ts;
- }
- return res;
-}
-
-void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_conn_stat *cstat = &conn->cstat;
- ngtcp2_duration timeout;
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- ngtcp2_pktns *pktns = &conn->pktns;
- ngtcp2_pktns *earliest_pktns;
- ngtcp2_tstamp earliest_loss_time;
- ngtcp2_tstamp last_tx_pkt_ts;
-
- conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time);
-
- if (earliest_loss_time != UINT64_MAX) {
- cstat->loss_detection_timer = earliest_loss_time;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "loss_detection_timer=%" PRIu64 " nonzero crypto loss time",
- cstat->loss_detection_timer);
- return;
- }
-
- if ((!in_pktns || in_pktns->rtb.num_retransmittable == 0) &&
- (!hs_pktns || hs_pktns->rtb.num_retransmittable == 0) &&
- (pktns->rtb.num_retransmittable == 0 ||
- !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) &&
- (conn->server ||
- (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED |
- NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)))) {
- if (cstat->loss_detection_timer) {
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "loss detection timer canceled");
- cstat->loss_detection_timer = 0;
- cstat->pto_count = 0;
- }
- return;
- }
-
- earliest_pktns =
- conn_get_earliest_pktns(conn, &last_tx_pkt_ts, cstat->last_tx_pkt_ts);
-
- assert(earliest_pktns);
-
- if (last_tx_pkt_ts == UINT64_MAX) {
- last_tx_pkt_ts = ts;
- }
-
- timeout = conn_compute_pto(conn, earliest_pktns) * (1ULL << cstat->pto_count);
-
- cstat->loss_detection_timer = last_tx_pkt_ts + timeout;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "loss_detection_timer=%" PRIu64 " last_tx_pkt_ts=%" PRIu64
- " timeout=%" PRIu64,
- cstat->loss_detection_timer, last_tx_pkt_ts,
- (uint64_t)(timeout / NGTCP2_MILLISECONDS));
-}
-
-int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) {
- ngtcp2_conn_stat *cstat = &conn->cstat;
- int rv;
- ngtcp2_pktns *in_pktns = conn->in_pktns;
- ngtcp2_pktns *hs_pktns = conn->hs_pktns;
- ngtcp2_tstamp earliest_loss_time;
- ngtcp2_pktns *loss_pktns =
- conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time);
- ngtcp2_pktns *earliest_pktns;
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- switch (conn->state) {
- case NGTCP2_CS_CLOSING:
- case NGTCP2_CS_DRAINING:
- cstat->loss_detection_timer = 0;
- cstat->pto_count = 0;
- return 0;
- default:
- break;
- }
-
- if (!cstat->loss_detection_timer) {
- return 0;
- }
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV,
- "loss detection timer fired");
-
- if (earliest_loss_time != UINT64_MAX) {
- rv = ngtcp2_conn_detect_lost_pkt(conn, loss_pktns, cstat, ts);
- if (rv != 0) {
- return rv;
- }
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
- return 0;
- }
-
- if (!conn->server && !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) {
- if (hs_pktns->crypto.tx.ckm) {
- hs_pktns->rtb.probe_pkt_left = 1;
- } else {
- in_pktns->rtb.probe_pkt_left = 1;
- }
- } else {
- earliest_pktns = conn_get_earliest_pktns(conn, NULL, cstat->last_tx_pkt_ts);
-
- assert(earliest_pktns);
-
- switch (earliest_pktns->rtb.pktns_id) {
- case NGTCP2_PKTNS_ID_INITIAL:
- assert(in_pktns);
- in_pktns->rtb.probe_pkt_left = 1;
- if (!conn->server) {
- break;
- }
- /* fall through for server so that it can coalesce packets. */
- /* fall through */
- case NGTCP2_PKTNS_ID_HANDSHAKE:
- assert(hs_pktns);
- hs_pktns->rtb.probe_pkt_left = 1;
- break;
- case NGTCP2_PKTNS_ID_APP:
- conn->pktns.rtb.probe_pkt_left = 2;
- break;
- default:
- assert(0);
- }
- }
-
- ++cstat->pto_count;
-
- ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, "pto_count=%zu",
- cstat->pto_count);
-
- ngtcp2_conn_set_loss_detection_timer(conn, ts);
-
- return 0;
-}
-
-int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn,
- ngtcp2_crypto_level crypto_level,
- const uint8_t *data, const size_t datalen) {
- ngtcp2_pktns *pktns;
- ngtcp2_frame_chain *frc;
- ngtcp2_crypto *fr;
- int rv;
-
- if (datalen == 0) {
- return 0;
- }
-
- switch (crypto_level) {
- case NGTCP2_CRYPTO_LEVEL_INITIAL:
- assert(conn->in_pktns);
- pktns = conn->in_pktns;
- break;
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- assert(conn->hs_pktns);
- pktns = conn->hs_pktns;
- break;
- case NGTCP2_CRYPTO_LEVEL_APP:
- pktns = &conn->pktns;
- break;
- default:
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- rv = ngtcp2_frame_chain_new(&frc, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- fr = &frc->fr.crypto;
-
- fr->type = NGTCP2_FRAME_CRYPTO;
- fr->offset = pktns->crypto.tx.offset;
- fr->datacnt = 1;
- fr->data[0].len = datalen;
- fr->data[0].base = (uint8_t *)data;
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL, &fr->offset, frc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
-
- pktns->crypto.strm.tx.offset += datalen;
- pktns->crypto.tx.offset += datalen;
-
- return 0;
-}
-
-int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, const uint8_t *token,
- size_t tokenlen) {
- int rv;
- ngtcp2_frame_chain *nfrc;
- uint8_t *p;
-
- assert(conn->server);
- assert(token);
- assert(tokenlen);
-
- rv = ngtcp2_frame_chain_extralen_new(&nfrc, tokenlen, conn->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr.type = NGTCP2_FRAME_NEW_TOKEN;
-
- p = (uint8_t *)nfrc + sizeof(*nfrc);
- memcpy(p, token, tokenlen);
-
- ngtcp2_vec_init(&nfrc->fr.new_token.token, p, tokenlen);
-
- nfrc->next = conn->pktns.tx.frq;
- conn->pktns.tx.frq = nfrc;
-
- return 0;
-}
-
-ngtcp2_strm *ngtcp2_conn_tx_strmq_top(ngtcp2_conn *conn) {
- assert(!ngtcp2_pq_empty(&conn->tx.strmq));
- return ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe);
-}
-
-void ngtcp2_conn_tx_strmq_pop(ngtcp2_conn *conn) {
- ngtcp2_strm *strm = ngtcp2_conn_tx_strmq_top(conn);
- assert(strm);
- ngtcp2_pq_pop(&conn->tx.strmq);
- strm->pe.index = NGTCP2_PQ_BAD_INDEX;
-}
-
-int ngtcp2_conn_tx_strmq_push(ngtcp2_conn *conn, ngtcp2_strm *strm) {
- return ngtcp2_pq_push(&conn->tx.strmq, &strm->pe);
-}
-
-size_t ngtcp2_conn_get_num_scid(ngtcp2_conn *conn) {
- return ngtcp2_ksl_len(&conn->scid.set);
-}
-
-size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest) {
- ngtcp2_ksl_it it;
- ngtcp2_scid *scid;
-
- for (it = ngtcp2_ksl_begin(&conn->scid.set); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- scid = ngtcp2_ksl_it_get(&it);
- *dest++ = scid->cid;
- }
-
- return ngtcp2_ksl_len(&conn->scid.set);
-}
-
-size_t ngtcp2_conn_get_num_active_dcid(ngtcp2_conn *conn) {
- size_t n = 1; /* for conn->dcid.current */
- ngtcp2_pv *pv = conn->pv;
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) {
- return 0;
- }
-
- if (pv) {
- if (pv->dcid.seq != conn->dcid.current.seq) {
- ++n;
- }
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->fallback_dcid.seq != conn->dcid.current.seq &&
- pv->fallback_dcid.seq != pv->dcid.seq) {
- ++n;
- }
- }
-
- n += ngtcp2_ringbuf_len(&conn->dcid.retired);
-
- return n;
-}
-
-static void copy_dcid_to_cid_token(ngtcp2_cid_token *dest,
- const ngtcp2_dcid *src) {
- dest->seq = src->seq;
- dest->cid = src->cid;
- ngtcp2_path_storage_init2(&dest->ps, &src->ps.path);
- dest->token_present =
- (uint8_t)!ngtcp2_check_invalid_stateless_reset_token(src->token);
- memcpy(dest->token, src->token, NGTCP2_STATELESS_RESET_TOKENLEN);
-}
-
-size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest) {
- ngtcp2_pv *pv = conn->pv;
- ngtcp2_cid_token *orig = dest;
- ngtcp2_dcid *dcid;
- size_t len, i;
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED)) {
- return 0;
- }
-
- copy_dcid_to_cid_token(dest, &conn->dcid.current);
- ++dest;
-
- if (pv) {
- if (pv->dcid.seq != conn->dcid.current.seq) {
- copy_dcid_to_cid_token(dest, &pv->dcid);
- ++dest;
- }
- if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) &&
- pv->fallback_dcid.seq != conn->dcid.current.seq &&
- pv->fallback_dcid.seq != pv->dcid.seq) {
- copy_dcid_to_cid_token(dest, &pv->fallback_dcid);
- ++dest;
- }
- }
-
- len = ngtcp2_ringbuf_len(&conn->dcid.retired);
- for (i = 0; i < len; ++i) {
- dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i);
- copy_dcid_to_cid_token(dest, dcid);
- ++dest;
- }
-
- return (size_t)(dest - orig);
-}
-
-void ngtcp2_conn_set_local_addr(ngtcp2_conn *conn, const ngtcp2_addr *addr) {
- ngtcp2_addr *dest = &conn->dcid.current.ps.path.local;
-
- assert(addr->addrlen <= sizeof(conn->dcid.current.ps.local_addrbuf));
- ngtcp2_addr_copy(dest, addr);
-}
-
-void ngtcp2_conn_set_remote_addr(ngtcp2_conn *conn, const ngtcp2_addr *addr) {
- ngtcp2_addr *dest = &conn->dcid.current.ps.path.remote;
-
- assert(addr->addrlen <= sizeof(conn->dcid.current.ps.remote_addrbuf));
- ngtcp2_addr_copy(dest, addr);
-}
-
-const ngtcp2_addr *ngtcp2_conn_get_remote_addr(ngtcp2_conn *conn) {
- return &conn->dcid.current.ps.path.remote;
-}
-
-int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path,
- ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_dcid *dcid;
-
- assert(!conn->server);
-
- conn->log.last_ts = ts;
- conn->qlog.last_ts = ts;
-
- if (conn->remote.transport_params.disable_active_migration ||
- !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED)) {
- return NGTCP2_ERR_INVALID_STATE;
- }
- if (ngtcp2_ringbuf_len(&conn->dcid.unused) == 0) {
- return NGTCP2_ERR_CONN_ID_BLOCKED;
- }
-
- if (ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0);
-
- rv = conn_stop_pv(conn, ts);
- if (rv != 0) {
- return rv;
- }
-
- rv = conn_retire_dcid(conn, &conn->dcid.current, ts);
- if (rv != 0) {
- return rv;
- }
-
- ngtcp2_dcid_copy(&conn->dcid.current, dcid);
- ngtcp2_path_copy(&conn->dcid.current.ps.path, path);
- ngtcp2_ringbuf_pop_front(&conn->dcid.unused);
-
- rv = conn_call_activate_dcid(conn, &conn->dcid.current);
- if (rv != 0) {
- return rv;
- }
-
- conn_reset_congestion_state(conn);
-
- return 0;
-}
-
-uint64_t ngtcp2_conn_get_max_local_streams_uni(ngtcp2_conn *conn) {
- return conn->local.uni.max_streams;
-}
-
-uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn) {
- return conn->tx.max_offset - conn->tx.offset;
-}
-
-uint64_t ngtcp2_conn_get_streams_bidi_left(ngtcp2_conn *conn) {
- uint64_t n = ngtcp2_ord_stream_id(conn->local.bidi.next_stream_id);
-
- return n > conn->local.bidi.max_streams
- ? 0
- : conn->local.bidi.max_streams - n + 1;
-}
-
-uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn) {
- uint64_t n = ngtcp2_ord_stream_id(conn->local.uni.next_stream_id);
-
- return n > conn->local.uni.max_streams ? 0
- : conn->local.uni.max_streams - n + 1;
-}
-
-ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) {
- ngtcp2_duration trpto;
- ngtcp2_duration idle_timeout;
-
- /* TODO Remote max_idle_timeout becomes effective after handshake
- completion. */
-
- if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED) ||
- conn->remote.transport_params.max_idle_timeout == 0 ||
- (conn->local.settings.transport_params.max_idle_timeout &&
- conn->local.settings.transport_params.max_idle_timeout <
- conn->remote.transport_params.max_idle_timeout)) {
- idle_timeout = conn->local.settings.transport_params.max_idle_timeout;
- } else {
- idle_timeout = conn->remote.transport_params.max_idle_timeout;
- }
-
- if (idle_timeout == 0) {
- return UINT64_MAX;
- }
-
- trpto = 3 * conn_compute_pto(
- conn, (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)
- ? &conn->pktns
- : conn->hs_pktns);
-
- return conn->idle_ts + ngtcp2_max(idle_timeout, trpto);
-}
-
-ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn) {
- return conn_compute_pto(conn,
- (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)
- ? &conn->pktns
- : conn->hs_pktns);
-}
-
-void ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn,
- const ngtcp2_crypto_ctx *ctx) {
- assert(conn->in_pktns);
- conn->in_pktns->crypto.ctx = *ctx;
-}
-
-const ngtcp2_crypto_ctx *ngtcp2_conn_get_initial_crypto_ctx(ngtcp2_conn *conn) {
- assert(conn->in_pktns);
- return &conn->in_pktns->crypto.ctx;
-}
-
-void ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn,
- const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx) {
- assert(!conn->crypto.retry_aead_ctx.native_handle);
-
- conn->crypto.retry_aead = *aead;
- conn->crypto.retry_aead_ctx = *aead_ctx;
-}
-
-void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn,
- const ngtcp2_crypto_ctx *ctx) {
- assert(conn->hs_pktns);
- conn->hs_pktns->crypto.ctx = *ctx;
- conn->pktns.crypto.ctx = *ctx;
-}
-
-const ngtcp2_crypto_ctx *ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn) {
- return &conn->pktns.crypto.ctx;
-}
-
-void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn) {
- return conn->crypto.tls_native_handle;
-}
-
-void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn,
- void *tls_native_handle) {
- conn->crypto.tls_native_handle = tls_native_handle;
-}
-
-void ngtcp2_conn_get_connection_close_error_code(
- ngtcp2_conn *conn, ngtcp2_connection_close_error_code *ccec) {
- *ccec = conn->rx.ccec;
-}
-
-void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr) {
- conn->crypto.tls_error = liberr;
-}
-
-int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn) {
- return conn->crypto.tls_error;
-}
-
-int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn, int64_t stream_id) {
- return conn_local_stream(conn, stream_id);
-}
-
-int ngtcp2_conn_is_server(ngtcp2_conn *conn) { return conn->server; }
-
-int ngtcp2_conn_after_retry(ngtcp2_conn *conn) {
- return (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY) != 0;
-}
-
-int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id,
- void *stream_user_data) {
- ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id);
-
- if (strm == NULL) {
- return NGTCP2_ERR_STREAM_NOT_FOUND;
- }
-
- strm->stream_user_data = stream_user_data;
-
- return 0;
-}
-
-void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent,
- const uint8_t *data) {
- memcpy(pcent->data, data, sizeof(pcent->data));
-}
-
-void ngtcp2_settings_default(ngtcp2_settings *settings) {
- memset(settings, 0, sizeof(*settings));
- settings->cc_algo = NGTCP2_CC_ALGO_CUBIC;
- settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT;
- settings->transport_params.max_udp_payload_size =
- NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE;
- settings->transport_params.ack_delay_exponent =
- NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- settings->transport_params.max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
- settings->transport_params.active_connection_id_limit =
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
-}
-
-/* The functions prefixed with ngtcp2_pkt_ are usually put inside
- ngtcp2_pkt.c. This function uses encryption construct and uses
- test data defined only in ngtcp2_conn_test.c, so it is written
- here. */
-ngtcp2_ssize ngtcp2_pkt_write_connection_close(
- uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt,
- const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp,
- const ngtcp2_crypto_cipher_ctx *hp_ctx) {
- ngtcp2_pkt_hd hd;
- ngtcp2_crypto_km ckm;
- ngtcp2_crypto_cc cc;
- ngtcp2_ppe ppe;
- ngtcp2_frame fr = {0};
- int rv;
-
- ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_INITIAL, dcid,
- scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1,
- NGTCP2_PROTO_VER, /* len = */ 0);
-
- ngtcp2_vec_init(&ckm.secret, NULL, 0);
- ngtcp2_vec_init(&ckm.iv, iv, 12);
- ckm.aead_ctx = *aead_ctx;
- ckm.pkt_num = 0;
- ckm.flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
-
- cc.aead_overhead = NGTCP2_INITIAL_AEAD_OVERHEAD;
- cc.aead = *aead;
- cc.hp = *hp;
- cc.ckm = &ckm;
- cc.hp_ctx = *hp_ctx;
- cc.encrypt = encrypt;
- cc.hp_mask = hp_mask;
-
- ngtcp2_ppe_init(&ppe, dest, destlen, &cc);
-
- rv = ngtcp2_ppe_encode_hd(&ppe, &hd);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return rv;
- }
-
- if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) {
- return NGTCP2_ERR_NOBUF;
- }
-
- fr.type = NGTCP2_FRAME_CONNECTION_CLOSE;
- fr.connection_close.error_code = error_code;
-
- rv = ngtcp2_ppe_encode_frame(&ppe, &fr);
- if (rv != 0) {
- assert(NGTCP2_ERR_NOBUF == rv);
- return rv;
- }
-
- return ngtcp2_ppe_final(&ppe, NULL);
-}
-
-int ngtcp2_is_bidi_stream(int64_t stream_id) { return bidi_stream(stream_id); }
diff --git a/deps/ngtcp2/lib/ngtcp2_conn.h b/deps/ngtcp2/lib/ngtcp2_conn.h
deleted file mode 100644
index d7782b1114..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_conn.h
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CONN_H
-#define NGTCP2_CONN_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_crypto.h"
-#include "ngtcp2_acktr.h"
-#include "ngtcp2_rtb.h"
-#include "ngtcp2_strm.h"
-#include "ngtcp2_mem.h"
-#include "ngtcp2_idtr.h"
-#include "ngtcp2_str.h"
-#include "ngtcp2_pkt.h"
-#include "ngtcp2_log.h"
-#include "ngtcp2_pq.h"
-#include "ngtcp2_cc.h"
-#include "ngtcp2_pv.h"
-#include "ngtcp2_cid.h"
-#include "ngtcp2_buf.h"
-#include "ngtcp2_ppe.h"
-#include "ngtcp2_qlog.h"
-#include "ngtcp2_rst.h"
-
-typedef enum {
- /* Client specific handshake states */
- NGTCP2_CS_CLIENT_INITIAL,
- NGTCP2_CS_CLIENT_WAIT_HANDSHAKE,
- NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED,
- /* Server specific handshake states */
- NGTCP2_CS_SERVER_INITIAL,
- NGTCP2_CS_SERVER_WAIT_HANDSHAKE,
- NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED,
- /* Shared by both client and server */
- NGTCP2_CS_POST_HANDSHAKE,
- NGTCP2_CS_CLOSING,
- NGTCP2_CS_DRAINING,
-} ngtcp2_conn_state;
-
-/* NGTCP2_MAX_STREAMS is the maximum number of streams. */
-#define NGTCP2_MAX_STREAMS (1LL << 60)
-
-/* NGTCP2_MAX_NUM_BUFFED_RX_PKTS is the maximum number of buffered
- reordered packets. */
-#define NGTCP2_MAX_NUM_BUFFED_RX_PKTS 4
-
-/* NGTCP2_MAX_REORDERED_CRYPTO_DATA is the maximum offset of crypto
- data which is not continuous. In other words, there is a gap of
- unreceived data. */
-#define NGTCP2_MAX_REORDERED_CRYPTO_DATA 65536
-
-/* NGTCP2_MAX_RX_INITIAL_CRYPTO_DATA is the maximum offset of received
- crypto stream in Initial packet. We set this hard limit here
- because crypto stream is unbounded. */
-#define NGTCP2_MAX_RX_INITIAL_CRYPTO_DATA 65536
-/* NGTCP2_MAX_RX_HANDSHAKE_CRYPTO_DATA is the maximum offset of
- received crypto stream in Handshake packet. We set this hard limit
- here because crypto stream is unbounded. */
-#define NGTCP2_MAX_RX_HANDSHAKE_CRYPTO_DATA 65536
-
-/* NGTCP2_MAX_RETRIES is the number of Retry packet which client can
- accept. */
-#define NGTCP2_MAX_RETRIES 3
-
-/* NGTCP2_MAX_DCID_POOL_SIZE is the maximum number of destination
- connection ID the remote endpoint provides to store. It must be
- the power of 2. */
-#define NGTCP2_MAX_DCID_POOL_SIZE 8
-/* NGTCP2_MAX_DCID_RETIRED_SIZE is the maximum number of retired DCID
- kept to catch in-flight packet on retired path. */
-#define NGTCP2_MAX_DCID_RETIRED_SIZE 2
-/* NGTCP2_MAX_SCID_POOL_SIZE is the maximum number of source
- connection ID the local endpoint provides to the remote endpoint.
- The chosen value was described in old draft. Now a remote endpoint
- tells the maximum value. The value can be quite large, and we have
- to put the sane limit.*/
-#define NGTCP2_MAX_SCID_POOL_SIZE 8
-
-/* NGTCP2_MAX_NON_ACK_TX_PKT is the maximum number of continuous non
- ACK-eliciting packets. */
-#define NGTCP2_MAX_NON_ACK_TX_PKT 3
-
-/*
- * ngtcp2_max_frame is defined so that it covers the largest ACK
- * frame.
- */
-typedef union {
- ngtcp2_frame fr;
- struct {
- ngtcp2_ack ack;
- /* ack includes 1 ngtcp2_ack_blk. */
- ngtcp2_ack_blk blks[NGTCP2_MAX_ACK_BLKS - 1];
- } ackfr;
-} ngtcp2_max_frame;
-
-typedef struct {
- uint8_t data[8];
-} ngtcp2_path_challenge_entry;
-
-void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent,
- const uint8_t *data);
-
-typedef enum {
- NGTCP2_CONN_FLAG_NONE = 0x00,
- /* NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED is set if handshake
- completed. */
- NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED = 0x01,
- /* NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED is set if connection ID is
- negotiated. This is only used for client. */
- NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED = 0x02,
- /* NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED is set if transport
- parameters are received. */
- NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED = 0x04,
- /* NGTCP2_CONN_FLAG_RECV_PROTECTED_PKT is set when a protected
- packet is received, and decrypted successfully. This flag is
- used to stop retransmitting handshake packets. It might be
- replaced with an another mechanism when we implement key
- update. */
- NGTCP2_CONN_FLAG_RECV_PROTECTED_PKT = 0x08,
- /* NGTCP2_CONN_FLAG_RECV_RETRY is set when a client receives Retry
- packet. */
- NGTCP2_CONN_FLAG_RECV_RETRY = 0x10,
- /* NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED is set when 0-RTT packet is
- rejected by a peer. */
- NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED = 0x20,
- /* NGTCP2_CONN_FLAG_SADDR_VERIFIED is set when source address is
- verified. */
- NGTCP2_CONN_FLAG_SADDR_VERIFIED = 0x40,
- /* NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED is set when an endpoint
- confirmed completion of handshake. */
- NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED = 0x80,
- /* NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED is set when the
- library transitions its state to "post handshake". */
- NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED = 0x0100,
- /* NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED is set when key update
- is not confirmed by the local endpoint. That is, it has not
- received ACK frame which acknowledges packet which is encrypted
- with new key. */
- NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED = 0x0800,
- /* NGTCP2_CONN_FLAG_PPE_PENDING is set when
- NGTCP2_WRITE_STREAM_FLAG_MORE is used and the intermediate state
- of ngtcp2_ppe is stored in pkt struct of ngtcp2_conn. */
- NGTCP2_CONN_FLAG_PPE_PENDING = 0x1000,
- /* NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE is set when idle
- timer should be restarted on next write. */
- NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE = 0x2000,
- /* NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED indicates that server as
- peer verified client address. This flag is only used by
- client. */
- NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED = 0x4000,
-} ngtcp2_conn_flag;
-
-typedef struct {
- ngtcp2_buf buf;
- /* pkt_type is the type of packet to send data in buf. If it is 0,
- it must be sent in Short packet. Otherwise, it is sent the long
- packet type denoted by pkt_type. */
- uint8_t pkt_type;
-} ngtcp2_crypto_data;
-
-typedef struct ngtcp2_pktns {
- struct {
- /* last_pkt_num is the packet number which the local endpoint sent
- last time.*/
- int64_t last_pkt_num;
- ngtcp2_frame_chain *frq;
- /* num_non_ack_pkt is the number of continuous non ACK-eliciting
- packets. */
- size_t num_non_ack_pkt;
- } tx;
-
- struct {
- /* pngap tracks received packet number in order to suppress
- duplicated packet number. */
- ngtcp2_gaptr pngap;
- /* max_pkt_num is the largest packet number received so far. */
- int64_t max_pkt_num;
- /* max_pkt_ts is the timestamp when max_pkt_num packet is
- received. */
- ngtcp2_tstamp max_pkt_ts;
- /*
- * buffed_pkts is buffered packets which cannot be decrypted with
- * the current encryption level.
- *
- * In server Initial encryption level, 0-RTT packet may be buffered.
- * In server Handshake encryption level, Short packet may be buffered.
- *
- * In client Initial encryption level, Handshake or Short packet may
- * be buffered. In client Handshake encryption level, Short packet
- * may be buffered.
- *
- * - 0-RTT packet is only buffered in server Initial encryption
- * level ngtcp2_pktns.
- *
- * - Handshake packet is only buffered in client Handshake
- * encryption level ngtcp2_pktns.
- *
- * - Short packet is only buffered in Short encryption level
- * ngtcp2_pktns.
- */
- ngtcp2_pkt_chain *buffed_pkts;
- } rx;
-
- struct {
- struct {
- /* frq contains crypto data sorted by their offset. */
- ngtcp2_ksl frq;
- /* offset is the offset of crypto stream in this packet number
- space. */
- uint64_t offset;
- /* ckm is a cryptographic key, and iv to encrypt outgoing
- packets. */
- ngtcp2_crypto_km *ckm;
- /* hp_ctx is cipher context for packet header protection. */
- ngtcp2_crypto_cipher_ctx hp_ctx;
- } tx;
-
- struct {
- /* ckm is a cryptographic key, and iv to decrypt incoming
- packets. */
- ngtcp2_crypto_km *ckm;
- /* hp_ctx is cipher context for packet header protection. */
- ngtcp2_crypto_cipher_ctx hp_ctx;
- } rx;
-
- ngtcp2_strm strm;
- ngtcp2_crypto_ctx ctx;
- } crypto;
-
- ngtcp2_acktr acktr;
- ngtcp2_rtb rtb;
-} ngtcp2_pktns;
-
-struct ngtcp2_conn {
- ngtcp2_conn_state state;
- ngtcp2_conn_callbacks callbacks;
- /* rcid is a connection ID present in Initial or 0-RTT packet from
- client as destination connection ID. Server uses this field to
- check that duplicated Initial or 0-RTT packet are indeed sent to
- this connection. It is also sent to client as
- original_destination_connection_id transport parameter. Client
- uses this field to validate original_destination_connection_id
- transport parameter if no Retry packet is involved. */
- ngtcp2_cid rcid;
- /* oscid is the source connection ID initially used by the local
- endpoint. */
- ngtcp2_cid oscid;
- /* retry_scid is the source connection ID from Retry packet. Client
- records it in order to verify retry_source_connection_id
- transport parameter. Server does not use this field. */
- ngtcp2_cid retry_scid;
- ngtcp2_pktns *in_pktns;
- ngtcp2_pktns *hs_pktns;
- ngtcp2_pktns pktns;
-
- struct {
- /* current is the current destination connection ID. */
- ngtcp2_dcid current;
- /* unused is a set of unused CID received from peer. */
- ngtcp2_ringbuf unused;
- /* retired is a set of CID retired by local endpoint. Keep them
- in 3*PTO to catch packets in flight along the old path. */
- ngtcp2_ringbuf retired;
- /* seqgap tracks received sequence numbers in order to ignore
- retransmitted duplicated NEW_CONNECTION_ID frame. */
- ngtcp2_gaptr seqgap;
- /* retire_prior_to is the largest retire_prior_to received so
- far. */
- uint64_t retire_prior_to;
- /* num_retire_queued is the number of RETIRE_CONNECTION_ID frames
- queued for transmission. */
- size_t num_retire_queued;
- } dcid;
-
- struct {
- /* set is a set of CID sent to peer. The peer can use any CIDs in
- this set. This includes used CID as well as unused ones. */
- ngtcp2_ksl set;
- /* used is a set of CID used by peer. The sort function of this
- priority queue takes timestamp when CID is retired and sorts
- them in ascending order. */
- ngtcp2_pq used;
- /* last_seq is the last sequence number of connection ID. */
- uint64_t last_seq;
- /* num_retired is the number of retired Connection ID still
- included in set. */
- size_t num_retired;
- } scid;
-
- struct {
- /* strmq contains ngtcp2_strm which has frames to send. */
- ngtcp2_pq strmq;
- /* ack is ACK frame. The underlying buffer is resused. */
- ngtcp2_frame *ack;
- /* max_ack_blks is the number of additional ngtcp2_ack_blk which
- ack can contain. */
- size_t max_ack_blks;
- /* offset is the offset the local endpoint has sent to the remote
- endpoint. */
- uint64_t offset;
- /* max_offset is the maximum offset that local endpoint can
- send. */
- uint64_t max_offset;
- } tx;
-
- struct {
- /* unsent_max_offset is the maximum offset that remote endpoint
- can send without extending MAX_DATA. This limit is not yet
- notified to the remote endpoint. */
- uint64_t unsent_max_offset;
- /* offset is the cumulative sum of stream data received for this
- connection. */
- uint64_t offset;
- /* max_offset is the maximum offset that remote endpoint can
- send. */
- uint64_t max_offset;
- /* path_challenge stores received PATH_CHALLENGE data. */
- ngtcp2_ringbuf path_challenge;
- /* ccec is the received connection close error code. */
- ngtcp2_connection_close_error_code ccec;
- struct {
- /* start_ts is the time instant when receiving rate measurement
- is started. */
- ngtcp2_tstamp start_ts;
- /* received is the number of bytes received in the current
- measurement period. */
- uint64_t received;
- } rate;
- } rx;
-
- struct {
- ngtcp2_crypto_km *ckm;
- ngtcp2_crypto_cipher_ctx hp_ctx;
- } early;
-
- struct {
- ngtcp2_settings settings;
- struct {
- /* max_streams is the maximum number of bidirectional streams which
- the local endpoint can open. */
- uint64_t max_streams;
- /* next_stream_id is the bidirectional stream ID which the local
- endpoint opens next. */
- int64_t next_stream_id;
- } bidi;
-
- struct {
- /* max_streams is the maximum number of unidirectional streams
- which the local endpoint can open. */
- uint64_t max_streams;
- /* next_stream_id is the unidirectional stream ID which the
- local endpoint opens next. */
- int64_t next_stream_id;
- } uni;
- } local;
-
- struct {
- /* transport_params is the received transport parameters during
- handshake. It is used for Short packet only. */
- ngtcp2_transport_params transport_params;
- /* pending_transport_params is received transport parameters
- during handshake. It is copied to transport_params when 1RTT
- key is available. */
- ngtcp2_transport_params pending_transport_params;
- struct {
- ngtcp2_idtr idtr;
- /* unsent_max_streams is the maximum number of streams of peer
- initiated bidirectional stream which the local endpoint can
- accept. This limit is not yet notified to the remote
- endpoint. */
- uint64_t unsent_max_streams;
- /* max_streams is the maximum number of streams of peer
- initiated bidirectional stream which the local endpoint can
- accept. */
- uint64_t max_streams;
- } bidi;
-
- struct {
- ngtcp2_idtr idtr;
- /* unsent_max_streams is the maximum number of streams of peer
- initiated unidirectional stream which the local endpoint can
- accept. This limit is not yet notified to the remote
- endpoint. */
- uint64_t unsent_max_streams;
- /* max_streams is the maximum number of streams of peer
- initiated unidirectional stream which the local endpoint can
- accept. */
- uint64_t max_streams;
- } uni;
- } remote;
-
- struct {
- struct {
- /* new_tx_ckm is a new sender 1RTT key which has not been
- used. */
- ngtcp2_crypto_km *new_tx_ckm;
- /* new_rx_ckm is a new receiver 1RTT key which has not
- successfully decrypted incoming packet yet. */
- ngtcp2_crypto_km *new_rx_ckm;
- /* old_rx_ckm is an old receiver 1RTT key. */
- ngtcp2_crypto_km *old_rx_ckm;
- /* confirmed_ts is the time instant when the key update is
- confirmed by the local endpoint last time. UINT64_MAX means
- undefined value. */
- ngtcp2_tstamp confirmed_ts;
- } key_update;
-
- /* tls_native_handle is a native handle to TLS session object. */
- void *tls_native_handle;
- size_t aead_overhead;
- /* decrypt_buf is a buffer which is used to write decrypted data. */
- ngtcp2_vec decrypt_buf;
- /* retry_aead is AEAD to verify Retry packet integrity. It is
- used by client only. */
- ngtcp2_crypto_aead retry_aead;
- /* retry_aead_ctx is AEAD cipher context to verify Retry packet
- integrity. It is used by client only. */
- ngtcp2_crypto_aead_ctx retry_aead_ctx;
- /* tls_error is TLS related error. */
- int tls_error;
- } crypto;
-
- /* pkt contains the packet intermediate construction data to support
- NGTCP2_WRITE_STREAM_FLAG_MORE */
- struct {
- ngtcp2_crypto_cc cc;
- ngtcp2_pkt_hd hd;
- ngtcp2_ppe ppe;
- ngtcp2_frame_chain **pfrc;
- int pkt_empty;
- int hd_logged;
- uint8_t rtb_entry_flags;
- int was_client_initial;
- ngtcp2_ssize hs_spktlen;
- } pkt;
-
- ngtcp2_map strms;
- ngtcp2_conn_stat cstat;
- ngtcp2_pv *pv;
- ngtcp2_log log;
- ngtcp2_qlog qlog;
- ngtcp2_rst rst;
- ngtcp2_cc_algo cc_algo;
- ngtcp2_cc cc;
- const ngtcp2_mem *mem;
- /* idle_ts is the time instant when idle timer started. */
- ngtcp2_tstamp idle_ts;
- void *user_data;
- uint32_t version;
- /* flags is bitwise OR of zero or more of ngtcp2_conn_flag. */
- uint16_t flags;
- int server;
-};
-
-typedef enum ngtcp2_vmsg_type {
- NGTCP2_VMSG_TYPE_STREAM,
-} ngtcp2_vmsg_type;
-
-typedef struct ngtcp2_vmsg_stream {
- /* strm is a stream that data is sent to. */
- ngtcp2_strm *strm;
- /* flags is bitwise OR of zero or more of
- ngtcp2_write_stream_flag. */
- uint32_t flags;
- /* data is the pointer to ngtcp2_vec array which contains the stream
- data to send. */
- const ngtcp2_vec *data;
- /* datacnt is the number of ngtcp2_vec pointed by data. */
- size_t datacnt;
- /* *pdatalen is the pointer to the variable which the number of
- bytes written is assigned to if pdatalen is not NULL. */
- ngtcp2_ssize *pdatalen;
-} ngtcp2_vmsg_stream;
-
-typedef struct ngtcp2_vmsg {
- ngtcp2_vmsg_type type;
- union {
- ngtcp2_vmsg_stream stream;
- };
-} ngtcp2_vmsg;
-
-/*
- * ngtcp2_conn_sched_ack stores packet number |pkt_num| and its
- * reception timestamp |ts| in order to send its ACK.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_PROTO
- * Same packet number has already been added.
- */
-int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr,
- int64_t pkt_num, int active_ack, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_find_stream returns a stream whose stream ID is
- * |stream_id|. If no such stream is found, it returns NULL.
- */
-ngtcp2_strm *ngtcp2_conn_find_stream(ngtcp2_conn *conn, int64_t stream_id);
-
-/*
- * conn_init_stream initializes |strm|. Its stream ID is |stream_id|.
- * This function adds |strm| to conn->strms. |strm| must be allocated
- * by the caller.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-callback function failed.
- */
-int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
- int64_t stream_id, void *stream_user_data);
-
-/*
- * ngtcp2_conn_close_stream closes stream |strm|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Stream is not found.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code);
-
-/*
- * ngtcp2_conn_close_stream closes stream |strm| if no further
- * transmission and reception are allowed, and all reordered incoming
- * data are emitted to the application, and the transmitted data are
- * acked.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Stream is not found.
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm,
- uint64_t app_error_code);
-
-/*
- * ngtcp2_conn_update_rtt updates RTT measurements. |rtt| is a latest
- * RTT which is not adjusted by ack delay. |ack_delay| is unscaled
- * ack_delay included in ACK frame. |ack_delay| is actually tainted
- * (sent by peer), so don't assume that |ack_delay| is always smaller
- * than, or equals to |rtt|.
- */
-void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt,
- ngtcp2_duration ack_delay);
-
-void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_detect_lost_pkt detects lost packets.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_tx_strmq_top returns the ngtcp2_strm which sits on the
- * top of queue. tx_strmq must not be empty.
- */
-ngtcp2_strm *ngtcp2_conn_tx_strmq_top(ngtcp2_conn *conn);
-
-/*
- * ngtcp2_conn_tx_strmq_pop pops the ngtcp2_strm from the queue.
- * tx_strmq must not be empty.
- */
-void ngtcp2_conn_tx_strmq_pop(ngtcp2_conn *conn);
-
-/*
- * ngtcp2_conn_tx_strmq_push pushes |strm| into tx_strmq.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_conn_tx_strmq_push(ngtcp2_conn *conn, ngtcp2_strm *strm);
-
-/*
- * ngtcp2_conn_internal_expiry returns the minimum expiry time among
- * all timers in |conn|.
- */
-ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn);
-
-ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path,
- uint8_t *dest, size_t destlen,
- ngtcp2_vmsg *vmsg, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_write_single_frame_pkt writes a packet which contains |fr|
- * frame only in the buffer pointed by |dest| whose length if
- * |destlen|. |type| is a long packet type to send. If |type| is 0,
- * Short packet is used. |dcid| is used as a destination connection
- * ID.
- *
- * The packet written by this function will not be retransmitted.
- *
- * This function returns the number of bytes written in |dest| if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-ngtcp2_ssize
-ngtcp2_conn_write_single_frame_pkt(ngtcp2_conn *conn, uint8_t *dest,
- size_t destlen, uint8_t type,
- const ngtcp2_cid *dcid, ngtcp2_frame *fr,
- uint8_t rtb_flags, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_commit_local_transport_params commits the local
- * transport parameters, which is currently set to
- * conn->local.settings.transport_params. This function will do some
- * amends on transport parameters for adjusting default values.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_INVALID_ARGUMENT
- * CID in preferred address equals to the original SCID.
- */
-int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn);
-
-/*
- * ngtcp2_conn_lost_pkt_expiry returns the earliest expiry time of
- * lost packet.
- */
-ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn);
-
-/*
- * ngtcp2_conn_remove_lost_pkt removes the expired lost packet.
- */
-void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_conn_resched_frames reschedules frames linked from |*pfrc|
- * for retransmission.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns,
- ngtcp2_frame_chain **pfrc);
-
-uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn);
-
-#endif /* NGTCP2_CONN_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_conv.c b/deps/ngtcp2/lib/ngtcp2_conv.c
deleted file mode 100644
index 18cf314791..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_conv.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_conv.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_str.h"
-#include "ngtcp2_pkt.h"
-
-uint64_t ngtcp2_get_uint64(const uint8_t *p) {
- uint64_t n;
- memcpy(&n, p, 8);
- return ngtcp2_ntohl64(n);
-}
-
-uint64_t ngtcp2_get_uint48(const uint8_t *p) {
- uint64_t n = 0;
- memcpy(((uint8_t *)&n) + 2, p, 6);
- return ngtcp2_ntohl64(n);
-}
-
-uint32_t ngtcp2_get_uint32(const uint8_t *p) {
- uint32_t n;
- memcpy(&n, p, 4);
- return ngtcp2_ntohl(n);
-}
-
-uint32_t ngtcp2_get_uint24(const uint8_t *p) {
- uint32_t n = 0;
- memcpy(((uint8_t *)&n) + 1, p, 3);
- return ngtcp2_ntohl(n);
-}
-
-uint16_t ngtcp2_get_uint16(const uint8_t *p) {
- uint16_t n;
- memcpy(&n, p, 2);
- return ngtcp2_ntohs(n);
-}
-
-uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p) {
- union {
- char b[8];
- uint16_t n16;
- uint32_t n32;
- uint64_t n64;
- } n;
-
- *plen = 1u << (*p >> 6);
-
- switch (*plen) {
- case 1:
- return *p;
- case 2:
- memcpy(&n, p, 2);
- n.b[0] &= 0x3f;
- return ngtcp2_ntohs(n.n16);
- case 4:
- memcpy(&n, p, 4);
- n.b[0] &= 0x3f;
- return ngtcp2_ntohl(n.n32);
- case 8:
- memcpy(&n, p, 8);
- n.b[0] &= 0x3f;
- return ngtcp2_ntohl64(n.n64);
- }
-
- assert(0);
-}
-
-int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen) {
- switch (pkt_numlen) {
- case 1:
- return *p;
- case 2:
- return (int64_t)ngtcp2_get_uint16(p);
- case 3:
- return (int64_t)ngtcp2_get_uint24(p);
- case 4:
- return (int64_t)ngtcp2_get_uint32(p);
- default:
- assert(0);
- }
-}
-
-uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n) {
- n = ngtcp2_htonl64(n);
- return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n) {
- n = ngtcp2_htonl64(n);
- return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 2, 6);
-}
-
-uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n) {
- n = ngtcp2_htonl(n);
- return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n) {
- n = ngtcp2_htonl(n);
- return ngtcp2_cpymem(p, ((const uint8_t *)&n) + 1, 3);
-}
-
-uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n) {
- n = ngtcp2_htons(n);
- return ngtcp2_cpymem(p, (const uint8_t *)&n, sizeof(n));
-}
-
-uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n) {
- uint8_t *rv;
- if (n < 64) {
- *p++ = (uint8_t)n;
- return p;
- }
- if (n < 16384) {
- rv = ngtcp2_put_uint16be(p, (uint16_t)n);
- *p |= 0x40;
- return rv;
- }
- if (n < 1073741824) {
- rv = ngtcp2_put_uint32be(p, (uint32_t)n);
- *p |= 0x80;
- return rv;
- }
- assert(n < 4611686018427387904ULL);
- rv = ngtcp2_put_uint64be(p, n);
- *p |= 0xc0;
- return rv;
-}
-
-uint8_t *ngtcp2_put_varint14(uint8_t *p, uint16_t n) {
- uint8_t *rv;
-
- assert(n < 16384);
-
- rv = ngtcp2_put_uint16be(p, n);
- *p |= 0x40;
-
- return rv;
-}
-
-uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len) {
- switch (len) {
- case 1:
- *p++ = (uint8_t)pkt_num;
- return p;
- case 2:
- ngtcp2_put_uint16be(p, (uint16_t)pkt_num);
- return p + 2;
- case 3:
- ngtcp2_put_uint24be(p, (uint32_t)pkt_num);
- return p + 3;
- case 4:
- ngtcp2_put_uint32be(p, (uint32_t)pkt_num);
- return p + 4;
- default:
- assert(0);
- }
-}
-
-size_t ngtcp2_get_varint_len(const uint8_t *p) { return 1u << (*p >> 6); }
-
-size_t ngtcp2_put_varint_len(uint64_t n) {
- if (n < 64) {
- return 1;
- }
- if (n < 16384) {
- return 2;
- }
- if (n < 1073741824) {
- return 4;
- }
- assert(n < 4611686018427387904ULL);
- return 8;
-}
-
-int64_t ngtcp2_nth_server_bidi_id(uint64_t n) {
- if (n == 0) {
- return 0;
- }
-
- if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
- return NGTCP2_MAX_SERVER_STREAM_ID_BIDI;
- }
-
- return (int64_t)(((n - 1) << 2) | 0x01);
-}
-
-int64_t ngtcp2_nth_client_bidi_id(uint64_t n) {
- if (n == 0) {
- return 0;
- }
-
- if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
- return NGTCP2_MAX_CLIENT_STREAM_ID_BIDI;
- }
-
- return (int64_t)((n - 1) << 2);
-}
-
-int64_t ngtcp2_nth_server_uni_id(uint64_t n) {
- if (n == 0) {
- return 0;
- }
-
- if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
- return NGTCP2_MAX_SERVER_STREAM_ID_UNI;
- }
-
- return (int64_t)(((n - 1) << 2) | 0x03);
-}
-
-int64_t ngtcp2_nth_client_uni_id(uint64_t n) {
- if (n == 0) {
- return 0;
- }
-
- if ((NGTCP2_MAX_VARINT >> 2) < n - 1) {
- return NGTCP2_MAX_CLIENT_STREAM_ID_UNI;
- }
-
- return (int64_t)(((n - 1) << 2) | 0x02);
-}
-
-uint64_t ngtcp2_ord_stream_id(int64_t stream_id) {
- return (uint64_t)(stream_id >> 2) + 1;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_conv.h b/deps/ngtcp2/lib/ngtcp2_conv.h
deleted file mode 100644
index 227470b919..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_conv.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CONV_H
-#define NGTCP2_CONV_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif /* HAVE_ARPA_INET_H */
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif /* HAVE_NETINET_IN_H */
-
-#ifdef HAVE_BYTESWAP_H
-# include <byteswap.h>
-#endif /* HAVE_BYTESWAP_H */
-
-#ifdef HAVE_ENDIAN_H
-# include <endian.h>
-#endif /* HAVE_ENDIAN_H */
-
-#ifdef HAVE_SYS_ENDIAN_H
-# include <sys/endian.h>
-#endif /* HAVE_SYS_ENDIAN_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#if defined HAVE_BSWAP_64 || HAVE_DECL_BSWAP_64
-# define ngtcp2_bswap64 bswap_64
-#else /* !HAVE_BSWAP_64 */
-# define ngtcp2_bswap64(N) \
- ((uint64_t)(ntohl((uint32_t)(N))) << 32 | ntohl((uint32_t)((N) >> 32)))
-#endif /* !HAVE_BSWAP_64 */
-
-#if defined HAVE_BE64TOH || HAVE_DECL_BE64TOH
-# define ngtcp2_ntohl64(N) be64toh(N)
-# define ngtcp2_htonl64(N) htobe64(N)
-#else /* !HAVE_BE64TOH */
-# if defined WORDS_BIGENDIAN
-# define ngtcp2_ntohl64(N) (N)
-# define ngtcp2_htonl64(N) (N)
-# else /* !WORDS_BIGENDIAN */
-# define ngtcp2_ntohl64(N) ngtcp2_bswap64(N)
-# define ngtcp2_htonl64(N) ngtcp2_bswap64(N)
-# endif /* !WORDS_BIGENDIAN */
-#endif /* !HAVE_BE64TOH */
-
-#if defined(WIN32)
-/* Windows requires ws2_32 library for ntonl family functions. We
- define inline functions for those function so that we don't have
- dependeny on that lib. */
-
-# ifdef _MSC_VER
-# define STIN static __inline
-# else
-# define STIN static inline
-# endif
-
-STIN uint32_t ngtcp2_htonl(uint32_t hostlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostlong >> 24;
- *p++ = (hostlong >> 16) & 0xffu;
- *p++ = (hostlong >> 8) & 0xffu;
- *p = hostlong & 0xffu;
- return res;
-}
-
-STIN uint16_t ngtcp2_htons(uint16_t hostshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&res;
- *p++ = hostshort >> 8;
- *p = hostshort & 0xffu;
- return res;
-}
-
-STIN uint32_t ngtcp2_ntohl(uint32_t netlong) {
- uint32_t res;
- unsigned char *p = (unsigned char *)&netlong;
- res = *p++ << 24;
- res += *p++ << 16;
- res += *p++ << 8;
- res += *p;
- return res;
-}
-
-STIN uint16_t ngtcp2_ntohs(uint16_t netshort) {
- uint16_t res;
- unsigned char *p = (unsigned char *)&netshort;
- res = *p++ << 8;
- res += *p;
- return res;
-}
-
-#else /* !WIN32 */
-
-# define ngtcp2_htonl htonl
-# define ngtcp2_htons htons
-# define ngtcp2_ntohl ntohl
-# define ngtcp2_ntohs ntohs
-
-#endif /* !WIN32 */
-
-/*
- * ngtcp2_get_uint64 reads 8 bytes from |p| as 64 bits unsigned
- * integer encoded as network byte order, and returns it in host byte
- * order.
- */
-uint64_t ngtcp2_get_uint64(const uint8_t *p);
-
-/*
- * ngtcp2_get_uint48 reads 6 bytes from |p| as 48 bits unsigned
- * integer encoded as network byte order, and returns it in host byte
- * order.
- */
-uint64_t ngtcp2_get_uint48(const uint8_t *p);
-
-/*
- * ngtcp2_get_uint32 reads 4 bytes from |p| as 32 bits unsigned
- * integer encoded as network byte order, and returns it in host byte
- * order.
- */
-uint32_t ngtcp2_get_uint32(const uint8_t *p);
-
-/*
- * ngtcp2_get_uint24 reads 3 bytes from |p| as 24 bits unsigned
- * integer encoded as network byte order, and returns it in host byte
- * order.
- */
-uint32_t ngtcp2_get_uint24(const uint8_t *p);
-
-/*
- * ngtcp2_get_uint16 reads 2 bytes from |p| as 16 bits unsigned
- * integer encoded as network byte order, and returns it in host byte
- * order.
- */
-uint16_t ngtcp2_get_uint16(const uint8_t *p);
-
-/*
- * ngtcp2_get_varint reads variable-length integer from |p|, and
- * returns it in host byte order. The number of bytes read is stored
- * in |*plen|.
- */
-uint64_t ngtcp2_get_varint(size_t *plen, const uint8_t *p);
-
-/*
- * ngtcp2_get_pkt_num reads encoded packet number from |p|. The
- * packet number is encoed in |pkt_numlen| bytes.
- */
-int64_t ngtcp2_get_pkt_num(const uint8_t *p, size_t pkt_numlen);
-
-/*
- * ngtcp2_put_uint64be writes |n| in host byte order in |p| in network
- * byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *ngtcp2_put_uint64be(uint8_t *p, uint64_t n);
-
-/*
- * ngtcp2_put_uint48be writes |n| in host byte order in |p| in network
- * byte order. It writes only least significant 48 bits. It returns
- * the one beyond of the last written position.
- */
-uint8_t *ngtcp2_put_uint48be(uint8_t *p, uint64_t n);
-
-/*
- * ngtcp2_put_uint32be writes |n| in host byte order in |p| in network
- * byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *ngtcp2_put_uint32be(uint8_t *p, uint32_t n);
-
-/*
- * ngtcp2_put_uint24be writes |n| in host byte order in |p| in network
- * byte order. It writes only least significant 24 bits. It returns
- * the one beyond of the last written position.
- */
-uint8_t *ngtcp2_put_uint24be(uint8_t *p, uint32_t n);
-
-/*
- * ngtcp2_put_uint16be writes |n| in host byte order in |p| in network
- * byte order. It returns the one beyond of the last written
- * position.
- */
-uint8_t *ngtcp2_put_uint16be(uint8_t *p, uint16_t n);
-
-/*
- * ngtcp2_put_varint writes |n| in |p| using variable-length integer
- * encoding. It returns the one beyond of the last written position.
- */
-uint8_t *ngtcp2_put_varint(uint8_t *p, uint64_t n);
-
-/*
- * ngtcp2_put_varint14 writes |n| in |p| using variable-length integer
- * encoding. |n| must be strictly less than 16384. The function
- * always encodes |n| in 2 bytes. It returns the one beyond of the
- * last written position.
- */
-uint8_t *ngtcp2_put_varint14(uint8_t *p, uint16_t n);
-
-/*
- * ngtcp2_put_pkt_num encodes |pkt_num| using |len| bytes. It
- * returns the one beyond of the last written position.
- */
-uint8_t *ngtcp2_put_pkt_num(uint8_t *p, int64_t pkt_num, size_t len);
-
-/*
- * ngtcp2_get_varint_len returns the required number of bytes to read
- * variable-length integer starting at |p|.
- */
-size_t ngtcp2_get_varint_len(const uint8_t *p);
-
-/*
- * ngtcp2_put_varint_len returns the required number of bytes to
- * encode |n|.
- */
-size_t ngtcp2_put_varint_len(uint64_t n);
-
-/*
- * ngtcp2_nth_server_bidi_id returns |n|-th server bidirectional
- * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is
- * larger than NGTCP2_MAX_SERVER_STREAM_ID_BIDI, this function returns
- * NGTCP2_MAX_SERVER_STREAM_ID_BIDI.
- */
-int64_t ngtcp2_nth_server_bidi_id(uint64_t n);
-
-/*
- * ngtcp2_nth_client_bidi_id returns |n|-th client bidirectional
- * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is
- * larger than NGTCP2_MAX_CLIENT_STREAM_ID_BIDI, this function returns
- * NGTCP2_MAX_CLIENT_STREAM_ID_BIDI.
- */
-int64_t ngtcp2_nth_client_bidi_id(uint64_t n);
-
-/*
- * ngtcp2_nth_server_uni_id returns |n|-th server unidirectional
- * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is
- * larger than NGTCP2_MAX_SERVER_STREAM_ID_UNI, this function returns
- * NGTCP2_MAX_SERVER_STREAM_ID_UNI.
- */
-int64_t ngtcp2_nth_server_uni_id(uint64_t n);
-
-/*
- * ngtcp2_nth_client_uni_id returns |n|-th client unidirectional
- * stream ID. If |n| is 0, it returns 0. If the |n|-th stream ID is
- * larger than NGTCP2_MAX_CLIENT_STREAM_ID_UNI, this function returns
- * NGTCP2_MAX_CLIENT_STREAM_ID_UNI.
- */
-int64_t ngtcp2_nth_client_uni_id(uint64_t n);
-
-/*
- * ngtcp2_ord_stream_id returns the ordinal number of |stream_id|.
- */
-uint64_t ngtcp2_ord_stream_id(int64_t stream_id);
-
-#endif /* NGTCP2_CONV_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/lib/ngtcp2_crypto.c
deleted file mode 100644
index 5cfe145ec9..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_crypto.c
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_crypto.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_str.h"
-#include "ngtcp2_conv.h"
-#include "ngtcp2_conn.h"
-
-int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
- size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen,
- const ngtcp2_mem *mem) {
- int rv = ngtcp2_crypto_km_nocopy_new(pckm, secretlen, ivlen, mem);
- if (rv != 0) {
- return rv;
- }
-
- if (secretlen) {
- memcpy((*pckm)->secret.base, secret, secretlen);
- }
- if (aead_ctx) {
- (*pckm)->aead_ctx = *aead_ctx;
- }
- memcpy((*pckm)->iv.base, iv, ivlen);
-
- return 0;
-}
-
-int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
- size_t ivlen, const ngtcp2_mem *mem) {
- size_t len;
- uint8_t *p;
-
- len = sizeof(ngtcp2_crypto_km) + secretlen + ivlen;
-
- *pckm = ngtcp2_mem_malloc(mem, len);
- if (*pckm == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km);
- (*pckm)->secret.base = p;
- (*pckm)->secret.len = secretlen;
- p += secretlen;
- (*pckm)->iv.base = p;
- (*pckm)->iv.len = ivlen;
- (*pckm)->aead_ctx.native_handle = NULL;
- (*pckm)->pkt_num = -1;
- (*pckm)->use_count = 0;
- (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
-
- return 0;
-}
-
-void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) {
- if (ckm == NULL) {
- return;
- }
-
- ngtcp2_mem_free(mem, ckm);
-}
-
-void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
- int64_t pkt_num) {
- size_t i;
- uint64_t n;
-
- memcpy(dest, iv, ivlen);
- n = ngtcp2_htonl64((uint64_t)pkt_num);
-
- for (i = 0; i < 8; ++i) {
- dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i];
- }
-}
-
-/*
- * varint_paramlen returns the length of a single transport parameter
- * which has variable integer in its parameter.
- */
-static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
- size_t valuelen = ngtcp2_put_varint_len(param);
- return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(valuelen) + valuelen;
-}
-
-/*
- * write_varint_param writes parameter |id| of the given |value| in
- * varint encoding. It returns p + the number of bytes written.
- */
-static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
- uint64_t value) {
- p = ngtcp2_put_varint(p, id);
- p = ngtcp2_put_varint(p, ngtcp2_put_varint_len(value));
- return ngtcp2_put_varint(p, value);
-}
-
-/*
- * cid_paramlen returns the length of a single transport parameter
- * which has |cid| as value.
- */
-static size_t cid_paramlen(ngtcp2_transport_param_id id,
- const ngtcp2_cid *cid) {
- return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(cid->datalen) +
- cid->datalen;
-}
-
-/*
- * write_cid_param writes parameter |id| of the given |cid|. It
- * returns p + the number of bytes written.
- */
-static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
- const ngtcp2_cid *cid) {
- assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
- assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
-
- p = ngtcp2_put_varint(p, id);
- p = ngtcp2_put_varint(p, cid->datalen);
- if (cid->datalen) {
- p = ngtcp2_cpymem(p, cid->data, cid->datalen);
- }
- return p;
-}
-
-ngtcp2_ssize
-ngtcp2_encode_transport_params(uint8_t *dest, size_t destlen,
- ngtcp2_transport_params_type exttype,
- const ngtcp2_transport_params *params) {
- uint8_t *p;
- size_t len = 0;
- /* For some reason, gcc 7.3.0 requires this initialization. */
- size_t preferred_addrlen = 0;
-
- switch (exttype) {
- case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO:
- break;
- case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS:
- len +=
- cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
- &params->original_dcid);
-
- if (params->stateless_reset_token_present) {
- len +=
- ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
- ngtcp2_put_varint_len(NGTCP2_STATELESS_RESET_TOKENLEN) +
- NGTCP2_STATELESS_RESET_TOKENLEN;
- }
- if (params->preferred_address_present) {
- assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN);
- assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN);
- preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
- 16 /* ipv6Address */ + 2 /* ipv6Port */
- + 1 +
- params->preferred_address.cid.datalen /* CID */ +
- NGTCP2_STATELESS_RESET_TOKENLEN;
- len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
- ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen;
- }
- if (params->retry_scid_present) {
- len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
- &params->retry_scid);
- }
- break;
- default:
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
- &params->initial_scid);
-
- if (params->initial_max_stream_data_bidi_local) {
- len += varint_paramlen(
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
- params->initial_max_stream_data_bidi_local);
- }
- if (params->initial_max_stream_data_bidi_remote) {
- len += varint_paramlen(
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
- params->initial_max_stream_data_bidi_remote);
- }
- if (params->initial_max_stream_data_uni) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
- params->initial_max_stream_data_uni);
- }
- if (params->initial_max_data) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
- params->initial_max_data);
- }
- if (params->initial_max_streams_bidi) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
- params->initial_max_streams_bidi);
- }
- if (params->initial_max_streams_uni) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
- params->initial_max_streams_uni);
- }
- if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
- params->max_udp_payload_size);
- }
- if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
- params->ack_delay_exponent);
- }
- if (params->disable_active_migration) {
- len +=
- ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION) +
- ngtcp2_put_varint_len(0);
- }
- if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
- params->max_ack_delay / NGTCP2_MILLISECONDS);
- }
- if (params->max_idle_timeout) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
- params->max_idle_timeout / NGTCP2_MILLISECONDS);
- }
- if (params->active_connection_id_limit &&
- params->active_connection_id_limit !=
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
- len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
- params->active_connection_id_limit);
- }
-
- if (destlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = dest;
-
- if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- p = write_cid_param(
- p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
- &params->original_dcid);
-
- if (params->stateless_reset_token_present) {
- p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
- p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token));
- p = ngtcp2_cpymem(p, params->stateless_reset_token,
- sizeof(params->stateless_reset_token));
- }
- if (params->preferred_address_present) {
- p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
- p = ngtcp2_put_varint(p, preferred_addrlen);
-
- p = ngtcp2_cpymem(p, params->preferred_address.ipv4_addr,
- sizeof(params->preferred_address.ipv4_addr));
- p = ngtcp2_put_uint16be(p, params->preferred_address.ipv4_port);
-
- p = ngtcp2_cpymem(p, params->preferred_address.ipv6_addr,
- sizeof(params->preferred_address.ipv6_addr));
- p = ngtcp2_put_uint16be(p, params->preferred_address.ipv6_port);
-
- *p++ = (uint8_t)params->preferred_address.cid.datalen;
- if (params->preferred_address.cid.datalen) {
- p = ngtcp2_cpymem(p, params->preferred_address.cid.data,
- params->preferred_address.cid.datalen);
- }
- p = ngtcp2_cpymem(
- p, params->preferred_address.stateless_reset_token,
- sizeof(params->preferred_address.stateless_reset_token));
- }
- if (params->retry_scid_present) {
- p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
- &params->retry_scid);
- }
- }
-
- p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
- &params->initial_scid);
-
- if (params->initial_max_stream_data_bidi_local) {
- p = write_varint_param(
- p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
- params->initial_max_stream_data_bidi_local);
- }
-
- if (params->initial_max_stream_data_bidi_remote) {
- p = write_varint_param(
- p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
- params->initial_max_stream_data_bidi_remote);
- }
-
- if (params->initial_max_stream_data_uni) {
- p = write_varint_param(p,
- NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
- params->initial_max_stream_data_uni);
- }
-
- if (params->initial_max_data) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
- params->initial_max_data);
- }
-
- if (params->initial_max_streams_bidi) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
- params->initial_max_streams_bidi);
- }
-
- if (params->initial_max_streams_uni) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
- params->initial_max_streams_uni);
- }
-
- if (params->max_udp_payload_size != NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
- params->max_udp_payload_size);
- }
-
- if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
- params->ack_delay_exponent);
- }
-
- if (params->disable_active_migration) {
- p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
- p = ngtcp2_put_varint(p, 0);
- }
-
- if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
- params->max_ack_delay / NGTCP2_MILLISECONDS);
- }
-
- if (params->max_idle_timeout) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
- params->max_idle_timeout / NGTCP2_MILLISECONDS);
- }
-
- if (params->active_connection_id_limit &&
- params->active_connection_id_limit !=
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
- p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
- params->active_connection_id_limit);
- }
-
- assert((size_t)(p - dest) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-/*
- * decode_varint decodes a single varint from the buffer pointed by
- * |p| of length |end - p|. If it decodes an integer successfully, it
- * stores the integer in |*pdest| and returns 0. Otherwise it returns
- * -1.
- */
-static ngtcp2_ssize decode_varint(uint64_t *pdest, const uint8_t *p,
- const uint8_t *end) {
- size_t len;
-
- if (p == end) {
- return -1;
- }
-
- len = ngtcp2_get_varint_len(p);
- if ((uint64_t)(end - p) < len) {
- return -1;
- }
-
- *pdest = ngtcp2_get_varint(&len, p);
-
- return (ngtcp2_ssize)len;
-}
-
-/*
- * decode_varint_param decodes length prefixed value from the buffer
- * pointed by |p| of length |end - p|. The length and value are
- * encoded in varint form. If it decodes a value successfully, it
- * stores the value in |*pdest| and returns 0. Otherwise it returns
- * -1.
- */
-static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p,
- const uint8_t *end) {
- const uint8_t *begin = p;
- ngtcp2_ssize nread;
- uint64_t valuelen;
- size_t n;
-
- nread = decode_varint(&valuelen, p, end);
- if (nread < 0) {
- return -1;
- }
-
- p += nread;
-
- if (p == end) {
- return -1;
- }
-
- if ((uint64_t)(end - p) < valuelen) {
- return -1;
- }
-
- if (ngtcp2_get_varint_len(p) != valuelen) {
- return -1;
- }
-
- *pdest = ngtcp2_get_varint(&n, p);
-
- p += valuelen;
-
- return (ngtcp2_ssize)(p - begin);
-}
-
-/*
- * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
- * pointed by |p| of length |end - p|. The length is encoded in
- * varint form. If it decodes a value successfully, it stores the
- * value in |*pdest| and returns the number of bytes read. Otherwise
- * it returns -1.
- */
-static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p,
- const uint8_t *end) {
- const uint8_t *begin = p;
- uint64_t valuelen;
- ngtcp2_ssize nread = decode_varint(&valuelen, p, end);
-
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- p += nread;
-
- if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
- valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- ngtcp2_cid_init(pdest, p, (size_t)valuelen);
-
- p += valuelen;
-
- return (ngtcp2_ssize)(p - begin);
-}
-
-int ngtcp2_decode_transport_params(ngtcp2_transport_params *params,
- ngtcp2_transport_params_type exttype,
- const uint8_t *data, size_t datalen) {
- const uint8_t *p, *end;
- size_t len;
- uint64_t param_type;
- uint64_t valuelen;
- ngtcp2_ssize nread;
- int initial_scid_present = 0;
- int original_dcid_present = 0;
-
- p = data;
- end = data + datalen;
-
- /* Set default values */
- memset(params, 0, sizeof(*params));
- params->initial_max_streams_bidi = 0;
- params->initial_max_streams_uni = 0;
- params->initial_max_stream_data_bidi_local = 0;
- params->initial_max_stream_data_bidi_remote = 0;
- params->initial_max_stream_data_uni = 0;
- params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE;
- params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
- params->stateless_reset_token_present = 0;
- params->preferred_address_present = 0;
- params->disable_active_migration = 0;
- params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
- params->max_idle_timeout = 0;
- params->active_connection_id_limit =
- NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
- params->retry_scid_present = 0;
- memset(&params->retry_scid, 0, sizeof(params->retry_scid));
- memset(&params->initial_scid, 0, sizeof(params->initial_scid));
- memset(&params->original_dcid, 0, sizeof(params->original_dcid));
-
- if (datalen == 0) {
- return 0;
- }
-
- for (; (size_t)(end - p) >= 2;) {
- nread = decode_varint(&param_type, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
-
- switch (param_type) {
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
- nread = decode_varint_param(&params->initial_max_stream_data_bidi_local,
- p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
- nread = decode_varint_param(&params->initial_max_stream_data_bidi_remote,
- p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
- nread = decode_varint_param(&params->initial_max_stream_data_uni, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
- nread = decode_varint_param(&params->initial_max_data, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
- nread = decode_varint_param(&params->initial_max_streams_bidi, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
- nread = decode_varint_param(&params->initial_max_streams_uni, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
- return NGTCP2_ERR_STREAM_LIMIT;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
- nread = decode_varint_param(&params->max_idle_timeout, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->max_idle_timeout *= NGTCP2_MILLISECONDS;
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
- nread = decode_varint_param(&params->max_udp_payload_size, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
- if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- nread = decode_varint(&valuelen, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- memcpy(params->stateless_reset_token, p,
- sizeof(params->stateless_reset_token));
- params->stateless_reset_token_present = 1;
-
- p += sizeof(params->stateless_reset_token);
- break;
- case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
- nread = decode_varint_param(&params->ack_delay_exponent, p, end);
- if (nread < 0 || params->ack_delay_exponent > 20) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
- if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- nread = decode_varint(&valuelen, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- if ((size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
- 2 /* ipv6Port */
- + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
- if (valuelen < len) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- memcpy(params->preferred_address.ipv4_addr, p,
- sizeof(params->preferred_address.ipv4_addr));
- p += sizeof(params->preferred_address.ipv4_addr);
- params->preferred_address.ipv4_port = ngtcp2_get_uint16(p);
- p += sizeof(uint16_t);
-
- memcpy(params->preferred_address.ipv6_addr, p,
- sizeof(params->preferred_address.ipv6_addr));
- p += sizeof(params->preferred_address.ipv6_addr);
- params->preferred_address.ipv6_port = ngtcp2_get_uint16(p);
- p += sizeof(uint16_t);
-
- /* cid */
- params->preferred_address.cid.datalen = *p++;
- len += params->preferred_address.cid.datalen;
- if (valuelen != len ||
- params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN ||
- params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- if (params->preferred_address.cid.datalen) {
- memcpy(params->preferred_address.cid.data, p,
- params->preferred_address.cid.datalen);
- p += params->preferred_address.cid.datalen;
- }
-
- /* stateless reset token */
- memcpy(params->preferred_address.stateless_reset_token, p,
- sizeof(params->preferred_address.stateless_reset_token));
- p += sizeof(params->preferred_address.stateless_reset_token);
- params->preferred_address_present = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
- nread = decode_varint(&valuelen, p, end);
- if (nread < 0 || valuelen != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- params->disable_active_migration = 1;
- break;
- case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
- if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- nread = decode_cid_param(&params->original_dcid, p, end);
- if (nread < 0) {
- return (int)nread;
- }
- original_dcid_present = 1;
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
- if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- nread = decode_cid_param(&params->retry_scid, p, end);
- if (nread < 0) {
- return (int)nread;
- }
- params->retry_scid_present = 1;
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
- nread = decode_cid_param(&params->initial_scid, p, end);
- if (nread < 0) {
- return (int)nread;
- }
- initial_scid_present = 1;
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
- nread = decode_varint_param(&params->max_ack_delay, p, end);
- if (nread < 0 || params->max_ack_delay >= 16384) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- params->max_ack_delay *= NGTCP2_MILLISECONDS;
- p += nread;
- break;
- case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
- nread = decode_varint_param(&params->active_connection_id_limit, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- break;
- default:
- /* Ignore unknown parameter */
- nread = decode_varint(&valuelen, p, end);
- if (nread < 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += nread;
- if ((size_t)(end - p) < valuelen) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
- p += valuelen;
- break;
- }
- }
-
- if (end - p != 0) {
- return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
- }
-
- if (!initial_scid_present ||
- (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS &&
- !original_dcid_present)) {
- return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
- }
-
- return 0;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_crypto.h b/deps/ngtcp2/lib/ngtcp2_crypto.h
deleted file mode 100644
index b1baf30a85..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_crypto.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_CRYPTO_H
-#define NGTCP2_CRYPTO_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-
-/* NGTCP2_INITIAL_AEAD_OVERHEAD is an overhead of AEAD used by Initial
- packets. Because QUIC uses AEAD_AES_128_GCM, the overhead is 16
- bytes. */
-#define NGTCP2_INITIAL_AEAD_OVERHEAD 16
-
-/* NGTCP2_MAX_AEAD_OVERHEAD is expected maximum AEAD overhead. */
-#define NGTCP2_MAX_AEAD_OVERHEAD 16
-
-typedef enum {
- NGTCP2_CRYPTO_KM_FLAG_NONE,
- /* NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE is set if key phase bit is
- set. */
- NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE = 0x01,
-} ngtcp2_crypto_km_flag;
-
-typedef struct {
- ngtcp2_vec secret;
- ngtcp2_crypto_aead_ctx aead_ctx;
- ngtcp2_vec iv;
- /* pkt_num is a packet number of a packet which uses this keying
- material. For encryption key, it is the lowest packet number of
- a packet. For decryption key, it is the lowest packet number of
- a packet which can be decrypted with this keying material. */
- int64_t pkt_num;
- /* use_count is the number of encryption or decryption failure. For
- tx key, this is the number of encryption. For rx key, this is
- the number of decryption failure. */
- uint64_t use_count;
- /* flags is the bitwise OR of zero or more of
- ngtcp2_crypto_km_flag. */
- uint8_t flags;
-} ngtcp2_crypto_km;
-
-/*
- * ngtcp2_crypto_km_new creates new ngtcp2_crypto_km object and
- * assigns its pointer to |*pckm|. The |secret| of length
- * |secretlen|, the |key| of length |keylen| and the |iv| of length
- * |ivlen| are copied to |*pckm|. If |secretlen| == 0, the function
- * assumes no secret is given which is acceptable. The sole reason to
- * store secret is update keys. Only 1RTT key can be updated.
- */
-int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
- size_t secretlen,
- const ngtcp2_crypto_aead_ctx *aead_ctx,
- const uint8_t *iv, size_t ivlen,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_crypto_km_nocopy_new is similar to ngtcp2_crypto_km_new, but
- * it does not copy secret, key and IV.
- */
-int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
- size_t ivlen, const ngtcp2_mem *mem);
-
-void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem);
-
-typedef struct {
- ngtcp2_crypto_aead aead;
- ngtcp2_crypto_cipher hp;
- ngtcp2_crypto_km *ckm;
- ngtcp2_crypto_cipher_ctx hp_ctx;
- size_t aead_overhead;
- ngtcp2_encrypt encrypt;
- ngtcp2_decrypt decrypt;
- ngtcp2_hp_mask hp_mask;
-} ngtcp2_crypto_cc;
-
-void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
- int64_t pkt_num);
-
-#endif /* NGTCP2_CRYPTO_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_err.c b/deps/ngtcp2/lib/ngtcp2_err.c
deleted file mode 100644
index 5a2425367d..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_err.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_err.h"
-
-const char *ngtcp2_strerror(int liberr) {
- switch (liberr) {
- case 0:
- return "NO_ERROR";
- case NGTCP2_ERR_INVALID_ARGUMENT:
- return "ERR_INVALID_ARGUMENT";
- case NGTCP2_ERR_UNKNOWN_PKT_TYPE:
- return "ERR_UNKNOWN_PKT_TYPE";
- case NGTCP2_ERR_NOBUF:
- return "ERR_NOBUF";
- case NGTCP2_ERR_PROTO:
- return "ERR_PROTO";
- case NGTCP2_ERR_INVALID_STATE:
- return "ERR_INVALID_STATE";
- case NGTCP2_ERR_ACK_FRAME:
- return "ERR_ACK_FRAME";
- case NGTCP2_ERR_STREAM_ID_BLOCKED:
- return "ERR_STREAM_ID_BLOCKED";
- case NGTCP2_ERR_STREAM_IN_USE:
- return "ERR_STREAM_IN_USE";
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
- return "ERR_STREAM_DATA_BLOCKED";
- case NGTCP2_ERR_FLOW_CONTROL:
- return "ERR_FLOW_CONTROL";
- case NGTCP2_ERR_CONNECTION_ID_LIMIT:
- return "ERR_CONNECTION_ID_LIMIT";
- case NGTCP2_ERR_STREAM_LIMIT:
- return "ERR_STREAM_LIMIT";
- case NGTCP2_ERR_FINAL_SIZE:
- return "ERR_FINAL_SIZE";
- case NGTCP2_ERR_CRYPTO:
- return "ERR_CRYPTO";
- case NGTCP2_ERR_PKT_NUM_EXHAUSTED:
- return "ERR_PKT_NUM_EXHAUSTED";
- case NGTCP2_ERR_NOMEM:
- return "ERR_NOMEM";
- case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
- return "ERR_REQUIRED_TRANSPORT_PARAM";
- case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
- return "ERR_MALFORMED_TRANSPORT_PARAM";
- case NGTCP2_ERR_FRAME_ENCODING:
- return "ERR_FRAME_ENCODING";
- case NGTCP2_ERR_TLS_DECRYPT:
- return "ERR_TLS_DECRYPT";
- case NGTCP2_ERR_STREAM_SHUT_WR:
- return "ERR_STREAM_SHUT_WR";
- case NGTCP2_ERR_STREAM_NOT_FOUND:
- return "ERR_STREAM_NOT_FOUND";
- case NGTCP2_ERR_STREAM_STATE:
- return "ERR_STREAM_STATE";
- case NGTCP2_ERR_RECV_VERSION_NEGOTIATION:
- return "ERR_RECV_VERSION_NEGOTIATION";
- case NGTCP2_ERR_CLOSING:
- return "ERR_CLOSING";
- case NGTCP2_ERR_DRAINING:
- return "ERR_DRAINING";
- case NGTCP2_ERR_TRANSPORT_PARAM:
- return "ERR_TRANSPORT_PARAM";
- case NGTCP2_ERR_DISCARD_PKT:
- return "ERR_DISCARD_PKT";
- case NGTCP2_ERR_PATH_VALIDATION_FAILED:
- return "ERR_PATH_VALIDATION_FAILED";
- case NGTCP2_ERR_CONN_ID_BLOCKED:
- return "ERR_CONN_ID_BLOCKED";
- case NGTCP2_ERR_CALLBACK_FAILURE:
- return "ERR_CALLBACK_FAILURE";
- case NGTCP2_ERR_INTERNAL:
- return "ERR_INTERNAL";
- case NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED:
- return "ERR_CRYPTO_BUFFER_EXCEEDED";
- case NGTCP2_ERR_WRITE_MORE:
- return "ERR_WRITE_MORE";
- case NGTCP2_ERR_RETRY:
- return "ERR_RETRY";
- case NGTCP2_ERR_DROP_CONN:
- return "ERR_DROP_CONN";
- default:
- return "(unknown)";
- }
-}
-
-int ngtcp2_err_is_fatal(int liberr) { return liberr < NGTCP2_ERR_FATAL; }
-
-uint64_t ngtcp2_err_infer_quic_transport_error_code(int liberr) {
- switch (liberr) {
- case 0:
- return NGTCP2_NO_ERROR;
- case NGTCP2_ERR_ACK_FRAME:
- case NGTCP2_ERR_FRAME_ENCODING:
- return NGTCP2_FRAME_ENCODING_ERROR;
- case NGTCP2_ERR_FLOW_CONTROL:
- return NGTCP2_FLOW_CONTROL_ERROR;
- case NGTCP2_ERR_CONNECTION_ID_LIMIT:
- return NGTCP2_CONNECTION_ID_LIMIT_ERROR;
- case NGTCP2_ERR_STREAM_LIMIT:
- return NGTCP2_STREAM_LIMIT_ERROR;
- case NGTCP2_ERR_FINAL_SIZE:
- return NGTCP2_FINAL_SIZE_ERROR;
- case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
- case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
- case NGTCP2_ERR_TRANSPORT_PARAM:
- return NGTCP2_TRANSPORT_PARAMETER_ERROR;
- case NGTCP2_ERR_INVALID_ARGUMENT:
- return NGTCP2_INTERNAL_ERROR;
- case NGTCP2_ERR_STREAM_STATE:
- return NGTCP2_STREAM_STATE_ERROR;
- case NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED:
- return NGTCP2_CRYPTO_BUFFER_EXCEEDED;
- default:
- return NGTCP2_PROTOCOL_VIOLATION;
- }
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_err.h b/deps/ngtcp2/lib/ngtcp2_err.h
deleted file mode 100644
index 9229f5425a..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_err.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_ERR_H
-#define NGTCP2_ERR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#endif /* NGTCP2_ERR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_gaptr.c b/deps/ngtcp2/lib/ngtcp2_gaptr.c
deleted file mode 100644
index 6e7f3b7e55..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_gaptr.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_gaptr.h"
-#include "ngtcp2_range.h"
-
-#include <string.h>
-#include <assert.h>
-
-int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem) {
- int rv;
- ngtcp2_range range = {0, UINT64_MAX};
-
- rv = ngtcp2_ksl_init(&gaptr->gap, ngtcp2_ksl_range_compar,
- sizeof(ngtcp2_range), mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_ksl_insert(&gaptr->gap, NULL, &range, NULL);
- if (rv != 0) {
- ngtcp2_ksl_free(&gaptr->gap);
- return rv;
- }
-
- gaptr->mem = mem;
-
- return 0;
-}
-
-void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr) {
- if (gaptr == NULL) {
- return;
- }
-
- ngtcp2_ksl_free(&gaptr->gap);
-}
-
-int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, size_t datalen) {
- int rv;
- ngtcp2_range k, m, l, r, q = {offset, offset + datalen};
- ngtcp2_ksl_it it;
-
- it = ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q,
- ngtcp2_ksl_range_exclusive_compar);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
- m = ngtcp2_range_intersect(&q, &k);
- if (!ngtcp2_range_len(&m)) {
- break;
- }
-
- if (ngtcp2_range_eq(&k, &m)) {
- ngtcp2_ksl_remove(&gaptr->gap, &it, &k);
- continue;
- }
- ngtcp2_range_cut(&l, &r, &k, &m);
- if (ngtcp2_range_len(&l)) {
- ngtcp2_ksl_update_key(&gaptr->gap, &k, &l);
-
- if (ngtcp2_range_len(&r)) {
- rv = ngtcp2_ksl_insert(&gaptr->gap, &it, &r, NULL);
- if (rv != 0) {
- return rv;
- }
- }
- } else if (ngtcp2_range_len(&r)) {
- ngtcp2_ksl_update_key(&gaptr->gap, &k, &r);
- }
- ngtcp2_ksl_it_next(&it);
- }
- return 0;
-}
-
-uint64_t ngtcp2_gaptr_first_gap_offset(ngtcp2_gaptr *gaptr) {
- ngtcp2_ksl_it it = ngtcp2_ksl_begin(&gaptr->gap);
- ngtcp2_range r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
- return r.begin;
-}
-
-ngtcp2_ksl_it ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr,
- uint64_t offset) {
- ngtcp2_range q = {offset, offset + 1};
- return ngtcp2_ksl_lower_bound_compar(&gaptr->gap, &q,
- ngtcp2_ksl_range_exclusive_compar);
-}
-
-int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
- size_t datalen) {
- ngtcp2_range q = {offset, offset + datalen};
- ngtcp2_ksl_it it = ngtcp2_ksl_lower_bound_compar(
- &gaptr->gap, &q, ngtcp2_ksl_range_exclusive_compar);
- ngtcp2_range k = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
- ngtcp2_range m = ngtcp2_range_intersect(&q, &k);
- return ngtcp2_range_len(&m) == 0;
-}
-
-void ngtcp2_gaptr_drop_first_gap(ngtcp2_gaptr *gaptr) {
- ngtcp2_ksl_it it = ngtcp2_ksl_begin(&gaptr->gap);
- ngtcp2_range r;
-
- assert(!ngtcp2_ksl_it_end(&it));
-
- r = *(ngtcp2_range *)ngtcp2_ksl_it_key(&it);
-
- ngtcp2_ksl_remove(&gaptr->gap, NULL, &r);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_gaptr.h b/deps/ngtcp2/lib/ngtcp2_gaptr.h
deleted file mode 100644
index 9e7fa03086..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_gaptr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_GAPTR_H
-#define NGTCP2_GAPTR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_ksl.h"
-
-/*
- * ngtcp2_gaptr maintains the gap in the range [0, UINT64_MAX).
- */
-typedef struct {
- /* gap maintains the range of offset which is not received
- yet. Initially, its range is [0, UINT64_MAX). */
- ngtcp2_ksl gap;
- /* mem is custom memory allocator */
- const ngtcp2_mem *mem;
-} ngtcp2_gaptr;
-
-/*
- * ngtcp2_gaptr_init initializes |gaptr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_gaptr_init(ngtcp2_gaptr *gaptr, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_gaptr_free frees resources allocated for |gaptr|.
- */
-void ngtcp2_gaptr_free(ngtcp2_gaptr *gaptr);
-
-/*
- * ngtcp2_gaptr_push adds new data of length |datalen| at the stream
- * offset |offset|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_gaptr_push(ngtcp2_gaptr *gaptr, uint64_t offset, size_t datalen);
-
-/*
- * ngtcp2_gaptr_first_gap_offset returns the offset to the first gap.
- * If there is no gap, it returns UINT64_MAX.
- */
-uint64_t ngtcp2_gaptr_first_gap_offset(ngtcp2_gaptr *gaptr);
-
-/*
- * ngtcp2_gaptr_get_first_gap_after returns the iterator pointing to
- * the first gap which overlaps or comes after |offset|.
- */
-ngtcp2_ksl_it ngtcp2_gaptr_get_first_gap_after(ngtcp2_gaptr *gaptr,
- uint64_t offset);
-
-/*
- * ngtcp2_gaptr_is_pushed returns nonzero if range [offset, offset +
- * datalen) is completely pushed into this object.
- */
-int ngtcp2_gaptr_is_pushed(ngtcp2_gaptr *gaptr, uint64_t offset,
- size_t datalen);
-
-/*
- * ngtcp2_gaptr_drop_first_gap deletes the first gap entirely as if
- * the range is pushed. This function assumes that at least one gap
- * exists.
- */
-void ngtcp2_gaptr_drop_first_gap(ngtcp2_gaptr *gaptr);
-
-#endif /* NGTCP2_GAPTR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_idtr.c b/deps/ngtcp2/lib/ngtcp2_idtr.c
deleted file mode 100644
index f04806b4a8..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_idtr.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_idtr.h"
-
-#include <assert.h>
-
-int ngtcp2_idtr_init(ngtcp2_idtr *idtr, int server, const ngtcp2_mem *mem) {
- int rv;
-
- rv = ngtcp2_gaptr_init(&idtr->gap, mem);
- if (rv != 0) {
- return rv;
- }
-
- idtr->server = server;
-
- return 0;
-}
-
-void ngtcp2_idtr_free(ngtcp2_idtr *idtr) {
- if (idtr == NULL) {
- return;
- }
-
- ngtcp2_gaptr_free(&idtr->gap);
-}
-
-/*
- * id_from_stream_id translates |stream_id| to id space used by
- * ngtcp2_idtr.
- */
-static uint64_t id_from_stream_id(int64_t stream_id) {
- return (uint64_t)(stream_id >> 2);
-}
-
-int ngtcp2_idtr_open(ngtcp2_idtr *idtr, int64_t stream_id) {
- uint64_t q;
-
- assert((idtr->server && (stream_id % 2)) ||
- (!idtr->server && (stream_id % 2)) == 0);
-
- q = id_from_stream_id(stream_id);
-
- if (ngtcp2_gaptr_is_pushed(&idtr->gap, q, 1)) {
- return NGTCP2_ERR_STREAM_IN_USE;
- }
-
- return ngtcp2_gaptr_push(&idtr->gap, q, 1);
-}
-
-int ngtcp2_idtr_is_open(ngtcp2_idtr *idtr, int64_t stream_id) {
- uint64_t q;
-
- assert((idtr->server && (stream_id % 2)) ||
- (!idtr->server && (stream_id % 2)) == 0);
-
- q = id_from_stream_id(stream_id);
-
- return ngtcp2_gaptr_is_pushed(&idtr->gap, q, 1);
-}
-
-uint64_t ngtcp2_idtr_first_gap(ngtcp2_idtr *idtr) {
- return ngtcp2_gaptr_first_gap_offset(&idtr->gap);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_idtr.h b/deps/ngtcp2/lib/ngtcp2_idtr.h
deleted file mode 100644
index 63f332e64f..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_idtr.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_IDTR_H
-#define NGTCP2_IDTR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_gaptr.h"
-
-/*
- * ngtcp2_idtr tracks the usage of stream ID.
- */
-typedef struct {
- /* gap maintains the range of ID which is not used yet. Initially,
- its range is [0, UINT64_MAX). */
- ngtcp2_gaptr gap;
- /* server is nonzero if this object records server initiated stream
- ID. */
- int server;
-} ngtcp2_idtr;
-
-/*
- * ngtcp2_idtr_init initializes |idtr|.
- *
- * If this object records server initiated ID (even number), set
- * |server| to nonzero.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_idtr_init(ngtcp2_idtr *idtr, int server, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_idtr_free frees resources allocated for |idtr|.
- */
-void ngtcp2_idtr_free(ngtcp2_idtr *idtr);
-
-/*
- * ngtcp2_idtr_open claims that |stream_id| is in used.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_STREAM_IN_USE
- * ID has already been used.
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_idtr_open(ngtcp2_idtr *idtr, int64_t stream_id);
-
-/*
- * ngtcp2_idtr_open tells whether ID |stream_id| is in used or not.
- *
- * It returns nonzero if |stream_id| is used.
- */
-int ngtcp2_idtr_is_open(ngtcp2_idtr *idtr, int64_t stream_id);
-
-/*
- * ngtcp2_idtr_first_gap returns the first id of first gap. If there
- * is no gap, it returns UINT64_MAX. The returned id is an id space
- * used in this object internally, and not stream ID.
- */
-uint64_t ngtcp2_idtr_first_gap(ngtcp2_idtr *idtr);
-
-#endif /* NGTCP2_IDTR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_ksl.c b/deps/ngtcp2/lib/ngtcp2_ksl.c
deleted file mode 100644
index 0c47150cb1..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ksl.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_ksl.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "ngtcp2_macro.h"
-#include "ngtcp2_mem.h"
-#include "ngtcp2_range.h"
-
-static size_t ksl_nodelen(size_t keylen) {
- return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0xf) &
- (size_t)~0xf;
-}
-
-static size_t ksl_blklen(size_t nodelen) {
- return sizeof(ngtcp2_ksl_blk) + nodelen * NGTCP2_KSL_MAX_NBLK -
- sizeof(uint64_t);
-}
-
-/*
- * ksl_node_set_key sets |key| to |node|.
- */
-static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node,
- const void *key) {
- memcpy(node->key, key, ksl->keylen);
-}
-
-int ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t keylen,
- const ngtcp2_mem *mem) {
- size_t nodelen = ksl_nodelen(keylen);
- size_t blklen = ksl_blklen(nodelen);
- ngtcp2_ksl_blk *head;
-
- ksl->head = ngtcp2_mem_malloc(mem, blklen);
- if (!ksl->head) {
- return NGTCP2_ERR_NOMEM;
- }
- ksl->front = ksl->back = ksl->head;
- ksl->compar = compar;
- ksl->keylen = keylen;
- ksl->nodelen = nodelen;
- ksl->n = 0;
- ksl->mem = mem;
-
- head = ksl->head;
- head->next = head->prev = NULL;
- head->n = 0;
- head->leaf = 1;
-
- return 0;
-}
-
-/*
- * ksl_free_blk frees |blk| recursively.
- */
-static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
- size_t i;
-
- if (!blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk);
- }
- }
-
- ngtcp2_mem_free(ksl->mem, blk);
-}
-
-void ngtcp2_ksl_free(ngtcp2_ksl *ksl) {
- if (!ksl) {
- return;
- }
-
- ksl_free_blk(ksl, ksl->head);
-}
-
-/*
- * ksl_split_blk splits |blk| into 2 ngtcp2_ksl_blk objects. The new
- * ngtcp2_ksl_blk is always the "right" block.
- *
- * It returns the pointer to the ngtcp2_ksl_blk created which is the
- * located at the right of |blk|, or NULL which indicates out of
- * memory error.
- */
-static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
- ngtcp2_ksl_blk *rblk;
-
- rblk = ngtcp2_mem_malloc(ksl->mem, ksl_blklen(ksl->nodelen));
- if (rblk == NULL) {
- return NULL;
- }
-
- rblk->next = blk->next;
- blk->next = rblk;
- if (rblk->next) {
- rblk->next->prev = rblk;
- } else if (ksl->back == blk) {
- ksl->back = rblk;
- }
- rblk->prev = blk;
- rblk->leaf = blk->leaf;
-
- rblk->n = blk->n / 2;
-
- memcpy(rblk->nodes, blk->nodes + ksl->nodelen * (blk->n - rblk->n),
- ksl->nodelen * rblk->n);
-
- blk->n -= rblk->n;
-
- assert(blk->n >= NGTCP2_KSL_MIN_NBLK);
- assert(rblk->n >= NGTCP2_KSL_MIN_NBLK);
-
- return rblk;
-}
-
-/*
- * ksl_split_node splits a node included in |blk| at the position |i|
- * into 2 adjacent nodes. The new node is always inserted at the
- * position |i+1|.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
- ngtcp2_ksl_node *node;
- ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk;
-
- rblk = ksl_split_blk(ksl, lblk);
- if (rblk == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- memmove(blk->nodes + (i + 2) * ksl->nodelen,
- blk->nodes + (i + 1) * ksl->nodelen,
- ksl->nodelen * (blk->n - (i + 1)));
-
- node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
- node->blk = rblk;
- ++blk->n;
- ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
-
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
-
- return 0;
-}
-
-/*
- * ksl_split_head splits a head (root) block. It increases the height
- * of skip list by 1.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-static int ksl_split_head(ngtcp2_ksl *ksl) {
- ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL;
- ngtcp2_ksl_node *node;
-
- rblk = ksl_split_blk(ksl, ksl->head);
- if (rblk == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- lblk = ksl->head;
-
- nhead = ngtcp2_mem_malloc(ksl->mem, ksl_blklen(ksl->nodelen));
- if (nhead == NULL) {
- ngtcp2_mem_free(ksl->mem, rblk);
- return NGTCP2_ERR_NOMEM;
- }
- nhead->next = nhead->prev = NULL;
- nhead->n = 2;
- nhead->leaf = 0;
-
- node = ngtcp2_ksl_nth_node(ksl, nhead, 0);
- ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
- node->blk = lblk;
-
- node = ngtcp2_ksl_nth_node(ksl, nhead, 1);
- ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
- node->blk = rblk;
-
- ksl->head = nhead;
-
- return 0;
-}
-
-/*
- * insert_node inserts a node whose key is |key| with the associated
- * |data| at the index of |i|. This function assumes that the number
- * of nodes contained by |blk| is strictly less than
- * NGTCP2_KSL_MAX_NBLK.
- */
-static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i,
- const ngtcp2_ksl_key *key, void *data) {
- ngtcp2_ksl_node *node;
-
- assert(blk->n < NGTCP2_KSL_MAX_NBLK);
-
- memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
- ksl->nodelen * (blk->n - i));
-
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
- ksl_node_set_key(ksl, node, key);
- node->data = data;
-
- ++blk->n;
-}
-
-static size_t ksl_bsearch(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
- const ngtcp2_ksl_key *key, ngtcp2_ksl_compar compar) {
- ngtcp2_ssize left = -1, right = (ngtcp2_ssize)blk->n, mid;
- ngtcp2_ksl_node *node;
-
- while (right - left > 1) {
- mid = (left + right) / 2;
- node = ngtcp2_ksl_nth_node(ksl, blk, (size_t)mid);
- if (compar((ngtcp2_ksl_key *)node->key, key)) {
- left = mid;
- } else {
- right = mid;
- }
- }
-
- return (size_t)right;
-}
-
-int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
- const ngtcp2_ksl_key *key, void *data) {
- ngtcp2_ksl_blk *blk = ksl->head;
- ngtcp2_ksl_node *node;
- size_t i;
- int rv;
-
- if (blk->n == NGTCP2_KSL_MAX_NBLK) {
- rv = ksl_split_head(ksl);
- if (rv != 0) {
- return rv;
- }
- blk = ksl->head;
- }
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (blk->leaf) {
- if (i < blk->n &&
- !ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
- if (it) {
- *it = ngtcp2_ksl_end(ksl);
- }
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- ksl_insert_node(ksl, blk, i, key, data);
- ++ksl->n;
- if (it) {
- ngtcp2_ksl_it_init(it, ksl, blk, i);
- }
- return 0;
- }
-
- if (i == blk->n) {
- /* This insertion extends the largest key in this subtree. */
- for (; !blk->leaf;) {
- node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
- if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
- rv = ksl_split_node(ksl, blk, blk->n - 1);
- if (rv != 0) {
- return rv;
- }
- node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
- }
- ksl_node_set_key(ksl, node, key);
- blk = node->blk;
- }
- ksl_insert_node(ksl, blk, blk->n, key, data);
- ++ksl->n;
- if (it) {
- ngtcp2_ksl_it_init(it, ksl, blk, blk->n - 1);
- }
- return 0;
- }
-
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
-
- if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
- rv = ksl_split_node(ksl, blk, i);
- if (rv != 0) {
- return rv;
- }
- if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
- node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
- if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
- ksl_node_set_key(ksl, node, key);
- }
- }
- }
-
- blk = node->blk;
- }
-}
-
-/*
- * ksl_remove_node removes the node included in |blk| at the index of
- * |i|.
- */
-static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
- memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen,
- ksl->nodelen * (blk->n - (i + 1)));
-
- --blk->n;
-}
-
-/*
- * ksl_merge_node merges 2 nodes which are the nodes at the index of
- * |i| and |i + 1|.
- *
- * If |blk| is the direct descendant of head (root) block and the head
- * block contains just 2 nodes, the merged block becomes head block,
- * which decreases the height of |ksl| by 1.
- *
- * This function returns the pointer to the merged block.
- */
-static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
- size_t i) {
- ngtcp2_ksl_blk *lblk, *rblk;
-
- assert(i + 1 < blk->n);
-
- lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
- rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk;
-
- assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK);
-
- memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes,
- ksl->nodelen * rblk->n);
-
- lblk->n += rblk->n;
- lblk->next = rblk->next;
- if (lblk->next) {
- lblk->next->prev = lblk;
- } else if (ksl->back == rblk) {
- ksl->back = lblk;
- }
-
- ngtcp2_mem_free(ksl->mem, rblk);
-
- if (ksl->head == blk && blk->n == 2) {
- ngtcp2_mem_free(ksl->mem, ksl->head);
- ksl->head = lblk;
- } else {
- ksl_remove_node(ksl, blk, i + 1);
- ksl_node_set_key(ksl, ngtcp2_ksl_nth_node(ksl, blk, i),
- ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
- }
-
- return lblk;
-}
-
-/*
- * ksl_shift_left moves the first node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i - 1]->blk->nodes.
- */
-static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
- ngtcp2_ksl_node *lnode, *rnode, *dest, *src;
-
- assert(i > 0);
-
- lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1);
- rnode = ngtcp2_ksl_nth_node(ksl, blk, i);
-
- assert(lnode->blk->n < NGTCP2_KSL_MAX_NBLK);
- assert(rnode->blk->n > NGTCP2_KSL_MIN_NBLK);
-
- dest = ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n);
- src = ngtcp2_ksl_nth_node(ksl, rnode->blk, 0);
-
- memcpy(dest, src, ksl->nodelen);
- ksl_node_set_key(ksl, lnode, dest->key);
- ++lnode->blk->n;
-
- --rnode->blk->n;
- memmove(rnode->blk->nodes, rnode->blk->nodes + ksl->nodelen,
- ksl->nodelen * rnode->blk->n);
-}
-
-/*
- * ksl_shift_right moves the last node in blk->nodes[i]->blk->nodes to
- * blk->nodes[i + 1]->blk->nodes.
- */
-static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
- ngtcp2_ksl_node *lnode, *rnode, *dest, *src;
-
- assert(i < blk->n - 1);
-
- lnode = ngtcp2_ksl_nth_node(ksl, blk, i);
- rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
-
- assert(lnode->blk->n > NGTCP2_KSL_MIN_NBLK);
- assert(rnode->blk->n < NGTCP2_KSL_MAX_NBLK);
-
- memmove(rnode->blk->nodes + ksl->nodelen, rnode->blk->nodes,
- ksl->nodelen * rnode->blk->n);
- ++rnode->blk->n;
-
- dest = ngtcp2_ksl_nth_node(ksl, rnode->blk, 0);
- src = ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1);
-
- memcpy(dest, src, ksl->nodelen);
-
- --lnode->blk->n;
- ksl_node_set_key(
- ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
-}
-
-/*
- * key_equal returns nonzero if |lhs| and |rhs| are equal using the
- * function |compar|.
- */
-static int key_equal(ngtcp2_ksl_compar compar, const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs) {
- return !compar(lhs, rhs) && !compar(rhs, lhs);
-}
-
-int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
- const ngtcp2_ksl_key *key) {
- ngtcp2_ksl_blk *blk = ksl->head;
- ngtcp2_ksl_node *node;
- size_t i;
-
- if (!blk->leaf && blk->n == 2 &&
- ngtcp2_ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK &&
- ngtcp2_ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) {
- blk = ksl_merge_node(ksl, ksl->head, 0);
- }
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (i == blk->n) {
- if (it) {
- *it = ngtcp2_ksl_end(ksl);
- }
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if (blk->leaf) {
- if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
- if (it) {
- *it = ngtcp2_ksl_end(ksl);
- }
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- ksl_remove_node(ksl, blk, i);
- --ksl->n;
- if (it) {
- if (blk->n == i && blk->next) {
- ngtcp2_ksl_it_init(it, ksl, blk->next, 0);
- } else {
- ngtcp2_ksl_it_init(it, ksl, blk, i);
- }
- }
- return 0;
- }
-
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
-
- if (node->blk->n == NGTCP2_KSL_MIN_NBLK) {
- if (i > 0 &&
- ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
- ksl_shift_right(ksl, blk, i - 1);
- blk = node->blk;
- } else if (i + 1 < blk->n &&
- ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n >
- NGTCP2_KSL_MIN_NBLK) {
- ksl_shift_left(ksl, blk, i + 1);
- blk = node->blk;
- } else if (i > 0) {
- blk = ksl_merge_node(ksl, blk, i - 1);
- } else {
- assert(i + 1 < blk->n);
- blk = ksl_merge_node(ksl, blk, i);
- }
- } else {
- blk = node->blk;
- }
- }
-}
-
-ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl,
- const ngtcp2_ksl_key *key) {
- ngtcp2_ksl_blk *blk = ksl->head;
- ngtcp2_ksl_it it;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, ksl->compar);
-
- if (blk->leaf) {
- if (i == blk->n && blk->next) {
- blk = blk->next;
- i = 0;
- }
- ngtcp2_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
-
- if (i == blk->n) {
- /* This happens if descendant has smaller key. Fast forward to
- find last node in this subtree. */
- for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
- ;
- if (blk->next) {
- blk = blk->next;
- i = 0;
- } else {
- i = blk->n;
- }
- ngtcp2_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
- blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
- }
-}
-
-ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl,
- const ngtcp2_ksl_key *key,
- ngtcp2_ksl_compar compar) {
- ngtcp2_ksl_blk *blk = ksl->head;
- ngtcp2_ksl_it it;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, key, compar);
-
- if (blk->leaf) {
- if (i == blk->n && blk->next) {
- blk = blk->next;
- i = 0;
- }
- ngtcp2_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
-
- if (i == blk->n) {
- /* This happens if descendant has smaller key. Fast forward to
- find last node in this subtree. */
- for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
- ;
- if (blk->next) {
- blk = blk->next;
- i = 0;
- } else {
- i = blk->n;
- }
- ngtcp2_ksl_it_init(&it, ksl, blk, i);
- return it;
- }
- blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
- }
-}
-
-void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
- const ngtcp2_ksl_key *new_key) {
- ngtcp2_ksl_blk *blk = ksl->head;
- ngtcp2_ksl_node *node;
- size_t i;
-
- for (;;) {
- i = ksl_bsearch(ksl, blk, old_key, ksl->compar);
-
- assert(i < blk->n);
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
-
- if (blk->leaf) {
- assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key));
- ksl_node_set_key(ksl, node, new_key);
- return;
- }
-
- if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) ||
- ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) {
- ksl_node_set_key(ksl, node, new_key);
- }
-
- blk = node->blk;
- }
-}
-
-static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) {
- size_t i;
- ngtcp2_ksl_node *node;
-
- fprintf(stderr, "LV=%zu n=%zu\n", level, blk->n);
-
- if (blk->leaf) {
- for (i = 0; i < blk->n; ++i) {
- node = ngtcp2_ksl_nth_node(ksl, blk, i);
- fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
- }
- fprintf(stderr, "\n");
- return;
- }
-
- for (i = 0; i < blk->n; ++i) {
- ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1);
- }
-}
-
-size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl) { return ksl->n; }
-
-void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) {
- size_t i;
- ngtcp2_ksl_blk *head;
-
- if (!ksl->head->leaf) {
- for (i = 0; i < ksl->head->n; ++i) {
- ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, ksl->head, i)->blk);
- }
- }
-
- ksl->front = ksl->back = ksl->head;
- ksl->n = 0;
-
- head = ksl->head;
-
- head->next = head->prev = NULL;
- head->n = 0;
- head->leaf = 1;
-}
-
-void ngtcp2_ksl_print(ngtcp2_ksl *ksl) { ksl_print(ksl, ksl->head, 0); }
-
-ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl) {
- ngtcp2_ksl_it it;
- ngtcp2_ksl_it_init(&it, ksl, ksl->front, 0);
- return it;
-}
-
-ngtcp2_ksl_it ngtcp2_ksl_end(const ngtcp2_ksl *ksl) {
- ngtcp2_ksl_it it;
- ngtcp2_ksl_it_init(&it, ksl, ksl->back, ksl->back->n);
- return it;
-}
-
-void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl,
- ngtcp2_ksl_blk *blk, size_t i) {
- it->ksl = ksl;
- it->blk = blk;
- it->i = i;
-}
-
-void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it) {
- assert(it->i < it->blk->n);
- return ngtcp2_ksl_nth_node(it->ksl, it->blk, it->i)->data;
-}
-
-void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it) {
- assert(!ngtcp2_ksl_it_begin(it));
-
- if (it->i == 0) {
- it->blk = it->blk->prev;
- it->i = it->blk->n - 1;
- } else {
- --it->i;
- }
-}
-
-int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it) {
- return it->i == 0 && it->blk->prev == NULL;
-}
-
-int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs) {
- const ngtcp2_range *a = lhs, *b = rhs;
- return a->begin < b->begin;
-}
-
-int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs) {
- const ngtcp2_range *a = lhs, *b = rhs;
- return a->begin < b->begin &&
- !(ngtcp2_max(a->begin, b->begin) < ngtcp2_min(a->end, b->end));
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_ksl.h b/deps/ngtcp2/lib/ngtcp2_ksl.h
deleted file mode 100644
index 071e10dce1..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ksl.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_KSL_H
-#define NGTCP2_KSL_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-
-#include <ngtcp2/ngtcp2.h>
-
-/*
- * Skip List using single key instead of range.
- */
-
-#define NGTCP2_KSL_DEGR 16
-/* NGTCP2_KSL_MAX_NBLK is the maximum number of nodes which a single
- block can contain. */
-#define NGTCP2_KSL_MAX_NBLK (2 * NGTCP2_KSL_DEGR - 1)
-/* NGTCP2_KSL_MIN_NBLK is the minimum number of nodes which a single
- block other than root must contains. */
-#define NGTCP2_KSL_MIN_NBLK (NGTCP2_KSL_DEGR - 1)
-
-/*
- * ngtcp2_ksl_key represents key in ngtcp2_ksl.
- */
-typedef void ngtcp2_ksl_key;
-
-struct ngtcp2_ksl_node;
-typedef struct ngtcp2_ksl_node ngtcp2_ksl_node;
-
-struct ngtcp2_ksl_blk;
-typedef struct ngtcp2_ksl_blk ngtcp2_ksl_blk;
-
-/*
- * ngtcp2_ksl_node is a node which contains either ngtcp2_ksl_blk or
- * opaque data. If a node is an internal node, it contains
- * ngtcp2_ksl_blk. Otherwise, it has data. The key is stored at the
- * location starting at key.
- */
-struct ngtcp2_ksl_node {
- union {
- ngtcp2_ksl_blk *blk;
- void *data;
- };
- union {
- uint64_t align;
- /* key is a buffer to include key associated to this node.
- Because the length of key is unknown until ngtcp2_ksl_init is
- called, the actual buffer will be allocated after this
- field. */
- uint8_t key[1];
- };
-};
-
-/*
- * ngtcp2_ksl_blk contains ngtcp2_ksl_node objects.
- */
-struct ngtcp2_ksl_blk {
- /* next points to the next block if leaf field is nonzero. */
- ngtcp2_ksl_blk *next;
- /* prev points to the previous block if leaf field is nonzero. */
- ngtcp2_ksl_blk *prev;
- /* n is the number of nodes this object contains in nodes. */
- size_t n;
- /* leaf is nonzero if this block contains leaf nodes. */
- int leaf;
- union {
- uint64_t align;
- /* nodes is a buffer to contain NGTCP2_KSL_MAX_NBLK
- ngtcp2_ksl_node objects. Because ngtcp2_ksl_node object is
- allocated along with the additional variable length key
- storage, the size of buffer is unknown until ngtcp2_ksl_init is
- called. */
- uint8_t nodes[1];
- };
-};
-
-/*
- * ngtcp2_ksl_compar is a function type which returns nonzero if key
- * |lhs| should be placed before |rhs|. It returns 0 otherwise.
- */
-typedef int (*ngtcp2_ksl_compar)(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs);
-
-struct ngtcp2_ksl;
-typedef struct ngtcp2_ksl ngtcp2_ksl;
-
-struct ngtcp2_ksl_it;
-typedef struct ngtcp2_ksl_it ngtcp2_ksl_it;
-
-/*
- * ngtcp2_ksl_it is a forward iterator to iterate nodes.
- */
-struct ngtcp2_ksl_it {
- const ngtcp2_ksl *ksl;
- ngtcp2_ksl_blk *blk;
- size_t i;
-};
-
-/*
- * ngtcp2_ksl is a deterministic paged skip list.
- */
-struct ngtcp2_ksl {
- /* head points to the root block. */
- ngtcp2_ksl_blk *head;
- /* front points to the first leaf block. */
- ngtcp2_ksl_blk *front;
- /* back points to the last leaf block. */
- ngtcp2_ksl_blk *back;
- ngtcp2_ksl_compar compar;
- size_t n;
- /* keylen is the size of key */
- size_t keylen;
- /* nodelen is the actual size of ngtcp2_ksl_node including key
- storage. */
- size_t nodelen;
- const ngtcp2_mem *mem;
-};
-
-/*
- * ngtcp2_ksl_init initializes |ksl|. |compar| specifies compare
- * function. |keylen| is the length of key.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t keylen,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_ksl_free frees resources allocated for |ksl|. If |ksl| is
- * NULL, this function does nothing. It does not free the memory
- * region pointed by |ksl| itself.
- */
-void ngtcp2_ksl_free(ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_insert inserts |key| with its associated |data|. On
- * successful insertion, the iterator points to the inserted node is
- * stored in |*it|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- * NGTCP2_ERR_INVALID_ARGUMENT
- * |key| already exists.
- */
-int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
- const ngtcp2_ksl_key *key, void *data);
-
-/*
- * ngtcp2_ksl_remove removes the |key| from |ksl|.
- *
- * This function assigns the iterator to |*it|, which points to the
- * node which is located at the right next of the removed node if |it|
- * is not NULL. If |key| is not found, no deletion takes place and
- * the return value of ngtcp2_ksl_end(ksl) is assigned to |*it|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * |key| does not exist.
- */
-int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
- const ngtcp2_ksl_key *key);
-
-/*
- * ngtcp2_ksl_lower_bound returns the iterator which points to the
- * first node which has the key which is equal to |key| or the last
- * node which satisfies !compar(&node->key, key). If there is no such
- * node, it returns the iterator which satisfies ngtcp2_ksl_it_end(it)
- * != 0.
- */
-ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl,
- const ngtcp2_ksl_key *key);
-
-/*
- * ngtcp2_ksl_lower_bound_compar works like ngtcp2_ksl_lower_bound,
- * but it takes custom function |compar| to do lower bound search.
- */
-ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl,
- const ngtcp2_ksl_key *key,
- ngtcp2_ksl_compar compar);
-
-/*
- * ngtcp2_ksl_update_key replaces the key of nodes which has |old_key|
- * with |new_key|. |new_key| must be strictly greater than the
- * previous node and strictly smaller than the next node.
- */
-void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
- const ngtcp2_ksl_key *new_key);
-
-/*
- * ngtcp2_ksl_begin returns the iterator which points to the first
- * node. If there is no node in |ksl|, it returns the iterator which
- * satisfies ngtcp2_ksl_it_end(it) != 0.
- */
-ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_end returns the iterator which points to the node
- * following the last node. The returned object satisfies
- * ngtcp2_ksl_it_end(). If there is no node in |ksl|, it returns the
- * iterator which satisfies ngtcp2_ksl_it_begin(it) != 0.
- */
-ngtcp2_ksl_it ngtcp2_ksl_end(const ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_len returns the number of elements stored in |ksl|.
- */
-size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_clear removes all elements stored in |ksl|.
- */
-void ngtcp2_ksl_clear(ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_nth_node returns the |n|th node under |blk|.
- */
-#define ngtcp2_ksl_nth_node(KSL, BLK, N) \
- ((ngtcp2_ksl_node *)(void *)((BLK)->nodes + (KSL)->nodelen * (N)))
-
-/*
- * ngtcp2_ksl_print prints its internal state in stderr. It assumes
- * that the key is of type int64_t. This function should be used for
- * the debugging purpose only.
- */
-void ngtcp2_ksl_print(ngtcp2_ksl *ksl);
-
-/*
- * ngtcp2_ksl_it_init initializes |it|.
- */
-void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl,
- ngtcp2_ksl_blk *blk, size_t i);
-
-/*
- * ngtcp2_ksl_it_get returns the data associated to the node which
- * |it| points to. It is undefined to call this function when
- * ngtcp2_ksl_it_end(it) returns nonzero.
- */
-void *ngtcp2_ksl_it_get(const ngtcp2_ksl_it *it);
-
-/*
- * ngtcp2_ksl_it_next advances the iterator by one. It is undefined
- * if this function is called when ngtcp2_ksl_it_end(it) returns
- * nonzero.
- */
-#define ngtcp2_ksl_it_next(IT) \
- (++(IT)->i == (IT)->blk->n && (IT)->blk->next \
- ? ((IT)->blk = (IT)->blk->next, (IT)->i = 0) \
- : 0)
-
-/*
- * ngtcp2_ksl_it_prev moves backward the iterator by one. It is
- * undefined if this function is called when ngtcp2_ksl_it_begin(it)
- * returns nonzero.
- */
-void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it);
-
-/*
- * ngtcp2_ksl_it_end returns nonzero if |it| points to the beyond the
- * last node.
- */
-#define ngtcp2_ksl_it_end(IT) \
- ((IT)->blk->n == (IT)->i && (IT)->blk->next == NULL)
-
-/*
- * ngtcp2_ksl_it_begin returns nonzero if |it| points to the first
- * node. |it| might satisfy both ngtcp2_ksl_it_begin(&it) and
- * ngtcp2_ksl_it_end(&it) if the skip list has no node.
- */
-int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it);
-
-/*
- * ngtcp2_ksl_key returns the key of the node which |it| points to.
- * It is undefined to call this function when ngtcp2_ksl_it_end(it)
- * returns nonzero.
- */
-#define ngtcp2_ksl_it_key(IT) \
- ((ngtcp2_ksl_key *)ngtcp2_ksl_nth_node((IT)->ksl, (IT)->blk, (IT)->i)->key)
-
-/*
- * ngtcp2_ksl_range_compar is an implementation of ngtcp2_ksl_compar.
- * lhs->ptr and rhs->ptr must point to ngtcp2_range object and the
- * function returns nonzero if (const ngtcp2_range *)(lhs->ptr)->begin
- * < (const ngtcp2_range *)(rhs->ptr)->begin.
- */
-int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs);
-
-/*
- * ngtcp2_ksl_range_exclusive_compar is an implementation of
- * ngtcp2_ksl_compar. lhs->ptr and rhs->ptr must point to
- * ngtcp2_range object and the function returns nonzero if (const
- * ngtcp2_range *)(lhs->ptr)->begin < (const ngtcp2_range
- * *)(rhs->ptr)->begin and the 2 ranges do not intersect.
- */
-int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs,
- const ngtcp2_ksl_key *rhs);
-
-#endif /* NGTCP2_KSL_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_log.c b/deps/ngtcp2/lib/ngtcp2_log.c
deleted file mode 100644
index 8b7ec0def6..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_log.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_log.h"
-
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <assert.h>
-#include <string.h>
-
-#include "ngtcp2_str.h"
-#include "ngtcp2_vec.h"
-#include "ngtcp2_macro.h"
-
-void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid,
- ngtcp2_printf log_printf, ngtcp2_tstamp ts,
- void *user_data) {
- if (scid) {
- ngtcp2_encode_hex(log->scid, scid->data, scid->datalen);
- } else {
- log->scid[0] = '\0';
- }
- log->log_printf = log_printf;
- log->ts = log->last_ts = ts;
- log->user_data = user_data;
-}
-
-/*
- * # Log header
- *
- * <LEVEL><TIMESTAMP> <SCID> <EVENT>
- *
- * <LEVEL>:
- * Log level. I=Info, W=Warning, E=Error
- *
- * <TIMESTAMP>:
- * Timestamp relative to ngtcp2_log.ts field in milliseconds
- * resolution.
- *
- * <SCID>:
- * Source Connection ID in hex string.
- *
- * <EVENT>:
- * Event. pkt=packet, frm=frame, rcv=recovery, cry=crypto,
- * con=connection(catch all)
- *
- * # Frame event
- *
- * <DIR> <PKN> <PKTNAME>(<PKTTYPE>) <FRAMENAME>(<FRAMETYPE>)
- *
- * <DIR>:
- * Flow direction. tx=transmission, rx=reception
- *
- * <PKN>:
- * Packet number.
- *
- * <PKTNAME>:
- * Packet name. (e.g., Initial, Handshake, S01)
- *
- * <PKTTYPE>:
- * Packet type in hex string.
- *
- * <FRAMENAME>:
- * Frame name. (e.g., STREAM, ACK, PING)
- *
- * <FRAMETYPE>:
- * Frame type in hex string.
- */
-
-#define NGTCP2_LOG_BUFLEN 4096
-
-/* TODO Split second and remaining fraction with comma */
-#define NGTCP2_LOG_HD "I%08" PRIu64 " 0x%s %s"
-#define NGTCP2_LOG_PKT NGTCP2_LOG_HD " %s %" PRId64 " %s(0x%02x)"
-#define NGTCP2_LOG_TP NGTCP2_LOG_HD " remote transport_parameters"
-
-#define NGTCP2_LOG_FRM_HD_FIELDS(DIR) \
- timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "frm", \
- (DIR), hd->pkt_num, strpkttype(hd), hd->type
-
-#define NGTCP2_LOG_PKT_HD_FIELDS(DIR) \
- timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "pkt", \
- (DIR), hd->pkt_num, strpkttype(hd), hd->type
-
-#define NGTCP2_LOG_TP_HD_FIELDS \
- timestamp_cast(log->last_ts - log->ts), (const char *)log->scid, "cry"
-
-static const char *strerrorcode(uint64_t error_code) {
- switch (error_code) {
- case NGTCP2_NO_ERROR:
- return "NO_ERROR";
- case NGTCP2_INTERNAL_ERROR:
- return "INTERNAL_ERROR";
- case NGTCP2_CONNECTION_REFUSED:
- return "CONNECTION_REFUSED";
- case NGTCP2_FLOW_CONTROL_ERROR:
- return "FLOW_CONTROL_ERROR";
- case NGTCP2_STREAM_LIMIT_ERROR:
- return "STREAM_LIMIT_ERROR";
- case NGTCP2_STREAM_STATE_ERROR:
- return "STREAM_STATE_ERROR";
- case NGTCP2_FINAL_SIZE_ERROR:
- return "FINAL_SIZE_ERROR";
- case NGTCP2_FRAME_ENCODING_ERROR:
- return "FRAME_ENCODING_ERROR";
- case NGTCP2_TRANSPORT_PARAMETER_ERROR:
- return "TRANSPORT_PARAMETER_ERROR";
- case NGTCP2_CONNECTION_ID_LIMIT_ERROR:
- return "CONNECTION_ID_LIMIT_ERROR";
- case NGTCP2_PROTOCOL_VIOLATION:
- return "PROTOCOL_VIOLATION";
- case NGTCP2_INVALID_TOKEN:
- return "INVALID_TOKEN";
- case NGTCP2_APPLICATION_ERROR:
- return "APPLICATION_ERROR";
- case NGTCP2_CRYPTO_BUFFER_EXCEEDED:
- return "CRYPTO_BUFFER_EXCEEDED";
- case NGTCP2_KEY_UPDATE_ERROR:
- return "KEY_UPDATE_ERROR";
- default:
- if (0x100u <= error_code && error_code <= 0x1ffu) {
- return "CRYPTO_ERROR";
- }
- return "(unknown)";
- }
-}
-
-static const char *strapperrorcode(uint64_t app_error_code) {
- (void)app_error_code;
- return "(unknown)";
-}
-
-static const char *strpkttype_long(uint8_t type) {
- switch (type) {
- case NGTCP2_PKT_VERSION_NEGOTIATION:
- return "VN";
- case NGTCP2_PKT_INITIAL:
- return "Initial";
- case NGTCP2_PKT_RETRY:
- return "Retry";
- case NGTCP2_PKT_HANDSHAKE:
- return "Handshake";
- case NGTCP2_PKT_0RTT:
- return "0RTT";
- default:
- return "(unknown)";
- }
-}
-
-static const char *strpkttype(const ngtcp2_pkt_hd *hd) {
- if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- return strpkttype_long(hd->type);
- }
- return "Short";
-}
-
-static const char *strevent(ngtcp2_log_event ev) {
- switch (ev) {
- case NGTCP2_LOG_EVENT_CON:
- return "con";
- case NGTCP2_LOG_EVENT_PKT:
- return "pkt";
- case NGTCP2_LOG_EVENT_FRM:
- return "frm";
- case NGTCP2_LOG_EVENT_RCV:
- return "rcv";
- case NGTCP2_LOG_EVENT_CRY:
- return "cry";
- case NGTCP2_LOG_EVENT_PTV:
- return "ptv";
- case NGTCP2_LOG_EVENT_NONE:
- default:
- return "non";
- }
-}
-
-static uint64_t timestamp_cast(uint64_t ns) { return ns / NGTCP2_MILLISECONDS; }
-
-static void log_fr_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_stream *fr, const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " STREAM(0x%02x) id=0x%" PRIx64
- " fin=%d offset=%" PRIu64 " len=%zu uni=%d"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type | fr->flags,
- fr->stream_id, fr->fin, fr->offset,
- ngtcp2_vec_len(fr->data, fr->datacnt),
- (fr->stream_id & 0x2) != 0);
-}
-
-static void log_fr_ack(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_ack *fr, const char *dir) {
- int64_t largest_ack, min_ack;
- size_t i;
-
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " ACK(0x%02x) largest_ack=%" PRId64
- " ack_delay=%" PRIu64 "(%" PRIu64
- ") ack_block_count=%zu"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->largest_ack,
- fr->ack_delay_unscaled / NGTCP2_MILLISECONDS, fr->ack_delay,
- fr->num_blks);
-
- largest_ack = fr->largest_ack;
- min_ack = fr->largest_ack - (int64_t)fr->first_ack_blklen;
-
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " ACK(0x%02x) block=[%" PRId64 "..%" PRId64
- "] block_count=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack, min_ack,
- fr->first_ack_blklen);
-
- for (i = 0; i < fr->num_blks; ++i) {
- const ngtcp2_ack_blk *blk = &fr->blks[i];
- largest_ack = min_ack - (int64_t)blk->gap - 2;
- min_ack = largest_ack - (int64_t)blk->blklen;
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " ACK(0x%02x) block=[%" PRId64 "..%" PRId64
- "] gap=%" PRIu64 " block_count=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, largest_ack,
- min_ack, blk->gap, blk->blklen);
- }
-}
-
-static void log_fr_padding(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_padding *fr, const char *dir) {
- log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PADDING(0x%02x) len=%zu"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->len);
-}
-
-static void log_fr_reset_stream(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_reset_stream *fr,
- const char *dir) {
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_PKT " RESET_STREAM(0x%02x) id=0x%" PRIx64
- " app_error_code=%s(0x%" PRIx64 ") final_size=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
- strapperrorcode(fr->app_error_code), fr->app_error_code, fr->final_size);
-}
-
-static void log_fr_connection_close(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_connection_close *fr,
- const char *dir) {
- char reason[256];
- size_t reasonlen = ngtcp2_min(sizeof(reason) - 1, fr->reasonlen);
-
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT
- " CONNECTION_CLOSE(0x%02x) error_code=%s(0x%" PRIx64 ") "
- "frame_type=%" PRIx64 " reason_len=%zu reason=[%s]"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type,
- fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
- ? strerrorcode(fr->error_code)
- : strapperrorcode(fr->error_code),
- fr->error_code, fr->frame_type, fr->reasonlen,
- ngtcp2_encode_printable_ascii(reason, fr->reason, reasonlen));
-}
-
-static void log_fr_max_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_max_data *fr, const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " MAX_DATA(0x%02x) max_data=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_data);
-}
-
-static void log_fr_max_stream_data(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_max_stream_data *fr,
- const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " MAX_STREAM_DATA(0x%02x) id=0x%" PRIx64
- " max_stream_data=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
- fr->max_stream_data);
-}
-
-static void log_fr_max_streams(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_max_streams *fr, const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " MAX_STREAMS(0x%02x) max_streams=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->max_streams);
-}
-
-static void log_fr_ping(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_ping *fr, const char *dir) {
- log->log_printf(log->user_data, (NGTCP2_LOG_PKT " PING(0x%02x)"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type);
-}
-
-static void log_fr_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_data_blocked *fr,
- const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " DATA_BLOCKED(0x%02x) offset=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset);
-}
-
-static void log_fr_stream_data_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_stream_data_blocked *fr,
- const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " STREAM_DATA_BLOCKED(0x%02x) id=0x%" PRIx64
- " offset=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
- fr->offset);
-}
-
-static void log_fr_streams_blocked(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_streams_blocked *fr,
- const char *dir) {
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_PKT " STREAMS_BLOCKED(0x%02x) stream_limit=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_limit);
-}
-
-static void log_fr_new_connection_id(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_new_connection_id *fr,
- const char *dir) {
- uint8_t buf[sizeof(fr->stateless_reset_token) * 2 + 1];
- uint8_t cid[sizeof(fr->cid.data) * 2 + 1];
-
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_PKT " NEW_CONNECTION_ID(0x%02x) seq=%" PRIu64
- " cid=0x%s retire_prior_to=%" PRIu64
- " stateless_reset_token=0x%s"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq,
- (const char *)ngtcp2_encode_hex(cid, fr->cid.data, fr->cid.datalen),
- fr->retire_prior_to,
- (const char *)ngtcp2_encode_hex(buf, fr->stateless_reset_token,
- sizeof(fr->stateless_reset_token)));
-}
-
-static void log_fr_stop_sending(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_stop_sending *fr,
- const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " STOP_SENDING(0x%02x) id=0x%" PRIx64
- " app_error_code=%s(0x%" PRIx64 ")"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->stream_id,
- strapperrorcode(fr->app_error_code), fr->app_error_code);
-}
-
-static void log_fr_path_challenge(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_path_challenge *fr,
- const char *dir) {
- uint8_t buf[sizeof(fr->data) * 2 + 1];
-
- log->log_printf(
- log->user_data, (NGTCP2_LOG_PKT " PATH_CHALLENGE(0x%02x) data=0x%s"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type,
- (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data)));
-}
-
-static void log_fr_path_response(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_path_response *fr,
- const char *dir) {
- uint8_t buf[sizeof(fr->data) * 2 + 1];
-
- log->log_printf(
- log->user_data, (NGTCP2_LOG_PKT " PATH_RESPONSE(0x%02x) data=0x%s"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type,
- (const char *)ngtcp2_encode_hex(buf, fr->data, sizeof(fr->data)));
-}
-
-static void log_fr_crypto(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_crypto *fr, const char *dir) {
- size_t datalen = 0;
- size_t i;
-
- for (i = 0; i < fr->datacnt; ++i) {
- datalen += fr->data[i].len;
- }
-
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_PKT " CRYPTO(0x%02x) offset=%" PRIu64 " len=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->offset, datalen);
-}
-
-static void log_fr_new_token(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_new_token *fr, const char *dir) {
- /* Show at most first 64 bytes of token. If token is longer than 64
- bytes, log first 64 bytes and then append "*" */
- uint8_t buf[128 + 1 + 1];
- uint8_t *p;
-
- if (fr->token.len > 64) {
- p = ngtcp2_encode_hex(buf, fr->token.base, 64);
- p[128] = '*';
- p[129] = '\0';
- } else {
- p = ngtcp2_encode_hex(buf, fr->token.base, fr->token.len);
- }
- log->log_printf(
- log->user_data, (NGTCP2_LOG_PKT " NEW_TOKEN(0x%02x) token=0x%s len=%zu"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, (const char *)p, fr->token.len);
-}
-
-static void log_fr_retire_connection_id(ngtcp2_log *log,
- const ngtcp2_pkt_hd *hd,
- const ngtcp2_retire_connection_id *fr,
- const char *dir) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_PKT " RETIRE_CONNECTION_ID(0x%02x) seq=%" PRIu64),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type, fr->seq);
-}
-
-static void log_fr_handshake_done(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_handshake_done *fr,
- const char *dir) {
- log->log_printf(log->user_data, (NGTCP2_LOG_PKT " HANDSHAKE_DONE(0x%02x)"),
- NGTCP2_LOG_FRM_HD_FIELDS(dir), fr->type);
-}
-
-static void log_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_frame *fr, const char *dir) {
- switch (fr->type) {
- case NGTCP2_FRAME_STREAM:
- log_fr_stream(log, hd, &fr->stream, dir);
- break;
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- log_fr_ack(log, hd, &fr->ack, dir);
- break;
- case NGTCP2_FRAME_PADDING:
- log_fr_padding(log, hd, &fr->padding, dir);
- break;
- case NGTCP2_FRAME_RESET_STREAM:
- log_fr_reset_stream(log, hd, &fr->reset_stream, dir);
- break;
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- log_fr_connection_close(log, hd, &fr->connection_close, dir);
- break;
- case NGTCP2_FRAME_MAX_DATA:
- log_fr_max_data(log, hd, &fr->max_data, dir);
- break;
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- log_fr_max_stream_data(log, hd, &fr->max_stream_data, dir);
- break;
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- log_fr_max_streams(log, hd, &fr->max_streams, dir);
- break;
- case NGTCP2_FRAME_PING:
- log_fr_ping(log, hd, &fr->ping, dir);
- break;
- case NGTCP2_FRAME_DATA_BLOCKED:
- log_fr_data_blocked(log, hd, &fr->data_blocked, dir);
- break;
- case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
- log_fr_stream_data_blocked(log, hd, &fr->stream_data_blocked, dir);
- break;
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- log_fr_streams_blocked(log, hd, &fr->streams_blocked, dir);
- break;
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- log_fr_new_connection_id(log, hd, &fr->new_connection_id, dir);
- break;
- case NGTCP2_FRAME_STOP_SENDING:
- log_fr_stop_sending(log, hd, &fr->stop_sending, dir);
- break;
- case NGTCP2_FRAME_PATH_CHALLENGE:
- log_fr_path_challenge(log, hd, &fr->path_challenge, dir);
- break;
- case NGTCP2_FRAME_PATH_RESPONSE:
- log_fr_path_response(log, hd, &fr->path_response, dir);
- break;
- case NGTCP2_FRAME_CRYPTO:
- log_fr_crypto(log, hd, &fr->crypto, dir);
- break;
- case NGTCP2_FRAME_NEW_TOKEN:
- log_fr_new_token(log, hd, &fr->new_token, dir);
- break;
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- log_fr_retire_connection_id(log, hd, &fr->retire_connection_id, dir);
- break;
- case NGTCP2_FRAME_HANDSHAKE_DONE:
- log_fr_handshake_done(log, hd, &fr->handshake_done, dir);
- break;
- default:
- assert(0);
- }
-}
-
-void ngtcp2_log_rx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_frame *fr) {
- if (!log->log_printf) {
- return;
- }
-
- log_fr(log, hd, fr, "rx");
-}
-
-void ngtcp2_log_tx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_frame *fr) {
- if (!log->log_printf) {
- return;
- }
-
- log_fr(log, hd, fr, "tx");
-}
-
-void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const uint32_t *sv, size_t nsv) {
- size_t i;
-
- if (!log->log_printf) {
- return;
- }
-
- for (i = 0; i < nsv; ++i) {
- log->log_printf(log->user_data, (NGTCP2_LOG_PKT " v=0x%08x"),
- NGTCP2_LOG_PKT_HD_FIELDS("rx"), sv[i]);
- }
-}
-
-void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr) {
- uint8_t buf[sizeof(sr->stateless_reset_token) * 2 + 1];
- ngtcp2_pkt_hd shd;
- ngtcp2_pkt_hd *hd = &shd;
-
- if (!log->log_printf) {
- return;
- }
-
- memset(&shd, 0, sizeof(shd));
-
- log->log_printf(
- log->user_data, (NGTCP2_LOG_PKT " token=0x%s randlen=%zu"),
- NGTCP2_LOG_PKT_HD_FIELDS("rx"),
- (const char *)ngtcp2_encode_hex(buf, sr->stateless_reset_token,
- sizeof(sr->stateless_reset_token)),
- sr->randlen);
-}
-
-void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype,
- const ngtcp2_transport_params *params) {
- uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1];
- uint8_t addr[16 * 2 + 1];
- uint8_t cid[NGTCP2_MAX_CIDLEN * 2 + 1];
-
- if (!log->log_printf) {
- return;
- }
-
- if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
- if (params->stateless_reset_token_present) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " stateless_reset_token=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- token, params->stateless_reset_token,
- sizeof(params->stateless_reset_token)));
- }
-
- if (params->preferred_address_present) {
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " preferred_address.ipv4_addr=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- addr, params->preferred_address.ipv4_addr,
- sizeof(params->preferred_address.ipv4_addr)));
- log->log_printf(
- log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv4_port=%u"),
- NGTCP2_LOG_TP_HD_FIELDS, params->preferred_address.ipv4_port);
-
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " preferred_address.ipv6_addr=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- addr, params->preferred_address.ipv6_addr,
- sizeof(params->preferred_address.ipv6_addr)));
- log->log_printf(
- log->user_data, (NGTCP2_LOG_TP " preferred_address.ipv6_port=%u"),
- NGTCP2_LOG_TP_HD_FIELDS, params->preferred_address.ipv6_port);
-
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " preferred_address.cid=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- cid, params->preferred_address.cid.data,
- params->preferred_address.cid.datalen));
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_TP " preferred_address.stateless_reset_token=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(
- token, params->preferred_address.stateless_reset_token,
- sizeof(params->preferred_address.stateless_reset_token)));
- }
-
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_TP " original_destination_connection_id=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(cid, params->original_dcid.data,
- params->original_dcid.datalen));
-
- if (params->retry_scid_present) {
- log->log_printf(
- log->user_data, (NGTCP2_LOG_TP " retry_source_connection_id=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(cid, params->retry_scid.data,
- params->retry_scid.datalen));
- }
- }
-
- log->log_printf(
- log->user_data, (NGTCP2_LOG_TP " initial_source_connection_id=0x%s"),
- NGTCP2_LOG_TP_HD_FIELDS,
- (const char *)ngtcp2_encode_hex(cid, params->initial_scid.data,
- params->initial_scid.datalen));
-
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_TP " initial_max_stream_data_bidi_local=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_local);
- log->log_printf(
- log->user_data,
- (NGTCP2_LOG_TP " initial_max_stream_data_bidi_remote=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_bidi_remote);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " initial_max_stream_data_uni=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_stream_data_uni);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " initial_max_data=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_data);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " initial_max_bidi_streams=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_bidi);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " initial_max_uni_streams=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->initial_max_streams_uni);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_idle_timeout=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS,
- params->max_idle_timeout / NGTCP2_MILLISECONDS);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " max_udp_payload_size=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->max_udp_payload_size);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " ack_delay_exponent=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->ack_delay_exponent);
- log->log_printf(log->user_data, (NGTCP2_LOG_TP " max_ack_delay=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS,
- params->max_ack_delay / NGTCP2_MILLISECONDS);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " active_connection_id_limit=%" PRIu64),
- NGTCP2_LOG_TP_HD_FIELDS, params->active_connection_id_limit);
- log->log_printf(log->user_data,
- (NGTCP2_LOG_TP " disable_active_migration=%d"),
- NGTCP2_LOG_TP_HD_FIELDS, params->disable_active_migration);
-}
-
-void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type,
- uint8_t flags, ngtcp2_tstamp sent_ts) {
- if (!log->log_printf) {
- return;
- }
-
- ngtcp2_log_info(
- log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " lost type=%s(0x%02x) sent_ts=%" PRIu64, pkt_num,
- (flags & NGTCP2_PKT_FLAG_LONG_FORM) ? strpkttype_long(type) : "Short",
- type, sent_ts);
-}
-
-static void log_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const char *dir) {
- uint8_t dcid[sizeof(hd->dcid.data) * 2 + 1];
- uint8_t scid[sizeof(hd->scid.data) * 2 + 1];
-
- if (!log->log_printf) {
- return;
- }
-
- ngtcp2_log_info(
- log, NGTCP2_LOG_EVENT_PKT,
- "%s pkn=%" PRId64 " dcid=0x%s scid=0x%s type=%s(0x%02x) len=%zu k=%d",
- dir, hd->pkt_num,
- (const char *)ngtcp2_encode_hex(dcid, hd->dcid.data, hd->dcid.datalen),
- (const char *)ngtcp2_encode_hex(scid, hd->scid.data, hd->scid.datalen),
- (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) ? strpkttype_long(hd->type)
- : "Short",
- hd->type, hd->len, (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) != 0);
-}
-
-void ngtcp2_log_rx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) {
- log_pkt_hd(log, hd, "rx");
-}
-
-void ngtcp2_log_tx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) {
- log_pkt_hd(log, hd, "tx");
-}
-
-void ngtcp2_log_info(ngtcp2_log *log, ngtcp2_log_event ev, const char *fmt,
- ...) {
- va_list ap;
- int n;
- char buf[NGTCP2_LOG_BUFLEN];
-
- if (!log->log_printf) {
- return;
- }
-
- va_start(ap, fmt);
- n = vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
-
- if (n < 0 || (size_t)n >= sizeof(buf)) {
- return;
- }
-
- log->log_printf(log->user_data, (NGTCP2_LOG_HD " %s"),
- timestamp_cast(log->last_ts - log->ts), log->scid,
- strevent(ev), buf);
-}
-
-void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd) {
- ngtcp2_log_info(log, NGTCP2_LOG_EVENT_PKT,
- "cancel tx pkn=%" PRId64 " type=%s(0x%02x)", hd->pkt_num,
- strpkttype(hd), hd->type);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_log.h b/deps/ngtcp2/lib/ngtcp2_log.h
deleted file mode 100644
index 985aa84b27..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_log.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_LOG_H
-#define NGTCP2_LOG_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_pkt.h"
-
-struct ngtcp2_log {
- /* log_printf is a sink to write log. NULL means no logging
- output. */
- ngtcp2_printf log_printf;
- /* ts is the time point used to write time delta in the log. */
- ngtcp2_tstamp ts;
- /* last_ts is the most recent time point that this object is
- told. */
- ngtcp2_tstamp last_ts;
- /* user_data is user-defined opaque data which is passed to
- log_pritnf. */
- void *user_data;
- /* scid is SCID encoded as NULL-terminated hex string. */
- uint8_t scid[NGTCP2_MAX_CIDLEN * 2 + 1];
-};
-
-typedef struct ngtcp2_log ngtcp2_log;
-
-void ngtcp2_log_init(ngtcp2_log *log, const ngtcp2_cid *scid,
- ngtcp2_printf log_printf, ngtcp2_tstamp ts,
- void *user_data);
-
-void ngtcp2_log_rx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_frame *fr);
-void ngtcp2_log_tx_fr(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const ngtcp2_frame *fr);
-
-void ngtcp2_log_rx_vn(ngtcp2_log *log, const ngtcp2_pkt_hd *hd,
- const uint32_t *sv, size_t nsv);
-
-void ngtcp2_log_rx_sr(ngtcp2_log *log, const ngtcp2_pkt_stateless_reset *sr);
-
-void ngtcp2_log_remote_tp(ngtcp2_log *log, uint8_t exttype,
- const ngtcp2_transport_params *params);
-
-void ngtcp2_log_pkt_lost(ngtcp2_log *log, int64_t pkt_num, uint8_t type,
- uint8_t flags, ngtcp2_tstamp sent_ts);
-
-void ngtcp2_log_rx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd);
-
-void ngtcp2_log_tx_pkt_hd(ngtcp2_log *log, const ngtcp2_pkt_hd *hd);
-
-void ngtcp2_log_tx_cancel(ngtcp2_log *log, const ngtcp2_pkt_hd *hd);
-
-#endif /* NGTCP2_LOG_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_macro.h b/deps/ngtcp2/lib/ngtcp2_macro.h
deleted file mode 100644
index e2603aae15..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_macro.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_MACRO_H
-#define NGTCP2_MACRO_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stddef.h>
-
-#include <ngtcp2/ngtcp2.h>
-
-#define ngtcp2_min(A, B) ((A) < (B) ? (A) : (B))
-#define ngtcp2_max(A, B) ((A) > (B) ? (A) : (B))
-
-#define ngtcp2_struct_of(ptr, type, member) \
- ((type *)(void *)((char *)(ptr)-offsetof(type, member)))
-
-/* ngtcp2_list_insert inserts |T| before |*PD|. The contract is that
- this is singly linked list, and the next element is pointed by next
- field of the previous element. |PD| must be a pointer to the
- pointer to the next field of the previous element of |*PD|: if C is
- the previous element of |PD|, PD = &C->next. */
-#define ngtcp2_list_insert(T, PD) \
- do { \
- (T)->next = *(PD); \
- *(PD) = (T); \
- } while (0)
-
-#endif /* NGTCP2_MACRO_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/lib/ngtcp2_map.c
deleted file mode 100644
index 12a20283b4..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_map.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_map.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_conv.h"
-
-#define INITIAL_TABLE_LENGTH 256
-
-int ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) {
- map->mem = mem;
- map->tablelen = INITIAL_TABLE_LENGTH;
- map->table = ngtcp2_mem_calloc(mem, map->tablelen, sizeof(ngtcp2_map_bucket));
- if (map->table == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- map->size = 0;
-
- return 0;
-}
-
-void ngtcp2_map_free(ngtcp2_map *map) {
- size_t i;
- ngtcp2_map_bucket *bkt;
-
- if (!map) {
- return;
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- if (bkt->ksl) {
- ngtcp2_ksl_free(bkt->ksl);
- ngtcp2_mem_free(map->mem, bkt->ksl);
- }
- }
-
- ngtcp2_mem_free(map->mem, map->table);
-}
-
-void ngtcp2_map_each_free(ngtcp2_map *map,
- int (*func)(ngtcp2_map_entry *entry, void *ptr),
- void *ptr) {
- uint32_t i;
- ngtcp2_map_bucket *bkt;
- ngtcp2_ksl_it it;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- func(bkt->ptr, ptr);
- bkt->ptr = NULL;
- assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- func(ngtcp2_ksl_it_get(&it), ptr);
- }
-
- ngtcp2_ksl_free(bkt->ksl);
- ngtcp2_mem_free(map->mem, bkt->ksl);
- bkt->ksl = NULL;
- }
- }
-}
-
-int ngtcp2_map_each(ngtcp2_map *map,
- int (*func)(ngtcp2_map_entry *entry, void *ptr),
- void *ptr) {
- int rv;
- uint32_t i;
- ngtcp2_map_bucket *bkt;
- ngtcp2_ksl_it it;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- rv = func(bkt->ptr, ptr);
- if (rv != 0) {
- return rv;
- }
- assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- rv = func(ngtcp2_ksl_it_get(&it), ptr);
- if (rv != 0) {
- return rv;
- }
- }
- }
- }
- return 0;
-}
-
-void ngtcp2_map_entry_init(ngtcp2_map_entry *entry, key_type key) {
- entry->key = key;
- entry->next = NULL;
-}
-
-/* FNV1a hash */
-static uint32_t hash(key_type key, uint32_t mod) {
- uint8_t *p, *end;
- uint32_t h = 0x811C9DC5u;
-
- key = ngtcp2_htonl64(key);
- p = (uint8_t *)&key;
- end = p + sizeof(key_type);
-
- for (; p != end;) {
- h ^= *p++;
- h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
- }
-
- return h & (mod - 1);
-}
-
-static int less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *(key_type *)lhs < *(key_type *)rhs;
-}
-
-static int map_insert(ngtcp2_map *map, ngtcp2_map_bucket *table,
- uint32_t tablelen, ngtcp2_map_entry *entry) {
- uint32_t h = hash(entry->key, tablelen);
- ngtcp2_map_bucket *bkt = &table[h];
- const ngtcp2_mem *mem = map->mem;
- int rv;
-
- if (bkt->ptr == NULL && (bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0)) {
- bkt->ptr = entry;
- return 0;
- }
-
- if (!bkt->ksl) {
- bkt->ksl = ngtcp2_mem_malloc(mem, sizeof(*bkt->ksl));
- if (bkt->ksl == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- ngtcp2_ksl_init(bkt->ksl, less, sizeof(key_type), mem);
- }
-
- if (bkt->ptr) {
- rv = ngtcp2_ksl_insert(bkt->ksl, NULL, &bkt->ptr->key, bkt->ptr);
- if (rv != 0) {
- return rv;
- }
-
- bkt->ptr = NULL;
- }
-
- return ngtcp2_ksl_insert(bkt->ksl, NULL, &entry->key, entry);
-}
-
-/* new_tablelen must be power of 2 */
-static int map_resize(ngtcp2_map *map, uint32_t new_tablelen) {
- uint32_t i;
- ngtcp2_map_bucket *new_table;
- ngtcp2_map_bucket *bkt;
- ngtcp2_ksl_it it;
- int rv;
-
- new_table =
- ngtcp2_mem_calloc(map->mem, new_tablelen, sizeof(ngtcp2_map_bucket));
- if (new_table == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
-
- if (bkt->ptr) {
- rv = map_insert(map, new_table, new_tablelen, bkt->ptr);
- if (rv != 0) {
- goto fail;
- }
- assert(bkt->ksl == NULL || ngtcp2_ksl_len(bkt->ksl) == 0);
- continue;
- }
-
- if (bkt->ksl) {
- for (it = ngtcp2_ksl_begin(bkt->ksl); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- rv = map_insert(map, new_table, new_tablelen, ngtcp2_ksl_it_get(&it));
- if (rv != 0) {
- goto fail;
- }
- }
- }
- }
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- if (bkt->ksl) {
- ngtcp2_ksl_free(bkt->ksl);
- ngtcp2_mem_free(map->mem, bkt->ksl);
- }
- }
-
- ngtcp2_mem_free(map->mem, map->table);
- map->tablelen = new_tablelen;
- map->table = new_table;
-
- return 0;
-
-fail:
- for (i = 0; i < new_tablelen; ++i) {
- bkt = &new_table[i];
- if (bkt->ksl) {
- ngtcp2_ksl_free(bkt->ksl);
- ngtcp2_mem_free(map->mem, bkt->ksl);
- }
- }
-
- return rv;
-}
-
-int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_entry *new_entry) {
- int rv;
-
- /* Load factor is 0.75 */
- if ((map->size + 1) * 4 > map->tablelen * 3) {
- rv = map_resize(map, map->tablelen * 2);
- if (rv != 0) {
- return rv;
- }
- }
- rv = map_insert(map, map->table, map->tablelen, new_entry);
- if (rv != 0) {
- return rv;
- }
- ++map->size;
- return 0;
-}
-
-ngtcp2_map_entry *ngtcp2_map_find(ngtcp2_map *map, key_type key) {
- ngtcp2_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
- ngtcp2_ksl_it it;
-
- if (bkt->ptr) {
- if (bkt->ptr->key == key) {
- return bkt->ptr;
- }
- return NULL;
- }
-
- if (bkt->ksl) {
- it = ngtcp2_ksl_lower_bound(bkt->ksl, &key);
- if (ngtcp2_ksl_it_end(&it) || *(key_type *)ngtcp2_ksl_it_key(&it) != key) {
- return NULL;
- }
- return ngtcp2_ksl_it_get(&it);
- }
-
- return NULL;
-}
-
-int ngtcp2_map_remove(ngtcp2_map *map, key_type key) {
- ngtcp2_map_bucket *bkt = &map->table[hash(key, map->tablelen)];
- int rv;
-
- if (bkt->ptr) {
- if (bkt->ptr->key == key) {
- bkt->ptr = NULL;
- --map->size;
- return 0;
- }
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if (bkt->ksl) {
- rv = ngtcp2_ksl_remove(bkt->ksl, NULL, &key);
- if (rv != 0) {
- return rv;
- }
- --map->size;
- return 0;
- }
-
- return NGTCP2_ERR_INVALID_ARGUMENT;
-}
-
-void ngtcp2_map_clear(ngtcp2_map *map) {
- uint32_t i;
- ngtcp2_map_bucket *bkt;
-
- for (i = 0; i < map->tablelen; ++i) {
- bkt = &map->table[i];
- bkt->ptr = NULL;
- if (bkt->ksl) {
- ngtcp2_ksl_free(bkt->ksl);
- ngtcp2_mem_free(map->mem, bkt->ksl);
- bkt->ksl = NULL;
- }
- }
-
- map->size = 0;
-}
-
-size_t ngtcp2_map_size(ngtcp2_map *map) { return map->size; }
diff --git a/deps/ngtcp2/lib/ngtcp2_map.h b/deps/ngtcp2/lib/ngtcp2_map.h
deleted file mode 100644
index 20afce24e9..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_map.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_MAP_H
-#define NGTCP2_MAP_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_ksl.h"
-
-/* Implementation of unordered map */
-
-typedef uint64_t key_type;
-
-typedef struct ngtcp2_map_entry {
- struct ngtcp2_map_entry *next;
- key_type key;
-} ngtcp2_map_entry;
-
-typedef struct ngtcp2_map_bucket {
- ngtcp2_map_entry *ptr;
- ngtcp2_ksl *ksl;
-} ngtcp2_map_bucket;
-
-typedef struct {
- ngtcp2_map_bucket *table;
- const ngtcp2_mem *mem;
- size_t size;
- uint32_t tablelen;
-} ngtcp2_map;
-
-/*
- * Initializes the map |map|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem);
-
-/*
- * Deallocates any resources allocated for |map|. The stored entries
- * are not freed by this function. Use ngtcp2_map_each_free() to free
- * each entries.
- */
-void ngtcp2_map_free(ngtcp2_map *map);
-
-/*
- * Deallocates each entries using |func| function and any resources
- * allocated for |map|. The |func| function is responsible for freeing
- * given the |entry| object. The |ptr| will be passed to the |func| as
- * send argument. The return value of the |func| will be ignored.
- */
-void ngtcp2_map_each_free(ngtcp2_map *map,
- int (*func)(ngtcp2_map_entry *entry, void *ptr),
- void *ptr);
-
-/*
- * Initializes the |entry| with the |key|. All entries to be inserted
- * to the map must be initialized with this function.
- */
-void ngtcp2_map_entry_init(ngtcp2_map_entry *entry, key_type key);
-
-/*
- * Inserts the new |entry| with the key |entry->key| to the map |map|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * The item associated by |key| already exists.
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_entry *entry);
-
-/*
- * Returns the entry associated by the key |key|. If there is no such
- * entry, this function returns NULL.
- */
-ngtcp2_map_entry *ngtcp2_map_find(ngtcp2_map *map, key_type key);
-
-/*
- * Removes the entry associated by the key |key| from the |map|. The
- * removed entry is not freed by this function.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * The entry associated by |key| does not exist.
- */
-int ngtcp2_map_remove(ngtcp2_map *map, key_type key);
-
-/*
- * Removes all entries from |map|.
- */
-void ngtcp2_map_clear(ngtcp2_map *map);
-
-/*
- * Returns the number of items stored in the map |map|.
- */
-size_t ngtcp2_map_size(ngtcp2_map *map);
-
-/*
- * Applies the function |func| to each entry in the |map| with the
- * optional user supplied pointer |ptr|.
- *
- * If the |func| returns 0, this function calls the |func| with the
- * next entry. If the |func| returns nonzero, it will not call the
- * |func| for further entries and return the return value of the
- * |func| immediately. Thus, this function returns 0 if all the
- * invocations of the |func| return 0, or nonzero value which the last
- * invocation of |func| returns.
- *
- * Don't use this function to free each entry. Use
- * ngtcp2_map_each_free() instead.
- */
-int ngtcp2_map_each(ngtcp2_map *map,
- int (*func)(ngtcp2_map_entry *entry, void *ptr), void *ptr);
-
-#endif /* NGTCP2_MAP_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_mem.c b/deps/ngtcp2/lib/ngtcp2_mem.c
deleted file mode 100644
index 2c036ad163..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_mem.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2014 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_mem.h"
-
-static void *default_malloc(size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return malloc(size);
-}
-
-static void default_free(void *ptr, void *mem_user_data) {
- (void)mem_user_data;
-
- free(ptr);
-}
-
-static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return calloc(nmemb, size);
-}
-
-static void *default_realloc(void *ptr, size_t size, void *mem_user_data) {
- (void)mem_user_data;
-
- return realloc(ptr, size);
-}
-
-static const ngtcp2_mem mem_default = {NULL, default_malloc, default_free,
- default_calloc, default_realloc};
-
-const ngtcp2_mem *ngtcp2_mem_default(void) { return &mem_default; }
-
-void *ngtcp2_mem_malloc(const ngtcp2_mem *mem, size_t size) {
- return mem->malloc(size, mem->mem_user_data);
-}
-
-void ngtcp2_mem_free(const ngtcp2_mem *mem, void *ptr) {
- mem->free(ptr, mem->mem_user_data);
-}
-
-void ngtcp2_mem_free2(ngtcp2_free free_func, void *ptr, void *mem_user_data) {
- free_func(ptr, mem_user_data);
-}
-
-void *ngtcp2_mem_calloc(const ngtcp2_mem *mem, size_t nmemb, size_t size) {
- return mem->calloc(nmemb, size, mem->mem_user_data);
-}
-
-void *ngtcp2_mem_realloc(const ngtcp2_mem *mem, void *ptr, size_t size) {
- return mem->realloc(ptr, size, mem->mem_user_data);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_mem.h b/deps/ngtcp2/lib/ngtcp2_mem.h
deleted file mode 100644
index cdecf8763a..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_mem.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2014 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_MEM_H
-#define NGTCP2_MEM_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/* Convenient wrapper functions to call allocator function in
- |mem|. */
-void *ngtcp2_mem_malloc(const ngtcp2_mem *mem, size_t size);
-void ngtcp2_mem_free(const ngtcp2_mem *mem, void *ptr);
-void ngtcp2_mem_free2(ngtcp2_free free_func, void *ptr, void *mem_user_data);
-void *ngtcp2_mem_calloc(const ngtcp2_mem *mem, size_t nmemb, size_t size);
-void *ngtcp2_mem_realloc(const ngtcp2_mem *mem, void *ptr, size_t size);
-
-#endif /* NGTCP2_MEM_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_path.c b/deps/ngtcp2/lib/ngtcp2_path.c
deleted file mode 100644
index 3f35f28ef6..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_path.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_path.h"
-
-#include <string.h>
-
-#include "ngtcp2_addr.h"
-
-void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local,
- const ngtcp2_addr *remote) {
- path->local = *local;
- path->remote = *remote;
-}
-
-void ngtcp2_path_copy(ngtcp2_path *dest, const ngtcp2_path *src) {
- ngtcp2_addr_copy(&dest->local, &src->local);
- ngtcp2_addr_copy(&dest->remote, &src->remote);
-}
-
-int ngtcp2_path_eq(const ngtcp2_path *a, const ngtcp2_path *b) {
- return ngtcp2_addr_eq(&a->local, &b->local) &&
- ngtcp2_addr_eq(&a->remote, &b->remote);
-}
-
-void ngtcp2_path_storage_init(ngtcp2_path_storage *ps,
- const struct sockaddr *local_addr,
- size_t local_addrlen, void *local_user_data,
- const struct sockaddr *remote_addr,
- size_t remote_addrlen, void *remote_user_data) {
- ngtcp2_addr_init(&ps->path.local, (const struct sockaddr *)&ps->local_addrbuf,
- 0, local_user_data);
- ngtcp2_addr_init(&ps->path.remote,
- (const struct sockaddr *)&ps->remote_addrbuf, 0,
- remote_user_data);
-
- ngtcp2_addr_copy_byte(&ps->path.local, local_addr, local_addrlen);
- ngtcp2_addr_copy_byte(&ps->path.remote, remote_addr, remote_addrlen);
-}
-
-void ngtcp2_path_storage_init2(ngtcp2_path_storage *ps,
- const ngtcp2_path *path) {
- ngtcp2_path_storage_init(ps, path->local.addr, path->local.addrlen,
- path->local.user_data, path->remote.addr,
- path->remote.addrlen, path->remote.user_data);
-}
-
-void ngtcp2_path_storage_zero(ngtcp2_path_storage *ps) {
- ngtcp2_addr_init(&ps->path.local, (const struct sockaddr *)&ps->local_addrbuf,
- 0, NULL);
- ngtcp2_addr_init(&ps->path.remote,
- (const struct sockaddr *)&ps->remote_addrbuf, 0, NULL);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_path.h b/deps/ngtcp2/lib/ngtcp2_path.h
deleted file mode 100644
index 1b2e2f87c8..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_path.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_PATH_H
-#define NGTCP2_PATH_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/*
- * ngtcp2_path_init initializes |path| with the given addresses. Note
- * that the buffer pointed by local->addr and remote->addr are not
- * copied. Their pointer values are assigned instead.
- */
-void ngtcp2_path_init(ngtcp2_path *path, const ngtcp2_addr *local,
- const ngtcp2_addr *remote);
-
-/*
- * ngtcp2_path_copy copies |src| into |dest|. This function assumes
- * that |dest| has enough buffer to store the deep copy of src->local
- * and src->remote.
- */
-void ngtcp2_path_copy(ngtcp2_path *dest, const ngtcp2_path *src);
-
-/*
- * ngtcp2_path_eq returns nonzero if |a| equals |b| such that
- * ngtcp2_addr_eq(&a->local, &b->local) && ngtcp2_addr_eq(&a->remote,
- * &b->remote) is true.
- */
-int ngtcp2_path_eq(const ngtcp2_path *a, const ngtcp2_path *b);
-
-/*
- * ngtcp2_path_storage_init2 initializes |ps| using |path| as initial
- * data.
- */
-void ngtcp2_path_storage_init2(ngtcp2_path_storage *ps,
- const ngtcp2_path *path);
-
-#endif /* NGTCP2_PATH_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_pkt.c b/deps/ngtcp2/lib/ngtcp2_pkt.c
deleted file mode 100644
index 905af29a82..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pkt.c
+++ /dev/null
@@ -1,2271 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_pkt.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "ngtcp2_conv.h"
-#include "ngtcp2_str.h"
-#include "ngtcp2_macro.h"
-#include "ngtcp2_cid.h"
-#include "ngtcp2_mem.h"
-
-int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts,
- const ngtcp2_mem *mem) {
- *ppc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pkt_chain) + pktlen);
- if (*ppc == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_path_storage_init2(&(*ppc)->path, path);
- (*ppc)->next = NULL;
- (*ppc)->pkt = (uint8_t *)(*ppc) + sizeof(ngtcp2_pkt_chain);
- (*ppc)->pktlen = pktlen;
- (*ppc)->ts = ts;
-
- memcpy((*ppc)->pkt, pkt, pktlen);
-
- return 0;
-}
-
-void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem) {
- ngtcp2_mem_free(mem, pc);
-}
-
-int ngtcp2_pkt_decode_version_cid(uint32_t *pversion, const uint8_t **pdcid,
- size_t *pdcidlen, const uint8_t **pscid,
- size_t *pscidlen, const uint8_t *data,
- size_t datalen, size_t short_dcidlen) {
- size_t len;
- uint32_t version;
- size_t dcidlen, scidlen;
-
- assert(datalen);
-
- if (data[0] & NGTCP2_HEADER_FORM_BIT) {
- /* 1 byte (Header Form, Fixed Bit, Long Packet Type, Type-Specific bits)
- * 4 bytes Version
- * 1 byte DCID Length
- * 1 byte SCID Length
- */
- len = 1 + 4 + 1 + 1;
- if (datalen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- dcidlen = data[5];
- len += dcidlen;
- if (datalen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- scidlen = data[5 + 1 + dcidlen];
- len += scidlen;
- if (datalen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- version = ngtcp2_get_uint32(&data[1]);
-
- if ((version == 0 || version == NGTCP2_PROTO_VER) &&
- (dcidlen > NGTCP2_MAX_CIDLEN || scidlen > NGTCP2_MAX_CIDLEN)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- *pversion = version;
- *pdcid = &data[6];
- *pdcidlen = dcidlen;
- *pscid = &data[6 + dcidlen + 1];
- *pscidlen = scidlen;
-
- if (version && version != NGTCP2_PROTO_VER) {
- return 1;
- }
- return 0;
- }
-
- assert(short_dcidlen <= NGTCP2_MAX_CIDLEN);
-
- len = 1 + short_dcidlen;
- if (datalen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- *pversion = NGTCP2_PROTO_VER;
- *pdcid = &data[1];
- *pdcidlen = short_dcidlen;
- *pscid = NULL;
- *pscidlen = 0;
-
- return 0;
-}
-
-void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type,
- const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
- int64_t pkt_num, size_t pkt_numlen, uint32_t version,
- size_t len) {
- hd->flags = flags;
- hd->type = type;
- if (dcid) {
- hd->dcid = *dcid;
- } else {
- ngtcp2_cid_zero(&hd->dcid);
- }
- if (scid) {
- hd->scid = *scid;
- } else {
- ngtcp2_cid_zero(&hd->scid);
- }
- hd->pkt_num = pkt_num;
- hd->token.base = NULL;
- hd->token.len = 0;
- hd->pkt_numlen = pkt_numlen;
- hd->version = version;
- hd->len = len;
-}
-
-static int has_mask(uint8_t b, uint8_t mask) { return (b & mask) == mask; }
-
-ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
- size_t pktlen) {
- uint8_t type;
- uint32_t version;
- size_t dcil, scil;
- const uint8_t *p;
- size_t len = 0;
- size_t n;
- size_t ntokenlen = 0;
- const uint8_t *token = NULL;
- size_t tokenlen = 0;
- uint64_t vi;
-
- if (pktlen < 5) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- version = ngtcp2_get_uint32(&pkt[1]);
-
- if (version == 0) {
- type = NGTCP2_PKT_VERSION_NEGOTIATION;
- /* This must be Version Negotiation packet which lacks packet
- number and payload length fields. */
- len = 5 + 2;
- } else {
- if (!(pkt[0] & NGTCP2_FIXED_BIT_MASK)) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- type = ngtcp2_pkt_get_type_long(pkt[0]);
- switch (type) {
- case NGTCP2_PKT_INITIAL:
- len = 1 /* Token Length */ + NGTCP2_MIN_LONG_HEADERLEN -
- 1; /* Cut packet number field */
- break;
- case NGTCP2_PKT_RETRY:
- /* Retry packet does not have packet number and length fields */
- len = 5 + 2;
- break;
- case NGTCP2_PKT_HANDSHAKE:
- case NGTCP2_PKT_0RTT:
- len = NGTCP2_MIN_LONG_HEADERLEN - 1; /* Cut packet number field */
- break;
- default:
- /* Unreachable */
- assert(0);
- }
- }
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- p = &pkt[5];
- dcil = *p;
- if (dcil > NGTCP2_MAX_CIDLEN) {
- /* QUIC v1 implementation never expect to receive CID length more
- than NGTCP2_MAX_CIDLEN. */
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- len += dcil;
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- p += 1 + dcil;
- scil = *p;
- if (scil > NGTCP2_MAX_CIDLEN) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- len += scil;
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- p += 1 + scil;
-
- if (type == NGTCP2_PKT_INITIAL) {
- /* Token Length */
- ntokenlen = ngtcp2_get_varint_len(p);
- len += ntokenlen - 1;
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- vi = ngtcp2_get_varint(&ntokenlen, p);
- if (pktlen - len < vi) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- tokenlen = (size_t)vi;
- len += tokenlen;
-
- p += ntokenlen;
-
- if (tokenlen) {
- token = p;
- }
-
- p += tokenlen;
- }
-
- switch (type) {
- case NGTCP2_PKT_VERSION_NEGOTIATION:
- case NGTCP2_PKT_RETRY:
- break;
- default:
- /* Length */
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- }
-
- dest->flags = NGTCP2_PKT_FLAG_LONG_FORM;
- dest->type = type;
- dest->version = version;
- dest->pkt_num = 0;
- dest->pkt_numlen = 0;
-
- p = &pkt[6];
- ngtcp2_cid_init(&dest->dcid, p, dcil);
- p += dcil + 1;
- ngtcp2_cid_init(&dest->scid, p, scil);
- p += scil;
-
- dest->token.base = (uint8_t *)token;
- dest->token.len = tokenlen;
- p += ntokenlen + tokenlen;
-
- switch (type) {
- case NGTCP2_PKT_VERSION_NEGOTIATION:
- case NGTCP2_PKT_RETRY:
- dest->len = 0;
- break;
- default:
- vi = ngtcp2_get_varint(&n, p);
- if (vi > SIZE_MAX) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
- dest->len = (size_t)vi;
- p += n;
- }
-
- assert((size_t)(p - pkt) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
- size_t pktlen, size_t dcidlen) {
- size_t len = 1 + dcidlen;
- const uint8_t *p = pkt;
-
- assert(dcidlen <= NGTCP2_MAX_CIDLEN);
-
- if (pktlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- if ((pkt[0] & NGTCP2_HEADER_FORM_BIT) ||
- (pkt[0] & NGTCP2_FIXED_BIT_MASK) == 0) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- p = &pkt[1];
-
- dest->type = NGTCP2_PKT_SHORT;
-
- ngtcp2_cid_init(&dest->dcid, p, dcidlen);
- p += dcidlen;
-
- /* Set 0 to SCID so that we don't accidentally reference it and gets
- garbage. */
- ngtcp2_cid_zero(&dest->scid);
-
- dest->flags = NGTCP2_PKT_FLAG_NONE;
- dest->version = 0;
- dest->len = 0;
- dest->pkt_num = 0;
- dest->pkt_numlen = 0;
-
- assert((size_t)(p - pkt) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
- const ngtcp2_pkt_hd *hd) {
- uint8_t *p;
- size_t len = NGTCP2_MIN_LONG_HEADERLEN + hd->dcid.datalen + hd->scid.datalen -
- 2; /* NGTCP2_MIN_LONG_HEADERLEN includes 1 byte for
- len and 1 byte for packet number. */
-
- if (hd->type != NGTCP2_PKT_RETRY) {
- len += 2 /* Length */ + hd->pkt_numlen;
- }
-
- if (hd->type == NGTCP2_PKT_INITIAL) {
- len += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
- }
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_HEADER_FORM_BIT | NGTCP2_FIXED_BIT_MASK |
- (uint8_t)(hd->type << 4) | (uint8_t)(hd->pkt_numlen - 1);
- p = ngtcp2_put_uint32be(p, hd->version);
- *p++ = (uint8_t)hd->dcid.datalen;
- if (hd->dcid.datalen) {
- p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
- }
- *p++ = (uint8_t)hd->scid.datalen;
- if (hd->scid.datalen) {
- p = ngtcp2_cpymem(p, hd->scid.data, hd->scid.datalen);
- }
-
- if (hd->type == NGTCP2_PKT_INITIAL) {
- p = ngtcp2_put_varint(p, hd->token.len);
- if (hd->token.len) {
- p = ngtcp2_cpymem(p, hd->token.base, hd->token.len);
- }
- }
-
- if (hd->type != NGTCP2_PKT_RETRY) {
- p = ngtcp2_put_varint14(p, (uint16_t)hd->len);
- p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
- }
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen,
- const ngtcp2_pkt_hd *hd) {
- uint8_t *p;
- size_t len = 1 + hd->dcid.datalen + hd->pkt_numlen;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p = NGTCP2_FIXED_BIT_MASK | (uint8_t)(hd->pkt_numlen - 1);
- if (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) {
- *p |= NGTCP2_SHORT_KEY_PHASE_BIT;
- }
-
- ++p;
-
- if (hd->dcid.datalen) {
- p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
- }
-
- p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload,
- size_t payloadlen) {
- uint8_t type;
-
- if (payloadlen == 0) {
- return 0;
- }
-
- type = payload[0];
-
- switch (type) {
- case NGTCP2_FRAME_PADDING:
- return (ngtcp2_ssize)ngtcp2_pkt_decode_padding_frame(&dest->padding,
- payload, payloadlen);
- case NGTCP2_FRAME_RESET_STREAM:
- return ngtcp2_pkt_decode_reset_stream_frame(&dest->reset_stream, payload,
- payloadlen);
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- return ngtcp2_pkt_decode_connection_close_frame(&dest->connection_close,
- payload, payloadlen);
- case NGTCP2_FRAME_MAX_DATA:
- return ngtcp2_pkt_decode_max_data_frame(&dest->max_data, payload,
- payloadlen);
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- return ngtcp2_pkt_decode_max_stream_data_frame(&dest->max_stream_data,
- payload, payloadlen);
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- return ngtcp2_pkt_decode_max_streams_frame(&dest->max_streams, payload,
- payloadlen);
- case NGTCP2_FRAME_PING:
- return ngtcp2_pkt_decode_ping_frame(&dest->ping, payload, payloadlen);
- case NGTCP2_FRAME_DATA_BLOCKED:
- return ngtcp2_pkt_decode_data_blocked_frame(&dest->data_blocked, payload,
- payloadlen);
- case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
- return ngtcp2_pkt_decode_stream_data_blocked_frame(
- &dest->stream_data_blocked, payload, payloadlen);
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- return ngtcp2_pkt_decode_streams_blocked_frame(&dest->streams_blocked,
- payload, payloadlen);
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- return ngtcp2_pkt_decode_new_connection_id_frame(&dest->new_connection_id,
- payload, payloadlen);
- case NGTCP2_FRAME_STOP_SENDING:
- return ngtcp2_pkt_decode_stop_sending_frame(&dest->stop_sending, payload,
- payloadlen);
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen);
- case NGTCP2_FRAME_PATH_CHALLENGE:
- return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge,
- payload, payloadlen);
- case NGTCP2_FRAME_PATH_RESPONSE:
- return ngtcp2_pkt_decode_path_response_frame(&dest->path_response, payload,
- payloadlen);
- case NGTCP2_FRAME_CRYPTO:
- return ngtcp2_pkt_decode_crypto_frame(&dest->crypto, payload, payloadlen);
- case NGTCP2_FRAME_NEW_TOKEN:
- return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload,
- payloadlen);
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- return ngtcp2_pkt_decode_retire_connection_id_frame(
- &dest->retire_connection_id, payload, payloadlen);
- case NGTCP2_FRAME_HANDSHAKE_DONE:
- return ngtcp2_pkt_decode_handshake_done_frame(&dest->handshake_done,
- payload, payloadlen);
- default:
- if (has_mask(type, NGTCP2_FRAME_STREAM)) {
- return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen);
- }
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- uint8_t type;
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t datalen;
- size_t ndatalen = 0;
- size_t n;
- uint64_t vi;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- type = payload[0];
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- if (type & NGTCP2_STREAM_OFF_BIT) {
- ++len;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
- }
-
- if (type & NGTCP2_STREAM_LEN_BIT) {
- ++len;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- ndatalen = ngtcp2_get_varint_len(p);
- len += ndatalen - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- vi = ngtcp2_get_varint(&ndatalen, p);
- if (payloadlen - len < vi) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- datalen = (size_t)vi;
- len += datalen;
- } else {
- len = payloadlen;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_STREAM;
- dest->flags = (uint8_t)(type & ~NGTCP2_FRAME_STREAM);
- dest->fin = (type & NGTCP2_STREAM_FIN_BIT) != 0;
- dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
-
- if (type & NGTCP2_STREAM_OFF_BIT) {
- dest->offset = ngtcp2_get_varint(&n, p);
- p += n;
- } else {
- dest->offset = 0;
- }
-
- if (type & NGTCP2_STREAM_LEN_BIT) {
- p += ndatalen;
- } else {
- datalen = payloadlen - (size_t)(p - payload);
- }
-
- if (datalen) {
- dest->data[0].len = datalen;
- dest->data[0].base = (uint8_t *)p;
- dest->datacnt = 1;
- p += datalen;
- } else {
- dest->datacnt = 0;
- }
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t num_blks, max_num_blks;
- size_t nnum_blks;
- size_t len = 1 + 1 + 1 + 1 + 1;
- const uint8_t *p;
- size_t i, j;
- ngtcp2_ack_blk *blk;
- size_t n;
- uint8_t type;
- uint64_t vi;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- type = payload[0];
-
- p = payload + 1;
-
- /* Largest Acknowledged */
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- /* ACK Delay */
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- /* ACK Block Count */
- nnum_blks = ngtcp2_get_varint_len(p);
- len += nnum_blks - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- vi = ngtcp2_get_varint(&nnum_blks, p);
- if (vi > SIZE_MAX / (1 + 1) || payloadlen - len < vi * (1 + 1)) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- num_blks = (size_t)vi;
- len += num_blks * (1 + 1);
-
- p += nnum_blks;
-
- /* First ACK Block */
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- for (i = 0; i < num_blks; ++i) {
- /* Gap, and Additional ACK Block */
- for (j = 0; j < 2; ++j) {
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
- }
- }
-
- if (type == NGTCP2_FRAME_ACK_ECN) {
- len += 3;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- for (i = 0; i < 3; ++i) {
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
- }
- }
-
- /* TODO We might not decode all blocks. It could be very large. */
- max_num_blks = ngtcp2_min(NGTCP2_MAX_ACK_BLKS, num_blks);
-
- p = payload + 1;
-
- dest->type = type;
- dest->largest_ack = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
- dest->ack_delay = ngtcp2_get_varint(&n, p);
- /* This value will be assigned in the upper layer. */
- dest->ack_delay_unscaled = 0;
- p += n;
- dest->num_blks = max_num_blks;
- p += nnum_blks;
- dest->first_ack_blklen = ngtcp2_get_varint(&n, p);
- p += n;
-
- for (i = 0; i < max_num_blks; ++i) {
- blk = &dest->blks[i];
- blk->gap = ngtcp2_get_varint(&n, p);
- p += n;
- blk->blklen = ngtcp2_get_varint(&n, p);
- p += n;
- }
- for (i = max_num_blks; i < num_blks; ++i) {
- p += ngtcp2_get_varint_len(p);
- p += ngtcp2_get_varint_len(p);
- }
-
- if (type == NGTCP2_FRAME_ACK_ECN) {
- /* Just parse ECN section for now */
- for (i = 0; i < 3; ++i) {
- ngtcp2_get_varint(&n, p);
- p += n;
- }
- }
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- const uint8_t *p, *ep;
-
- assert(payloadlen > 0);
-
- p = payload + 1;
- ep = payload + payloadlen;
-
- for (; p != ep && *p == NGTCP2_FRAME_PADDING; ++p)
- ;
-
- dest->type = NGTCP2_FRAME_PADDING;
- dest->len = (size_t)(p - payload);
-
- return dest->len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1 + 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- p += n;
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- p += n;
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_RESET_STREAM;
- dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
- dest->app_error_code = ngtcp2_get_varint(&n, p);
- p += n;
- dest->final_size = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
- ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen) {
- size_t len = 1 + 1 + 1;
- const uint8_t *p;
- size_t reasonlen;
- size_t nreasonlen;
- size_t n;
- uint8_t type;
- uint64_t vi;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- type = payload[0];
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
- ++len;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
- }
-
- nreasonlen = ngtcp2_get_varint_len(p);
- len += nreasonlen - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- vi = ngtcp2_get_varint(&nreasonlen, p);
- if (payloadlen - len < vi) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- reasonlen = (size_t)vi;
- len += reasonlen;
-
- p = payload + 1;
-
- dest->type = type;
- dest->error_code = ngtcp2_get_varint(&n, p);
- p += n;
- if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
- dest->frame_type = ngtcp2_get_varint(&n, p);
- p += n;
- } else {
- dest->frame_type = 0;
- }
- dest->reasonlen = reasonlen;
- p += nreasonlen;
- if (reasonlen == 0) {
- dest->reason = NULL;
- } else {
- dest->reason = (uint8_t *)p;
- p += reasonlen;
- }
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- dest->type = NGTCP2_FRAME_MAX_DATA;
- dest->max_data = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame(
- ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen) {
- size_t len = 1 + 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_MAX_STREAM_DATA;
- dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
- dest->max_stream_data = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- dest->type = payload[0];
- dest->max_streams = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- (void)payload;
- (void)payloadlen;
-
- dest->type = NGTCP2_FRAME_PING;
- return 1;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- dest->type = NGTCP2_FRAME_DATA_BLOCKED;
- dest->offset = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
- dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
- dest->offset = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame(
- ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- dest->type = payload[0];
- dest->stream_limit = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame(
- ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen) {
- size_t len = 1 + 1 + 1 + 1 + 16;
- const uint8_t *p;
- size_t n;
- size_t cil;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- cil = *p;
- if (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- len += cil;
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_NEW_CONNECTION_ID;
- dest->seq = ngtcp2_get_varint(&n, p);
- p += n;
- dest->retire_prior_to = ngtcp2_get_varint(&n, p);
- p += n + 1;
- ngtcp2_cid_init(&dest->cid, p, cil);
- p += cil;
- memcpy(dest->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
- p += NGTCP2_STATELESS_RESET_TOKENLEN;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- p += n;
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_STOP_SENDING;
- dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
- p += n;
- dest->app_error_code = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 8;
- const uint8_t *p;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_PATH_CHALLENGE;
- ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
- p += sizeof(dest->data);
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 8;
- const uint8_t *p;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_PATH_RESPONSE;
- ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
- p += sizeof(dest->data);
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1 + 1;
- const uint8_t *p;
- size_t datalen;
- size_t ndatalen;
- size_t n;
- uint64_t vi;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p += n;
-
- ndatalen = ngtcp2_get_varint_len(p);
- len += ndatalen - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- vi = ngtcp2_get_varint(&ndatalen, p);
- if (payloadlen - len < vi) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- datalen = (size_t)vi;
- len += datalen;
-
- p = payload + 1;
-
- dest->type = NGTCP2_FRAME_CRYPTO;
- dest->offset = ngtcp2_get_varint(&n, p);
- p += n;
- dest->data[0].len = datalen;
- p += ndatalen;
- if (dest->data[0].len) {
- dest->data[0].base = (uint8_t *)p;
- p += dest->data[0].len;
- dest->datacnt = 1;
- } else {
- dest->data[0].base = NULL;
- dest->datacnt = 0;
- }
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
- size_t datalen;
- uint64_t vi;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- vi = ngtcp2_get_varint(&n, p);
- if (payloadlen - len < vi) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
- datalen = (size_t)vi;
- len += datalen;
-
- dest->type = NGTCP2_FRAME_NEW_TOKEN;
- dest->token.len = datalen;
- p += n;
- dest->token.base = (uint8_t *)p;
- p += dest->token.len;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- size_t len = 1 + 1;
- const uint8_t *p;
- size_t n;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- p = payload + 1;
-
- n = ngtcp2_get_varint_len(p);
- len += n - 1;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_FRAME_ENCODING;
- }
-
- dest->type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
- dest->seq = ngtcp2_get_varint(&n, p);
- p += n;
-
- assert((size_t)(p - payload) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- (void)payload;
- (void)payloadlen;
-
- dest->type = NGTCP2_FRAME_HANDSHAKE_DONE;
- return 1;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen,
- ngtcp2_frame *fr) {
- switch (fr->type) {
- case NGTCP2_FRAME_STREAM:
- return ngtcp2_pkt_encode_stream_frame(out, outlen, &fr->stream);
- case NGTCP2_FRAME_ACK:
- return ngtcp2_pkt_encode_ack_frame(out, outlen, &fr->ack);
- case NGTCP2_FRAME_PADDING:
- return ngtcp2_pkt_encode_padding_frame(out, outlen, &fr->padding);
- case NGTCP2_FRAME_RESET_STREAM:
- return ngtcp2_pkt_encode_reset_stream_frame(out, outlen, &fr->reset_stream);
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- return ngtcp2_pkt_encode_connection_close_frame(out, outlen,
- &fr->connection_close);
- case NGTCP2_FRAME_MAX_DATA:
- return ngtcp2_pkt_encode_max_data_frame(out, outlen, &fr->max_data);
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- return ngtcp2_pkt_encode_max_stream_data_frame(out, outlen,
- &fr->max_stream_data);
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- return ngtcp2_pkt_encode_max_streams_frame(out, outlen, &fr->max_streams);
- case NGTCP2_FRAME_PING:
- return ngtcp2_pkt_encode_ping_frame(out, outlen, &fr->ping);
- case NGTCP2_FRAME_DATA_BLOCKED:
- return ngtcp2_pkt_encode_data_blocked_frame(out, outlen, &fr->data_blocked);
- case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
- return ngtcp2_pkt_encode_stream_data_blocked_frame(
- out, outlen, &fr->stream_data_blocked);
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- return ngtcp2_pkt_encode_streams_blocked_frame(out, outlen,
- &fr->streams_blocked);
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- return ngtcp2_pkt_encode_new_connection_id_frame(out, outlen,
- &fr->new_connection_id);
- case NGTCP2_FRAME_STOP_SENDING:
- return ngtcp2_pkt_encode_stop_sending_frame(out, outlen, &fr->stop_sending);
- case NGTCP2_FRAME_PATH_CHALLENGE:
- return ngtcp2_pkt_encode_path_challenge_frame(out, outlen,
- &fr->path_challenge);
- case NGTCP2_FRAME_PATH_RESPONSE:
- return ngtcp2_pkt_encode_path_response_frame(out, outlen,
- &fr->path_response);
- case NGTCP2_FRAME_CRYPTO:
- return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->crypto);
- case NGTCP2_FRAME_NEW_TOKEN:
- return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token);
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- return ngtcp2_pkt_encode_retire_connection_id_frame(
- out, outlen, &fr->retire_connection_id);
- case NGTCP2_FRAME_HANDSHAKE_DONE:
- return ngtcp2_pkt_encode_handshake_done_frame(out, outlen,
- &fr->handshake_done);
- default:
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen,
- ngtcp2_stream *fr) {
- size_t len = 1;
- uint8_t flags = NGTCP2_STREAM_LEN_BIT;
- uint8_t *p;
- size_t i;
- size_t datalen = 0;
-
- if (fr->fin) {
- flags |= NGTCP2_STREAM_FIN_BIT;
- }
-
- if (fr->offset) {
- flags |= NGTCP2_STREAM_OFF_BIT;
- len += ngtcp2_put_varint_len(fr->offset);
- }
-
- len += ngtcp2_put_varint_len((uint64_t)fr->stream_id);
-
- for (i = 0; i < fr->datacnt; ++i) {
- datalen += fr->data[i].len;
- }
-
- len += ngtcp2_put_varint_len(datalen);
- len += datalen;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = flags | NGTCP2_FRAME_STREAM;
-
- fr->flags = flags;
-
- p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
-
- if (fr->offset) {
- p = ngtcp2_put_varint(p, fr->offset);
- }
-
- p = ngtcp2_put_varint(p, datalen);
-
- for (i = 0; i < fr->datacnt; ++i) {
- assert(fr->data[i].len);
- assert(fr->data[i].base);
- p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
- }
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen,
- ngtcp2_ack *fr) {
- size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->largest_ack) +
- ngtcp2_put_varint_len(fr->ack_delay) +
- ngtcp2_put_varint_len(fr->num_blks) +
- ngtcp2_put_varint_len(fr->first_ack_blklen);
- uint8_t *p;
- size_t i;
- const ngtcp2_ack_blk *blk;
-
- for (i = 0; i < fr->num_blks; ++i) {
- blk = &fr->blks[i];
- len += ngtcp2_put_varint_len(blk->gap);
- len += ngtcp2_put_varint_len(blk->blklen);
- }
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_ACK;
- p = ngtcp2_put_varint(p, (uint64_t)fr->largest_ack);
- p = ngtcp2_put_varint(p, fr->ack_delay);
- p = ngtcp2_put_varint(p, fr->num_blks);
- p = ngtcp2_put_varint(p, fr->first_ack_blklen);
-
- for (i = 0; i < fr->num_blks; ++i) {
- blk = &fr->blks[i];
- p = ngtcp2_put_varint(p, blk->gap);
- p = ngtcp2_put_varint(p, blk->blklen);
- }
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen,
- const ngtcp2_padding *fr) {
- if (outlen < fr->len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- memset(out, 0, fr->len);
-
- return (ngtcp2_ssize)fr->len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
- const ngtcp2_reset_stream *fr) {
- size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
- ngtcp2_put_varint_len(fr->app_error_code) +
- ngtcp2_put_varint_len(fr->final_size);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_RESET_STREAM;
- p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
- p = ngtcp2_put_varint(p, fr->app_error_code);
- p = ngtcp2_put_varint(p, fr->final_size);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
- const ngtcp2_connection_close *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->error_code) +
- (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
- ? ngtcp2_put_varint_len(fr->frame_type)
- : 0) +
- ngtcp2_put_varint_len(fr->reasonlen) + fr->reasonlen;
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = fr->type;
- p = ngtcp2_put_varint(p, fr->error_code);
- if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) {
- p = ngtcp2_put_varint(p, fr->frame_type);
- }
- p = ngtcp2_put_varint(p, fr->reasonlen);
- if (fr->reasonlen) {
- p = ngtcp2_cpymem(p, fr->reason, fr->reasonlen);
- }
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_data *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->max_data);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_MAX_DATA;
- p = ngtcp2_put_varint(p, fr->max_data);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_stream_data *fr) {
- size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
- ngtcp2_put_varint_len(fr->max_stream_data);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_MAX_STREAM_DATA;
- p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
- p = ngtcp2_put_varint(p, fr->max_stream_data);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_streams *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = fr->type;
- p = ngtcp2_put_varint(p, fr->max_streams);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_ping_frame(uint8_t *out, size_t outlen,
- const ngtcp2_ping *fr) {
- (void)fr;
-
- if (outlen < 1) {
- return NGTCP2_ERR_NOBUF;
- }
-
- *out++ = NGTCP2_FRAME_PING;
-
- return 1;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen,
- const ngtcp2_data_blocked *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->offset);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_DATA_BLOCKED;
- p = ngtcp2_put_varint(p, fr->offset);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame(
- uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) {
- size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
- ngtcp2_put_varint_len(fr->offset);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
- p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
- p = ngtcp2_put_varint(p, fr->offset);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen,
- const ngtcp2_streams_blocked *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->stream_limit);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = fr->type;
- p = ngtcp2_put_varint(p, fr->stream_limit);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen,
- const ngtcp2_new_connection_id *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->seq) +
- ngtcp2_put_varint_len(fr->retire_prior_to) + 1 +
- fr->cid.datalen + NGTCP2_STATELESS_RESET_TOKENLEN;
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_NEW_CONNECTION_ID;
- p = ngtcp2_put_varint(p, fr->seq);
- p = ngtcp2_put_varint(p, fr->retire_prior_to);
- *p++ = (uint8_t)fr->cid.datalen;
- p = ngtcp2_cpymem(p, fr->cid.data, fr->cid.datalen);
- p = ngtcp2_cpymem(p, fr->stateless_reset_token,
- NGTCP2_STATELESS_RESET_TOKENLEN);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
- const ngtcp2_stop_sending *fr) {
- size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
- ngtcp2_put_varint_len(fr->app_error_code);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_STOP_SENDING;
- p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
- p = ngtcp2_put_varint(p, fr->app_error_code);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_path_challenge_frame(uint8_t *out, size_t outlen,
- const ngtcp2_path_challenge *fr) {
- size_t len = 1 + 8;
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_PATH_CHALLENGE;
- p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen,
- const ngtcp2_path_response *fr) {
- size_t len = 1 + 8;
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_PATH_RESPONSE;
- p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen,
- const ngtcp2_crypto *fr) {
- size_t len = 1;
- uint8_t *p;
- size_t i;
- size_t datalen = 0;
-
- len += ngtcp2_put_varint_len(fr->offset);
-
- for (i = 0; i < fr->datacnt; ++i) {
- datalen += fr->data[i].len;
- }
-
- len += ngtcp2_put_varint_len(datalen);
- len += datalen;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_CRYPTO;
-
- p = ngtcp2_put_varint(p, fr->offset);
- p = ngtcp2_put_varint(p, datalen);
-
- for (i = 0; i < fr->datacnt; ++i) {
- assert(fr->data[i].base);
- p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
- }
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
- const ngtcp2_new_token *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->token.len) + fr->token.len;
- uint8_t *p;
-
- assert(fr->token.len);
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_NEW_TOKEN;
-
- p = ngtcp2_put_varint(p, fr->token.len);
- p = ngtcp2_cpymem(p, fr->token.base, fr->token.len);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame(
- uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) {
- size_t len = 1 + ngtcp2_put_varint_len(fr->seq);
- uint8_t *p;
-
- if (outlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = out;
-
- *p++ = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
-
- p = ngtcp2_put_varint(p, fr->seq);
-
- assert((size_t)(p - out) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_encode_handshake_done_frame(uint8_t *out, size_t outlen,
- const ngtcp2_handshake_done *fr) {
- (void)fr;
-
- if (outlen < 1) {
- return NGTCP2_ERR_NOBUF;
- }
-
- *out++ = NGTCP2_FRAME_HANDSHAKE_DONE;
-
- return 1;
-}
-
-ngtcp2_ssize ngtcp2_pkt_write_version_negotiation(
- uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid,
- size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv,
- size_t nsv) {
- size_t len = 1 + 4 + 1 + dcidlen + 1 + scidlen + nsv * 4;
- uint8_t *p;
- size_t i;
-
- assert(dcidlen < 256);
- assert(scidlen < 256);
-
- if (destlen < len) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = dest;
-
- *p++ = 0x80 | unused_random;
- p = ngtcp2_put_uint32be(p, 0);
- *p++ = (uint8_t)dcidlen;
- if (dcidlen) {
- p = ngtcp2_cpymem(p, dcid, dcidlen);
- }
- *p++ = (uint8_t)scidlen;
- if (scidlen) {
- p = ngtcp2_cpymem(p, scid, scidlen);
- }
-
- for (i = 0; i < nsv; ++i) {
- p = ngtcp2_put_uint32be(p, sv[i]);
- }
-
- assert((size_t)(p - dest) == len);
-
- return (ngtcp2_ssize)len;
-}
-
-size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest,
- const uint8_t *payload,
- size_t payloadlen) {
- const uint8_t *end = payload + payloadlen;
-
- assert((payloadlen % sizeof(uint32_t)) == 0);
-
- for (; payload != end; payload += sizeof(uint32_t)) {
- *dest++ = ngtcp2_get_uint32(payload);
- }
-
- return payloadlen / sizeof(uint32_t);
-}
-
-int ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset *sr,
- const uint8_t *payload,
- size_t payloadlen) {
- const uint8_t *p = payload;
-
- if (payloadlen <
- NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- sr->rand = p;
- sr->randlen = payloadlen - NGTCP2_STATELESS_RESET_TOKENLEN;
- p += sr->randlen;
- memcpy(sr->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
-
- return 0;
-}
-
-int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload,
- size_t payloadlen) {
- size_t len = /* token */ 1 + NGTCP2_RETRY_TAGLEN;
-
- if (payloadlen < len) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- dest->token.base = (uint8_t *)payload;
- dest->token.len = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN);
- ngtcp2_cpymem(dest->tag, payload + dest->token.len, NGTCP2_RETRY_TAGLEN);
-
- return 0;
-}
-
-int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num,
- size_t n) {
- int64_t expected = max_pkt_num + 1;
- int64_t win = (int64_t)1 << n;
- int64_t hwin = win / 2;
- int64_t mask = win - 1;
- int64_t cand = (expected & ~mask) | pkt_num;
-
- if (cand <= expected - hwin) {
- assert(cand <= (int64_t)NGTCP2_MAX_VARINT - win);
- return cand + win;
- }
- if (cand > expected + hwin && cand >= win) {
- return cand - win;
- }
- return cand;
-}
-
-int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr) {
- int64_t largest_ack = fr->largest_ack;
- size_t i;
-
- if (largest_ack < (int64_t)fr->first_ack_blklen) {
- return NGTCP2_ERR_ACK_FRAME;
- }
-
- largest_ack -= (int64_t)fr->first_ack_blklen;
-
- for (i = 0; i < fr->num_blks; ++i) {
- if (largest_ack < (int64_t)fr->blks[i].gap + 2) {
- return NGTCP2_ERR_ACK_FRAME;
- }
-
- largest_ack -= (int64_t)fr->blks[i].gap + 2;
-
- if (largest_ack < (int64_t)fr->blks[i].blklen) {
- return NGTCP2_ERR_ACK_FRAME;
- }
-
- largest_ack -= (int64_t)fr->blks[i].blklen;
- }
-
- return 0;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
- const uint8_t *stateless_reset_token,
- const uint8_t *rand, size_t randlen) {
- uint8_t *p;
-
- if (destlen <
- NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
- return NGTCP2_ERR_NOBUF;
- }
-
- if (randlen < NGTCP2_MIN_STATELESS_RESET_RANDLEN) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- p = dest;
-
- randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen);
-
- p = ngtcp2_cpymem(p, rand, randlen);
- p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN);
- *dest = (uint8_t)((*dest & 0x7fu) | 0x40u);
-
- return p - dest;
-}
-
-ngtcp2_ssize
-ngtcp2_pkt_write_retry(uint8_t *dest, size_t destlen, const ngtcp2_cid *dcid,
- const ngtcp2_cid *scid, const ngtcp2_cid *odcid,
- const uint8_t *token, size_t tokenlen,
- ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx) {
- ngtcp2_pkt_hd hd;
- uint8_t pseudo_retry[1500];
- ngtcp2_ssize pseudo_retrylen;
- uint8_t tag[NGTCP2_RETRY_TAGLEN];
- int rv;
- uint8_t *p;
- size_t offset;
-
- assert(tokenlen > 0);
- assert(!ngtcp2_cid_eq(scid, odcid));
-
- /* Retry packet is sent at most once per one connection attempt. In
- the first connection attempt, client has to send random DCID
- which is at least 8 bytes long. */
- if (odcid->datalen < 8) {
- return NGTCP2_ERR_INVALID_ARGUMENT;
- }
-
- ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_RETRY, dcid,
- scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1,
- NGTCP2_PROTO_VER, /* len = */ 0);
-
- pseudo_retrylen =
- ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd,
- /* unused = */ 0, odcid, token, tokenlen);
- if (pseudo_retrylen < 0) {
- return pseudo_retrylen;
- }
-
- /* OpenSSL does not like NULL plaintext. */
- rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0,
- (const uint8_t *)NGTCP2_RETRY_NONCE,
- sizeof(NGTCP2_RETRY_NONCE) - 1, pseudo_retry,
- (size_t)pseudo_retrylen);
- if (rv != 0) {
- return rv;
- }
-
- offset = 1 + odcid->datalen;
- if (destlen < (size_t)pseudo_retrylen + sizeof(tag) - offset) {
- return NGTCP2_ERR_NOBUF;
- }
-
- p = ngtcp2_cpymem(dest, pseudo_retry + offset,
- (size_t)pseudo_retrylen - offset);
- p = ngtcp2_cpymem(p, tag, sizeof(tag));
-
- return p - dest;
-}
-
-ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
- uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused,
- const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen) {
- uint8_t *p = dest;
- ngtcp2_ssize nwrite;
-
- if (destlen < 1 + odcid->datalen) {
- return NGTCP2_ERR_NOBUF;
- }
-
- *p++ = (uint8_t)odcid->datalen;
- p = ngtcp2_cpymem(p, odcid->data, odcid->datalen);
- destlen -= (size_t)(p - dest);
-
- nwrite = ngtcp2_pkt_encode_hd_long(p, destlen, hd);
- if (nwrite < 0) {
- return nwrite;
- }
-
- if (destlen < (size_t)nwrite + tokenlen) {
- return NGTCP2_ERR_NOBUF;
- }
-
- *p &= 0xf0;
- *p |= unused;
-
- p += nwrite;
-
- p = ngtcp2_cpymem(p, token, tokenlen);
-
- return p - dest;
-}
-
-int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_encrypt encrypt,
- const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx) {
- uint8_t pseudo_retry[1500];
- size_t pseudo_retrylen;
- uint8_t *p = pseudo_retry;
- int rv;
- uint8_t tag[NGTCP2_RETRY_TAGLEN];
-
- assert(pktlen >= sizeof(retry->tag));
-
- if (sizeof(pseudo_retry) <
- 1 + retry->odcid.datalen + pktlen - sizeof(retry->tag)) {
- return NGTCP2_ERR_PROTO;
- }
-
- *p++ = (uint8_t)retry->odcid.datalen;
- p = ngtcp2_cpymem(p, retry->odcid.data, retry->odcid.datalen);
- p = ngtcp2_cpymem(p, pkt, pktlen - sizeof(retry->tag));
-
- pseudo_retrylen = (size_t)(p - pseudo_retry);
-
- /* OpenSSL does not like NULL plaintext. */
- rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0,
- (const uint8_t *)NGTCP2_RETRY_NONCE,
- sizeof(NGTCP2_RETRY_NONCE) - 1, pseudo_retry, pseudo_retrylen);
- if (rv != 0) {
- return rv;
- }
-
- if (0 != memcmp(retry->tag, tag, sizeof(retry->tag))) {
- return NGTCP2_ERR_PROTO;
- }
-
- return 0;
-}
-
-size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
- size_t len, size_t left) {
- size_t n = 1 /* type */ + ngtcp2_put_varint_len((uint64_t)stream_id) +
- (offset ? ngtcp2_put_varint_len(offset) : 0);
-
- if (left <= n) {
- return (size_t)-1;
- }
-
- left -= n;
-
- if (left > 8 + 1073741823 && len > 1073741823) {
-#if SIZE_MAX > UINT32_MAX
- len = ngtcp2_min(len, 4611686018427387903lu);
-#endif /* SIZE_MAX > UINT32_MAX */
- return ngtcp2_min(len, left - 8);
- }
-
- if (left > 4 + 16383 && len > 16383) {
- len = ngtcp2_min(len, 1073741823);
- return ngtcp2_min(len, left - 4);
- }
-
- if (left > 2 + 63 && len > 63) {
- len = ngtcp2_min(len, 16383);
- return ngtcp2_min(len, left - 2);
- }
-
- len = ngtcp2_min(len, 63);
- return ngtcp2_min(len, left - 1);
-}
-
-size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
- size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset);
-
- /* CRYPTO frame must contain nonzero length data. Return -1 if
- there is no space to write crypto data. */
- if (left <= n + 1) {
- return (size_t)-1;
- }
-
- left -= n;
-
- if (left > 8 + 1073741823 && len > 1073741823) {
-#if SIZE_MAX > UINT32_MAX
- len = ngtcp2_min(len, 4611686018427387903lu);
-#endif /* SIZE_MAX > UINT32_MAX */
- return ngtcp2_min(len, left - 8);
- }
-
- if (left > 4 + 16383 && len > 16383) {
- len = ngtcp2_min(len, 1073741823);
- return ngtcp2_min(len, left - 4);
- }
-
- if (left > 2 + 63 && len > 63) {
- len = ngtcp2_min(len, 16383);
- return ngtcp2_min(len, left - 2);
- }
-
- len = ngtcp2_min(len, 63);
- return ngtcp2_min(len, left - 1);
-}
-
-uint8_t ngtcp2_pkt_get_type_long(uint8_t c) {
- return (uint8_t)((c & NGTCP2_LONG_TYPE_MASK) >> 4);
-}
-
-int ngtcp2_pkt_verify_reserved_bits(uint8_t c) {
- if (c & NGTCP2_HEADER_FORM_BIT) {
- return (c & NGTCP2_LONG_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
- }
- return (c & NGTCP2_SHORT_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_pkt.h b/deps/ngtcp2/lib/ngtcp2_pkt.h
deleted file mode 100644
index 7348cb9a9d..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pkt.h
+++ /dev/null
@@ -1,1126 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_PKT_H
-#define NGTCP2_PKT_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/* QUIC header macros */
-#define NGTCP2_HEADER_FORM_BIT 0x80
-#define NGTCP2_FIXED_BIT_MASK 0x40
-#define NGTCP2_PKT_NUMLEN_MASK 0x03
-
-/* Long header specific macros */
-#define NGTCP2_LONG_TYPE_MASK 0x30
-#define NGTCP2_LONG_RESERVED_BIT_MASK 0x0c
-
-/* Short header specific macros */
-#define NGTCP2_SHORT_SPIN_BIT_MASK 0x20
-#define NGTCP2_SHORT_RESERVED_BIT_MASK 0x18
-#define NGTCP2_SHORT_KEY_PHASE_BIT 0x04
-
-/* NGTCP2_SR_TYPE is a Type field of Stateless Reset. */
-#define NGTCP2_SR_TYPE 0x1f
-
-/* NGTCP2_MIN_LONG_HEADERLEN is the minimum length of long header.
- That is (1|1|TT|RR|PP)<1> + VERSION<4> + DCIL<1> + SCIL<1> +
- LENGTH<1> + PKN<1> */
-#define NGTCP2_MIN_LONG_HEADERLEN (1 + 4 + 1 + 1 + 1 + 1)
-
-#define NGTCP2_STREAM_FIN_BIT 0x01
-#define NGTCP2_STREAM_LEN_BIT 0x02
-#define NGTCP2_STREAM_OFF_BIT 0x04
-
-/* NGTCP2_STREAM_OVERHEAD is the maximum number of bytes required
- other than payload for STREAM frame. That is from type field to
- the beginning of the payload. */
-#define NGTCP2_STREAM_OVERHEAD (1 + 8 + 8 + 8)
-
-/* NGTCP2_CRYPTO_OVERHEAD is the maximum number of bytes required
- other than payload for CRYPTO frame. That is from type field to
- the beginning of the payload. */
-#define NGTCP2_CRYPTO_OVERHEAD (1 + 8 + 8)
-
-/* NGTCP2_MIN_FRAME_PAYLOADLEN is the minimum frame payload length. */
-#define NGTCP2_MIN_FRAME_PAYLOADLEN 16
-
-/* NGTCP2_MAX_VARINT is the maximum value which can be encoded in
- variable-length integer encoding */
-#define NGTCP2_MAX_VARINT ((1ULL << 62) - 1)
-
-/* NGTCP2_MAX_SERVER_STREAM_ID_BIDI is the maximum bidirectional
- server stream ID. */
-#define NGTCP2_MAX_SERVER_STREAM_ID_BIDI ((int64_t)0x3ffffffffffffffdll)
-/* NGTCP2_MAX_CLIENT_STREAM_ID_BIDI is the maximum bidirectional
- client stream ID. */
-#define NGTCP2_MAX_CLIENT_STREAM_ID_BIDI ((int64_t)0x3ffffffffffffffcll)
-/* NGTCP2_MAX_SERVER_STREAM_ID_UNI is the maximum unidirectional
- server stream ID. */
-#define NGTCP2_MAX_SERVER_STREAM_ID_UNI ((int64_t)0x3fffffffffffffffll)
-/* NGTCP2_MAX_CLIENT_STREAM_ID_UNI is the maximum unidirectional
- client stream ID. */
-#define NGTCP2_MAX_CLIENT_STREAM_ID_UNI ((int64_t)0x3ffffffffffffffell)
-
-/* NGTCP2_MAX_NUM_ACK_BLK is the maximum number of Additional ACK
- blocks which this library can create, or decode. */
-#define NGTCP2_MAX_ACK_BLKS 32
-
-/* NGTCP2_MAX_PKT_NUM is the maximum packet number. */
-#define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1))
-
-/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion in
- addition to the minimum DCID length to hide/trigger Stateless
- Reset. */
-#define NGTCP2_MIN_PKT_EXPANDLEN 22
-
-/* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */
-#define NGTCP2_RETRY_TAGLEN 16
-
-typedef struct ngtcp2_pkt_retry {
- ngtcp2_cid odcid;
- ngtcp2_vec token;
- uint8_t tag[NGTCP2_RETRY_TAGLEN];
-} ngtcp2_pkt_retry;
-
-typedef enum {
- NGTCP2_FRAME_PADDING = 0x00,
- NGTCP2_FRAME_PING = 0x01,
- NGTCP2_FRAME_ACK = 0x02,
- NGTCP2_FRAME_ACK_ECN = 0x03,
- NGTCP2_FRAME_RESET_STREAM = 0x04,
- NGTCP2_FRAME_STOP_SENDING = 0x05,
- NGTCP2_FRAME_CRYPTO = 0x06,
- NGTCP2_FRAME_NEW_TOKEN = 0x07,
- NGTCP2_FRAME_STREAM = 0x08,
- NGTCP2_FRAME_MAX_DATA = 0x10,
- NGTCP2_FRAME_MAX_STREAM_DATA = 0x11,
- NGTCP2_FRAME_MAX_STREAMS_BIDI = 0x12,
- NGTCP2_FRAME_MAX_STREAMS_UNI = 0x13,
- NGTCP2_FRAME_DATA_BLOCKED = 0x14,
- NGTCP2_FRAME_STREAM_DATA_BLOCKED = 0x15,
- NGTCP2_FRAME_STREAMS_BLOCKED_BIDI = 0x16,
- NGTCP2_FRAME_STREAMS_BLOCKED_UNI = 0x17,
- NGTCP2_FRAME_NEW_CONNECTION_ID = 0x18,
- NGTCP2_FRAME_RETIRE_CONNECTION_ID = 0x19,
- NGTCP2_FRAME_PATH_CHALLENGE = 0x1a,
- NGTCP2_FRAME_PATH_RESPONSE = 0x1b,
- NGTCP2_FRAME_CONNECTION_CLOSE = 0x1c,
- NGTCP2_FRAME_CONNECTION_CLOSE_APP = 0x1d,
- NGTCP2_FRAME_HANDSHAKE_DONE = 0x1e,
-} ngtcp2_frame_type;
-
-typedef struct {
- uint8_t type;
- /**
- * flags of decoded STREAM frame. This gets ignored when encoding
- * STREAM frame.
- */
- uint8_t flags;
- uint8_t fin;
- int64_t stream_id;
- uint64_t offset;
- /* datacnt is the number of elements that data contains. Although
- the length of data is 1 in this definition, the library may
- allocate extra bytes to hold more elements. */
- size_t datacnt;
- /* data is the array of ngtcp2_vec which references data. */
- ngtcp2_vec data[1];
-} ngtcp2_stream;
-
-typedef struct {
- uint64_t gap;
- uint64_t blklen;
-} ngtcp2_ack_blk;
-
-typedef struct {
- uint8_t type;
- int64_t largest_ack;
- uint64_t ack_delay;
- /**
- * ack_delay_unscaled is an ack_delay multiplied by
- * 2**ack_delay_component * NGTCP2_MICROSECONDS.
- */
- ngtcp2_duration ack_delay_unscaled;
- uint64_t first_ack_blklen;
- size_t num_blks;
- ngtcp2_ack_blk blks[1];
-} ngtcp2_ack;
-
-typedef struct {
- uint8_t type;
- /**
- * The length of contiguous PADDING frames.
- */
- size_t len;
-} ngtcp2_padding;
-
-typedef struct {
- uint8_t type;
- int64_t stream_id;
- uint64_t app_error_code;
- uint64_t final_size;
-} ngtcp2_reset_stream;
-
-typedef struct {
- uint8_t type;
- uint64_t error_code;
- uint64_t frame_type;
- size_t reasonlen;
- uint8_t *reason;
-} ngtcp2_connection_close;
-
-typedef struct {
- uint8_t type;
- /**
- * max_data is Maximum Data.
- */
- uint64_t max_data;
-} ngtcp2_max_data;
-
-typedef struct {
- uint8_t type;
- int64_t stream_id;
- uint64_t max_stream_data;
-} ngtcp2_max_stream_data;
-
-typedef struct {
- uint8_t type;
- uint64_t max_streams;
-} ngtcp2_max_streams;
-
-typedef struct {
- uint8_t type;
-} ngtcp2_ping;
-
-typedef struct {
- uint8_t type;
- uint64_t offset;
-} ngtcp2_data_blocked;
-
-typedef struct {
- uint8_t type;
- int64_t stream_id;
- uint64_t offset;
-} ngtcp2_stream_data_blocked;
-
-typedef struct {
- uint8_t type;
- uint64_t stream_limit;
-} ngtcp2_streams_blocked;
-
-typedef struct {
- uint8_t type;
- uint64_t seq;
- uint64_t retire_prior_to;
- ngtcp2_cid cid;
- uint8_t stateless_reset_token[NGTCP2_STATELESS_RESET_TOKENLEN];
-} ngtcp2_new_connection_id;
-
-typedef struct {
- uint8_t type;
- int64_t stream_id;
- uint64_t app_error_code;
-} ngtcp2_stop_sending;
-
-typedef struct {
- uint8_t type;
- uint8_t data[8];
-} ngtcp2_path_challenge;
-
-typedef struct {
- uint8_t type;
- uint8_t data[8];
-} ngtcp2_path_response;
-
-typedef struct {
- uint8_t type;
- uint64_t offset;
- /* datacnt is the number of elements that data contains. Although
- the length of data is 1 in this definition, the library may
- allocate extra bytes to hold more elements. */
- size_t datacnt;
- /* data is the array of ngtcp2_vec which references data. */
- ngtcp2_vec data[1];
-} ngtcp2_crypto;
-
-typedef struct {
- uint8_t type;
- ngtcp2_vec token;
-} ngtcp2_new_token;
-
-typedef struct {
- uint8_t type;
- uint64_t seq;
-} ngtcp2_retire_connection_id;
-
-typedef struct {
- uint8_t type;
-} ngtcp2_handshake_done;
-
-typedef union {
- uint8_t type;
- ngtcp2_stream stream;
- ngtcp2_ack ack;
- ngtcp2_padding padding;
- ngtcp2_reset_stream reset_stream;
- ngtcp2_connection_close connection_close;
- ngtcp2_max_data max_data;
- ngtcp2_max_stream_data max_stream_data;
- ngtcp2_max_streams max_streams;
- ngtcp2_ping ping;
- ngtcp2_data_blocked data_blocked;
- ngtcp2_stream_data_blocked stream_data_blocked;
- ngtcp2_streams_blocked streams_blocked;
- ngtcp2_new_connection_id new_connection_id;
- ngtcp2_stop_sending stop_sending;
- ngtcp2_path_challenge path_challenge;
- ngtcp2_path_response path_response;
- ngtcp2_crypto crypto;
- ngtcp2_new_token new_token;
- ngtcp2_retire_connection_id retire_connection_id;
- ngtcp2_handshake_done handshake_done;
-} ngtcp2_frame;
-
-struct ngtcp2_pkt_chain;
-typedef struct ngtcp2_pkt_chain ngtcp2_pkt_chain;
-
-/*
- * ngtcp2_pkt_chain is the chain of incoming packets buffered.
- */
-struct ngtcp2_pkt_chain {
- ngtcp2_path_storage path;
- ngtcp2_pkt_chain *next;
- uint8_t *pkt;
- size_t pktlen;
- ngtcp2_tstamp ts;
-};
-
-/*
- * ngtcp2_pkt_chain_new allocates ngtcp2_pkt_chain objects, and
- * assigns its pointer to |*ppc|. The content of buffer pointed by
- * |pkt| of length |pktlen| is copied into |*ppc|. The packet is
- * obtained via the network |path|. The values of path->local and
- * path->remote are copied into |*ppc|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path,
- const uint8_t *pkt, size_t pktlen, ngtcp2_tstamp ts,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_pkt_chain_del deallocates |pc|. It also frees the memory
- * pointed by |pc|.
- */
-void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_pkt_hd_init initializes |hd| with the given values. If
- * |dcid| and/or |scid| is NULL, DCID and SCID of |hd| is empty
- * respectively. |pkt_numlen| is the number of bytes used to encode
- * |pkt_num| and either 1, 2, or 4. |version| is QUIC version for
- * long header. |len| is the length field of Initial, 0RTT, and
- * Handshake packets.
- */
-void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type,
- const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
- int64_t pkt_num, size_t pkt_numlen, uint32_t version,
- size_t len);
-
-/*
- * ngtcp2_pkt_encode_hd_long encodes |hd| as QUIC long header into
- * |out| which has length |outlen|. It returns the number of bytes
- * written into |outlen| if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer is too short
- */
-ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
- const ngtcp2_pkt_hd *hd);
-
-/*
- * ngtcp2_pkt_encode_hd_short encodes |hd| as QUIC short header into
- * |out| which has length |outlen|. It returns the number of bytes
- * written into |outlen| if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer is too short
- */
-ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen,
- const ngtcp2_pkt_hd *hd);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_decode_frame` decodes a QUIC frame from the buffer
- * pointed by |payload| whose length is |payloadlen|.
- *
- * This function returns the number of bytes read to decode a single
- * frame if it succeeds, or one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_FRAME_ENCODING`
- * Frame is badly formatted; or frame type is unknown.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload,
- size_t payloadlen);
-
-/**
- * @function
- *
- * `ngtcp2_pkt_encode_frame` encodes a frame |fm| into the buffer
- * pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written to the buffer, or
- * one of the following negative error codes:
- *
- * :enum:`NGTCP2_ERR_NOBUF`
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen,
- ngtcp2_frame *fr);
-
-/*
- * ngtcp2_pkt_decode_version_negotiation decodes Version Negotiation
- * packet payload |payload| of length |payloadlen|, and stores the
- * result in |dest|. |dest| must have enough capacity to store the
- * result. |payloadlen| also must be a multiple of sizeof(uint32_t).
- *
- * This function returns the number of versions written in |dest|.
- */
-size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_stateless_reset decodes Stateless Reset payload
- * |payload| of length |payloadlen|. The |payload| must start with
- * Stateless Reset Token.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Payloadlen is too short.
- */
-int ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset *sr,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_retry decodes Retry packet payload |payload| of
- * length |payloadlen|. The |payload| must start with Retry token
- * field.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Payloadlen is too short.
- */
-int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_stream_frame decodes STREAM frame from |payload|
- * of length |payloadlen|. The result is stored in the object pointed
- * by |dest|. STREAM frame must start at payload[0]. This function
- * finishes when it decodes one STREAM frame, and returns the exact
- * number of bytes read to decode a frame if it succeeds, or one of
- * the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include STREAM frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_ack_frame decodes ACK frame from |payload| of
- * length |payloadlen|. The result is stored in the object pointed by
- * |dest|. ACK frame must start at payload[0]. This function
- * finishes when it decodes one ACK frame, and returns the exact
- * number of bytes read to decode a frame if it succeeds, or one of
- * the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include ACK frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_padding_frame decodes contiguous PADDING frames
- * from |payload| of length |payloadlen|. It continues to parse
- * frames as long as the frame type is PADDING. This finishes when it
- * encounters the frame type which is not PADDING, or all input data
- * is read. The first byte (payload[0]) must be NGTCP2_FRAME_PADDING.
- * This function returns the exact number of bytes read to decode
- * PADDING frames.
- */
-size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_reset_stream_frame decodes RESET_STREAM frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. RESET_STREAM frame must start at
- * payload[0]. This function finishes when it decodes one
- * RESET_STREAM frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include RESET_STREAM frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_connection_close_frame decodes CONNECTION_CLOSE
- * frame from |payload| of length |payloadlen|. The result is stored
- * in the object pointed by |dest|. CONNECTION_CLOSE frame must start
- * at payload[0]. This function finishes it decodes one
- * CONNECTION_CLOSE frame, and returns the exact number of bytes read
- * to decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include CONNECTION_CLOSE frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
- ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_max_data_frame decodes MAX_DATA frame from
- * |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. MAX_DATA frame must start at payload[0].
- * This function finishes when it decodes one MAX_DATA frame, and
- * returns the exact number of bytes read to decode a frame if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include MAX_DATA frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_max_stream_data_frame decodes MAX_STREAM_DATA
- * frame from |payload| of length |payloadlen|. The result is stored
- * in the object pointed by |dest|. MAX_STREAM_DATA frame must start
- * at payload[0]. This function finishes when it decodes one
- * MAX_STREAM_DATA frame, and returns the exact number of bytes read
- * to decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include MAX_STREAM_DATA frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame(
- ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_max_streams_frame decodes MAX_STREAMS frame from
- * |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. MAX_STREAMS frame must start at
- * payload[0]. This function finishes when it decodes one MAX_STREAMS
- * frame, and returns the exact number of bytes read to decode a frame
- * if it succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include MAX_STREAMS frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_ping_frame decodes PING frame from |payload| of
- * length |payloadlen|. The result is stored in the object pointed by
- * |dest|. PING frame must start at payload[0]. This function
- * finishes when it decodes one PING frame, and returns the exact
- * number of bytes read to decode a frame if it succeeds, or one of
- * the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include PING frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_data_blocked_frame decodes DATA_BLOCKED frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. DATA_BLOCKED frame must start at
- * payload[0]. This function finishes when it decodes one
- * DATA_BLOCKED frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include DATA_BLOCKED frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_stream_data_blocked_frame decodes
- * STREAM_DATA_BLOCKED frame from |payload| of length |payloadlen|.
- * The result is stored in the object pointed by |dest|.
- * STREAM_DATA_BLOCKED frame must start at payload[0]. This function
- * finishes when it decodes one STREAM_DATA_BLOCKED frame, and returns
- * the exact number of bytes read to decode a frame if it succeeds, or
- * one of the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include STREAM_DATA_BLOCKED frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_streams_blocked_frame decodes STREAMS_BLOCKED
- * frame from |payload| of length |payloadlen|. The result is stored
- * in the object pointed by |dest|. STREAMS_BLOCKED frame must start
- * at payload[0]. This function finishes when it decodes one
- * STREAMS_BLOCKED frame, and returns the exact number of bytes read
- * to decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include STREAMS_BLOCKED frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame(
- ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_new_connection_id_frame decodes NEW_CONNECTION_ID
- * frame from |payload| of length |payloadlen|. The result is stored
- * in the object pointed by |dest|. NEW_CONNECTION_ID frame must
- * start at payload[0]. This function finishes when it decodes one
- * NEW_CONNECTION_ID frame, and returns the exact number of bytes read
- * to decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include NEW_CONNECTION_ID frame; or the
- * length of CID is strictly less than NGTCP2_MIN_CIDLEN or
- * greater than NGTCP2_MAX_CIDLEN.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame(
- ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_stop_sending_frame decodes STOP_SENDING frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. STOP_SENDING frame must start at
- * payload[0]. This function finishes when it decodes one
- * STOP_SENDING frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include STOP_SENDING frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_path_challenge_frame decodes PATH_CHALLENGE frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. PATH_CHALLENGE frame must start at
- * payload[0]. This function finishes when it decodes one
- * PATH_CHALLENGE frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include PATH_CHALLENGE frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_path_response_frame decodes PATH_RESPONSE frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. PATH_RESPONSE frame must start at
- * payload[0]. This function finishes when it decodes one
- * PATH_RESPONSE frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include PATH_RESPONSE frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_crypto_frame decodes CRYPTO frame from |payload|
- * of length |payloadlen|. The result is stored in the object pointed
- * by |dest|. CRYPTO frame must start at payload[0]. This function
- * finishes when it decodes one CRYPTO frame, and returns the exact
- * number of bytes read to decode a frame if it succeeds, or one of
- * the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include CRYPTO frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_new_token_frame decodes NEW_TOKEN frame from
- * |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. NEW_TOKEN frame must start at
- * payload[0]. This function finishes when it decodes one NEW_TOKEN
- * frame, and returns the exact number of bytes read to decode a frame
- * if it succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include NEW_TOKEN frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_retire_connection_id_frame decodes RETIRE_CONNECTION_ID
- * frame from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. RETIRE_CONNECTION_ID frame must start at
- * payload[0]. This function finishes when it decodes one RETIRE_CONNECTION_ID
- * frame, and returns the exact number of bytes read to decode a frame
- * if it succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include RETIRE_CONNECTION_ID frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_decode_handshake_done_frame decodes HANDSHAKE_DONE frame
- * from |payload| of length |payloadlen|. The result is stored in the
- * object pointed by |dest|. HANDSHAKE_DONE frame must start at
- * payload[0]. This function finishes when it decodes one
- * HANDSHAKE_DONE frame, and returns the exact number of bytes read to
- * decode a frame if it succeeds, or one of the following negative
- * error codes:
- *
- * NGTCP2_ERR_FRAME_ENCODING
- * Payload is too short to include HANDSHAKE_DONE frame.
- */
-ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest,
- const uint8_t *payload,
- size_t payloadlen);
-
-/*
- * ngtcp2_pkt_encode_stream_frame encodes STREAM frame |fr| into the
- * buffer pointed by |out| of length |outlen|.
- *
- * This function assigns <the serialized frame type> &
- * ~NGTCP2_FRAME_STREAM to fr->flags.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen,
- ngtcp2_stream *fr);
-
-/*
- * ngtcp2_pkt_encode_ack_frame encodes ACK frame |fr| into the buffer
- * pointed by |out| of length |outlen|.
- *
- * This function assigns <the serialized frame type> &
- * ~NGTCP2_FRAME_ACK to fr->flags.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen,
- ngtcp2_ack *fr);
-
-/*
- * ngtcp2_pkt_encode_padding_frame encodes PADDING frame |fr| into the
- * buffer pointed by |out| of length |outlen|.
- *
- * This function encodes consecutive fr->len PADDING frames.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write frame(s).
- */
-ngtcp2_ssize ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen,
- const ngtcp2_padding *fr);
-
-/*
- * ngtcp2_pkt_encode_reset_stream_frame encodes RESET_STREAM frame
- * |fr| into the buffer pointed by |out| of length |buflen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
- const ngtcp2_reset_stream *fr);
-
-/*
- * ngtcp2_pkt_encode_connection_close_frame encodes CONNECTION_CLOSE
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
- const ngtcp2_connection_close *fr);
-
-/*
- * ngtcp2_pkt_encode_max_data_frame encodes MAX_DATA frame |fr| into
- * the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_data *fr);
-
-/*
- * ngtcp2_pkt_encode_max_stream_data_frame encodes MAX_STREAM_DATA
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_stream_data *fr);
-
-/*
- * ngtcp2_pkt_encode_max_streams_frame encodes MAX_STREAMS
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen,
- const ngtcp2_max_streams *fr);
-
-/*
- * ngtcp2_pkt_encode_ping_frame encodes PING frame |fr| into the
- * buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_ping_frame(uint8_t *out, size_t outlen,
- const ngtcp2_ping *fr);
-
-/*
- * ngtcp2_pkt_encode_data_blocked_frame encodes DATA_BLOCKED frame
- * |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen,
- const ngtcp2_data_blocked *fr);
-
-/*
- * ngtcp2_pkt_encode_stream_data_blocked_frame encodes
- * STREAM_DATA_BLOCKED frame |fr| into the buffer pointed by |out| of
- * length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame(
- uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr);
-
-/*
- * ngtcp2_pkt_encode_streams_blocked_frame encodes STREAMS_BLOCKED
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen,
- const ngtcp2_streams_blocked *fr);
-
-/*
- * ngtcp2_pkt_encode_new_connection_id_frame encodes NEW_CONNECTION_ID
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen,
- const ngtcp2_new_connection_id *fr);
-
-/*
- * ngtcp2_pkt_encode_stop_sending_frame encodes STOP_SENDING frame
- * |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
- const ngtcp2_stop_sending *fr);
-
-/*
- * ngtcp2_pkt_encode_path_challenge_frame encodes PATH_CHALLENGE frame
- * |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_path_challenge_frame(uint8_t *out, size_t outlen,
- const ngtcp2_path_challenge *fr);
-
-/*
- * ngtcp2_pkt_encode_path_response_frame encodes PATH_RESPONSE frame
- * |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen,
- const ngtcp2_path_response *fr);
-
-/*
- * ngtcp2_pkt_encode_crypto_frame encodes CRYPTO frame |fr| into the
- * buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen,
- const ngtcp2_crypto *fr);
-
-/*
- * ngtcp2_pkt_encode_new_token_frame encodes NEW_TOKEN frame |fr| into
- * the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
- const ngtcp2_new_token *fr);
-
-/*
- * ngtcp2_pkt_encode_retire_connection_id_frame encodes RETIRE_CONNECTION_ID
- * frame |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame(
- uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr);
-
-/*
- * ngtcp2_pkt_encode_handshake_done_frame encodes HANDSHAKE_DONE frame
- * |fr| into the buffer pointed by |out| of length |outlen|.
- *
- * This function returns the number of bytes written if it succeeds,
- * or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * Buffer does not have enough capacity to write a frame.
- */
-ngtcp2_ssize
-ngtcp2_pkt_encode_handshake_done_frame(uint8_t *out, size_t outlen,
- const ngtcp2_handshake_done *fr);
-
-/*
- * ngtcp2_pkt_adjust_pkt_num find the full 64 bits packet number for
- * |pkt_num|, which is expected to be least significant |n| bits. The
- * |max_pkt_num| is the highest successfully authenticated packet
- * number.
- */
-int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num,
- size_t n);
-
-/*
- * ngtcp2_pkt_validate_ack checks that ack is malformed or not.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_ACK_FRAME
- * ACK frame is malformed
- */
-int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr);
-
-/*
- * ngtcp2_pkt_stream_max_datalen returns the maximum number of bytes
- * which can be sent for stream denoted by |stream_id|. |offset| is
- * an offset of within the stream. |len| is the estimated number of
- * bytes to be sent. |left| is the size of buffer. If |left| is too
- * small to write STREAM frame, this function returns (size_t)-1.
- */
-size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
- size_t len, size_t left);
-
-/*
- * ngtcp2_pkt_crypto_max_datalen returns the maximum number of bytes
- * which can be sent for crypto stream. |offset| is an offset of
- * within the crypto stream. |len| is the estimated number of bytes
- * to be sent. |left| is the size of buffer. If |left| is too small
- * to write CRYPTO frame, this function returns (size_t)-1.
- */
-size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left);
-
-/*
- * ngtcp2_pkt_verify_reserved_bits verifies that the first byte |c| of
- * the packet header has the correct reserved bits.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * Reserved bits has wrong value.
- */
-int ngtcp2_pkt_verify_reserved_bits(uint8_t c);
-
-/*
- * ngtcp2_pkt_encode_pseudo_retry encodes Retry pseudo-packet in the
- * buffer pointed by |dest| of length |destlen|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_BUF
- * Buffer is too short.
- */
-ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
- uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused,
- const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen);
-
-/*
- * ngtcp2_pkt_verify_retry_tag verifies Retry packet. The buffer
- * pointed by |pkt| of length |pktlen| must contain Retry packet
- * including packet header. The odcid and tag fields of |retry| must
- * be specified. |aead| must be AEAD_AES_128_GCM.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PROTO
- * Verification failed.
- */
-int ngtcp2_pkt_verify_retry_tag(const ngtcp2_pkt_retry *retry,
- const uint8_t *pkt, size_t pktlen,
- ngtcp2_encrypt encrypt,
- const ngtcp2_crypto_aead *aead,
- const ngtcp2_crypto_aead_ctx *aead_ctx);
-
-#endif /* NGTCP2_PKT_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_ppe.c b/deps/ngtcp2/lib/ngtcp2_ppe.c
deleted file mode 100644
index e2c47fd0c5..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ppe.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_ppe.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_str.h"
-#include "ngtcp2_conv.h"
-
-void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen,
- ngtcp2_crypto_cc *cc) {
- ngtcp2_buf_init(&ppe->buf, out, outlen);
-
- ppe->hdlen = 0;
- ppe->len_offset = 0;
- ppe->pkt_num_offset = 0;
- ppe->pkt_numlen = 0;
- ppe->pkt_num = 0;
- ppe->sample_offset = 0;
- ppe->cc = cc;
-}
-
-int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd) {
- ngtcp2_ssize rv;
- ngtcp2_buf *buf = &ppe->buf;
- ngtcp2_crypto_cc *cc = ppe->cc;
-
- if (ngtcp2_buf_left(buf) < cc->aead_overhead) {
- return NGTCP2_ERR_NOBUF;
- }
-
- if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- ppe->len_offset = 1 + 4 + 1 + hd->dcid.datalen + 1 + hd->scid.datalen;
- if (hd->type == NGTCP2_PKT_INITIAL) {
- ppe->len_offset += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
- }
- ppe->pkt_num_offset = ppe->len_offset + 2;
- rv = ngtcp2_pkt_encode_hd_long(
- buf->last, ngtcp2_buf_left(buf) - cc->aead_overhead, hd);
- } else {
- ppe->pkt_num_offset = 1 + hd->dcid.datalen;
- rv = ngtcp2_pkt_encode_hd_short(
- buf->last, ngtcp2_buf_left(buf) - cc->aead_overhead, hd);
- }
- if (rv < 0) {
- return (int)rv;
- }
-
- ppe->sample_offset = ppe->pkt_num_offset + 4;
-
- buf->last += rv;
-
- ppe->pkt_numlen = hd->pkt_numlen;
- ppe->hdlen = (size_t)rv;
-
- ppe->pkt_num = hd->pkt_num;
-
- return 0;
-}
-
-int ngtcp2_ppe_encode_frame(ngtcp2_ppe *ppe, ngtcp2_frame *fr) {
- ngtcp2_ssize rv;
- ngtcp2_buf *buf = &ppe->buf;
- ngtcp2_crypto_cc *cc = ppe->cc;
-
- if (ngtcp2_buf_left(buf) < cc->aead_overhead) {
- return NGTCP2_ERR_NOBUF;
- }
-
- rv = ngtcp2_pkt_encode_frame(buf->last,
- ngtcp2_buf_left(buf) - cc->aead_overhead, fr);
- if (rv < 0) {
- return (int)rv;
- }
-
- buf->last += rv;
-
- return 0;
-}
-
-ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt) {
- ngtcp2_buf *buf = &ppe->buf;
- ngtcp2_crypto_cc *cc = ppe->cc;
- uint8_t *payload = buf->begin + ppe->hdlen;
- size_t payloadlen = ngtcp2_buf_len(buf) - ppe->hdlen;
- uint8_t mask[NGTCP2_HP_SAMPLELEN];
- uint8_t *p;
- size_t i;
- int rv;
-
- assert(cc->encrypt);
- assert(cc->hp_mask);
-
- if (ppe->len_offset) {
- ngtcp2_put_varint14(
- buf->begin + ppe->len_offset,
- (uint16_t)(payloadlen + ppe->pkt_numlen + cc->aead_overhead));
- }
-
- ngtcp2_crypto_create_nonce(ppe->nonce, cc->ckm->iv.base, cc->ckm->iv.len,
- ppe->pkt_num);
-
- rv = cc->encrypt(payload, &cc->aead, &cc->ckm->aead_ctx, payload, payloadlen,
- ppe->nonce, cc->ckm->iv.len, buf->begin, ppe->hdlen);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- buf->last = payload + payloadlen + cc->aead_overhead;
-
- /* TODO Check that we have enough space to get sample */
- assert(ppe->sample_offset + NGTCP2_HP_SAMPLELEN <= ngtcp2_buf_len(buf));
-
- rv = cc->hp_mask(mask, &cc->hp, &cc->hp_ctx, buf->begin + ppe->sample_offset);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
-
- p = buf->begin;
- if (*p & NGTCP2_HEADER_FORM_BIT) {
- *p = (uint8_t)(*p ^ (mask[0] & 0x0f));
- } else {
- *p = (uint8_t)(*p ^ (mask[0] & 0x1f));
- }
-
- p = buf->begin + ppe->pkt_num_offset;
- for (i = 0; i < ppe->pkt_numlen; ++i) {
- *(p + i) ^= mask[i + 1];
- }
-
- if (ppkt != NULL) {
- *ppkt = buf->begin;
- }
-
- return (ngtcp2_ssize)ngtcp2_buf_len(buf);
-}
-
-size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe) {
- ngtcp2_crypto_cc *cc = ppe->cc;
-
- if (ngtcp2_buf_left(&ppe->buf) < cc->aead_overhead) {
- return 0;
- }
-
- return ngtcp2_buf_left(&ppe->buf) - cc->aead_overhead;
-}
-
-size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe) {
- ngtcp2_crypto_cc *cc = ppe->cc;
-
- return ngtcp2_buf_len(&ppe->buf) + cc->aead_overhead;
-}
-
-size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe) {
- ngtcp2_crypto_cc *cc = ppe->cc;
- ngtcp2_buf *buf = &ppe->buf;
- size_t len;
-
- assert(ngtcp2_buf_left(buf) >= cc->aead_overhead);
-
- len = ngtcp2_buf_left(buf) - cc->aead_overhead;
- memset(buf->last, 0, len);
- buf->last += len;
-
- return len;
-}
-
-size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe) {
- ngtcp2_crypto_cc *cc = ppe->cc;
- ngtcp2_buf *buf = &ppe->buf;
- size_t max_samplelen;
- size_t len = 0;
-
- assert(cc->aead_overhead);
-
- max_samplelen = ngtcp2_buf_len(buf) + cc->aead_overhead - ppe->sample_offset;
- if (max_samplelen < NGTCP2_HP_SAMPLELEN) {
- len = NGTCP2_HP_SAMPLELEN - max_samplelen;
- assert(ngtcp2_ppe_left(ppe) >= len);
- memset(buf->last, 0, len);
- buf->last += len;
- }
-
- return len;
-}
-
-size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) {
- ngtcp2_crypto_cc *cc = ppe->cc;
- ngtcp2_buf *buf = &ppe->buf;
- size_t pktlen = ngtcp2_buf_len(buf) + cc->aead_overhead;
- size_t len;
-
- if (pktlen >= n) {
- return 0;
- }
-
- len = n - pktlen;
- buf->last = ngtcp2_setmem(buf->last, 0, len);
-
- return len;
-}
-
-int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe) {
- ngtcp2_buf *buf = &ppe->buf;
- return ngtcp2_buf_left(buf) >= (4 - ppe->pkt_numlen) + NGTCP2_HP_SAMPLELEN;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_ppe.h b/deps/ngtcp2/lib/ngtcp2_ppe.h
deleted file mode 100644
index ca6b21dce0..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ppe.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_PPE_H
-#define NGTCP2_PPE_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_pkt.h"
-#include "ngtcp2_buf.h"
-#include "ngtcp2_crypto.h"
-
-/*
- * ngtcp2_ppe is the Protected Packet Encoder.
- */
-typedef struct {
- ngtcp2_buf buf;
- ngtcp2_crypto_cc *cc;
- /* hdlen is the number of bytes for packet header written in buf. */
- size_t hdlen;
- /* len_offset is the offset to Length field. */
- size_t len_offset;
- /* pkt_num_offset is the offset to packet number field. */
- size_t pkt_num_offset;
- /* pkt_numlen is the number of bytes used to encode a packet
- number */
- size_t pkt_numlen;
- /* sample_offset is the offset to sample for packet number
- encryption. */
- size_t sample_offset;
- /* pkt_num is the packet number written in buf. */
- int64_t pkt_num;
- /* nonce is the buffer to store nonce. It should be equal or longer
- than then length of IV. */
- uint8_t nonce[32];
-} ngtcp2_ppe;
-
-/*
- * ngtcp2_ppe_init initializes |ppe| with the given buffer.
- */
-void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen,
- ngtcp2_crypto_cc *cc);
-
-/*
- * ngtcp2_ppe_encode_hd encodes |hd|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * The buffer is too small.
- */
-int ngtcp2_ppe_encode_hd(ngtcp2_ppe *ppe, const ngtcp2_pkt_hd *hd);
-
-/*
- * ngtcp2_ppe_encode_frame encodes |fr|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOBUF
- * The buffer is too small.
- */
-int ngtcp2_ppe_encode_frame(ngtcp2_ppe *ppe, ngtcp2_frame *fr);
-
-/*
- * ngtcp2_ppe_final encrypts QUIC packet payload. If |**ppkt| is not
- * NULL, the pointer to the packet is assigned to it.
- *
- * This function returns the length of QUIC packet, including header,
- * and payload if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User-defined callback function failed.
- */
-ngtcp2_ssize ngtcp2_ppe_final(ngtcp2_ppe *ppe, const uint8_t **ppkt);
-
-/*
- * ngtcp2_ppe_left returns the number of bytes left to write
- * additional frames. This does not count AEAD overhead.
- */
-size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe);
-
-/*
- * ngtcp2_ppe_pktlen returns the provisional packet length. It
- * includes AEAD overhead.
- */
-size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe);
-
-/**
- * @function
- *
- * `ngtcp2_ppe_padding` encodes PADDING frames to the end of the
- * buffer. This function returns the number of bytes padded.
- */
-size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe);
-
-/*
- * ngtcp2_ppe_padding_hp_sample adds PADDING frame if the current
- * payload does not have enough space for header protection sample.
- * This function should be called just before calling
- * ngtcp2_ppe_final().
- *
- * This function returns the number of bytes added as padding.
- */
-size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe);
-
-/*
- * ngtcp2_ppe_padding_size adds PADDING frame so that the size of QUIC
- * packet is at least |n| bytes long. If it is unable to add PADDING
- * in that way, this function still adds PADDING frame as much as
- * possible. This function should be called just before calling
- * ngtcp2_ppe_final(). For Short packet, this function should be
- * called instead of ngtcp2_ppe_padding_hp_sample.
- *
- * This function returns the number of bytes added as padding.
- */
-size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n);
-
-/*
- * ngtcp2_ppe_ensure_hp_sample returns nonzero if the buffer has
- * enough space for header protection sample. This should be called
- * right after packet header is written.
- */
-int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe);
-
-#endif /* NGTCP2_PPE_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_pq.c b/deps/ngtcp2/lib/ngtcp2_pq.c
deleted file mode 100644
index 5e1003d794..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pq.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_pq.h"
-
-#include <assert.h>
-
-#include "ngtcp2_macro.h"
-
-void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_less less, const ngtcp2_mem *mem) {
- pq->mem = mem;
- pq->capacity = 0;
- pq->q = NULL;
- pq->length = 0;
- pq->less = less;
-}
-
-void ngtcp2_pq_free(ngtcp2_pq *pq) {
- ngtcp2_mem_free(pq->mem, pq->q);
- pq->q = NULL;
-}
-
-static void swap(ngtcp2_pq *pq, size_t i, size_t j) {
- ngtcp2_pq_entry *a = pq->q[i];
- ngtcp2_pq_entry *b = pq->q[j];
-
- pq->q[i] = b;
- b->index = i;
- pq->q[j] = a;
- a->index = j;
-}
-
-static void bubble_up(ngtcp2_pq *pq, size_t index) {
- size_t parent;
- while (index != 0) {
- parent = (index - 1) / 2;
- if (!pq->less(pq->q[index], pq->q[parent])) {
- return;
- }
- swap(pq, parent, index);
- index = parent;
- }
-}
-
-int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item) {
- if (pq->capacity <= pq->length) {
- void *nq;
- size_t ncapacity;
-
- ncapacity = ngtcp2_max(4, (pq->capacity * 2));
-
- nq = ngtcp2_mem_realloc(pq->mem, pq->q,
- ncapacity * sizeof(ngtcp2_pq_entry *));
- if (nq == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
- pq->capacity = ncapacity;
- pq->q = nq;
- }
- pq->q[pq->length] = item;
- item->index = pq->length;
- ++pq->length;
- bubble_up(pq, pq->length - 1);
- return 0;
-}
-
-ngtcp2_pq_entry *ngtcp2_pq_top(ngtcp2_pq *pq) {
- assert(pq->length);
- return pq->q[0];
-}
-
-static void bubble_down(ngtcp2_pq *pq, size_t index) {
- size_t i, j, minindex;
- for (;;) {
- j = index * 2 + 1;
- minindex = index;
- for (i = 0; i < 2; ++i, ++j) {
- if (j >= pq->length) {
- break;
- }
- if (pq->less(pq->q[j], pq->q[minindex])) {
- minindex = j;
- }
- }
- if (minindex == index) {
- return;
- }
- swap(pq, index, minindex);
- index = minindex;
- }
-}
-
-void ngtcp2_pq_pop(ngtcp2_pq *pq) {
- if (pq->length > 0) {
- pq->q[0] = pq->q[pq->length - 1];
- pq->q[0]->index = 0;
- --pq->length;
- bubble_down(pq, 0);
- }
-}
-
-void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item) {
- assert(pq->q[item->index] == item);
-
- if (item->index == 0) {
- ngtcp2_pq_pop(pq);
- return;
- }
-
- if (item->index == pq->length - 1) {
- --pq->length;
- return;
- }
-
- pq->q[item->index] = pq->q[pq->length - 1];
- pq->q[item->index]->index = item->index;
- --pq->length;
-
- if (pq->less(item, pq->q[item->index])) {
- bubble_down(pq, item->index);
- } else {
- bubble_up(pq, item->index);
- }
-}
-
-int ngtcp2_pq_empty(ngtcp2_pq *pq) { return pq->length == 0; }
-
-size_t ngtcp2_pq_size(ngtcp2_pq *pq) { return pq->length; }
-
-int ngtcp2_pq_each(ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg) {
- size_t i;
-
- if (pq->length == 0) {
- return 0;
- }
- for (i = 0; i < pq->length; ++i) {
- if ((*fun)(pq->q[i], arg)) {
- return 1;
- }
- }
- return 0;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_pq.h b/deps/ngtcp2/lib/ngtcp2_pq.h
deleted file mode 100644
index b7e4a77ba5..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pq.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- * Copyright (c) 2012 nghttp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_PQ_H
-#define NGTCP2_PQ_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-
-/* Implementation of priority queue */
-
-/* NGTCP2_PQ_BAD_INDEX is the priority queue index which indicates
- that an entry is not queued. Assigning this value to
- ngtcp2_pq_entry.index can check that the entry is queued or not. */
-#define NGTCP2_PQ_BAD_INDEX SIZE_MAX
-
-typedef struct {
- size_t index;
-} ngtcp2_pq_entry;
-
-/* "less" function, return nonzero if |lhs| is less than |rhs|. */
-typedef int (*ngtcp2_less)(const ngtcp2_pq_entry *lhs,
- const ngtcp2_pq_entry *rhs);
-
-typedef struct {
- /* The pointer to the pointer to the item stored */
- ngtcp2_pq_entry **q;
- /* Memory allocator */
- const ngtcp2_mem *mem;
- /* The number of items stored */
- size_t length;
- /* The maximum number of items this pq can store. This is
- automatically extended when length is reached to this value. */
- size_t capacity;
- /* The less function between items */
- ngtcp2_less less;
-} ngtcp2_pq;
-
-/*
- * Initializes priority queue |pq| with compare function |cmp|.
- */
-void ngtcp2_pq_init(ngtcp2_pq *pq, ngtcp2_less less, const ngtcp2_mem *mem);
-
-/*
- * Deallocates any resources allocated for |pq|. The stored items are
- * not freed by this function.
- */
-void ngtcp2_pq_free(ngtcp2_pq *pq);
-
-/*
- * Adds |item| to the priority queue |pq|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item);
-
-/*
- * Returns item at the top of the queue |pq|. It is undefined if the
- * queue is empty.
- */
-ngtcp2_pq_entry *ngtcp2_pq_top(ngtcp2_pq *pq);
-
-/*
- * Pops item at the top of the queue |pq|. The popped item is not
- * freed by this function.
- */
-void ngtcp2_pq_pop(ngtcp2_pq *pq);
-
-/*
- * Returns nonzero if the queue |pq| is empty.
- */
-int ngtcp2_pq_empty(ngtcp2_pq *pq);
-
-/*
- * Returns the number of items in the queue |pq|.
- */
-size_t ngtcp2_pq_size(ngtcp2_pq *pq);
-
-typedef int (*ngtcp2_pq_item_cb)(ngtcp2_pq_entry *item, void *arg);
-
-/*
- * Applys |fun| to each item in |pq|. The |arg| is passed as arg
- * parameter to callback function. This function must not change the
- * ordering key. If the return value from callback is nonzero, this
- * function returns 1 immediately without iterating remaining items.
- * Otherwise this function returns 0.
- */
-int ngtcp2_pq_each(ngtcp2_pq *pq, ngtcp2_pq_item_cb fun, void *arg);
-
-/*
- * Removes |item| from priority queue.
- */
-void ngtcp2_pq_remove(ngtcp2_pq *pq, ngtcp2_pq_entry *item);
-
-#endif /* NGTCP2_PQ_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_pv.c b/deps/ngtcp2/lib/ngtcp2_pv.c
deleted file mode 100644
index 171f02dc43..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pv.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_pv.h"
-
-#include <string.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_log.h"
-#include "ngtcp2_macro.h"
-#include "ngtcp2_addr.h"
-
-void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data,
- ngtcp2_tstamp expiry) {
- memcpy(pvent->data, data, sizeof(pvent->data));
- pvent->expiry = expiry;
-}
-
-int ngtcp2_pv_new(ngtcp2_pv **ppv, const ngtcp2_dcid *dcid,
- ngtcp2_duration timeout, uint8_t flags, ngtcp2_log *log,
- const ngtcp2_mem *mem) {
- int rv;
-
- (*ppv) = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pv));
- if (*ppv == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_ringbuf_init(&(*ppv)->ents, NGTCP2_PV_MAX_ENTRIES,
- sizeof(ngtcp2_pv_entry), mem);
- if (rv != 0) {
- ngtcp2_mem_free(mem, *ppv);
- return 0;
- }
-
- ngtcp2_dcid_copy(&(*ppv)->dcid, dcid);
-
- (*ppv)->mem = mem;
- (*ppv)->log = log;
- (*ppv)->timeout = timeout;
- (*ppv)->started_ts = 0;
- (*ppv)->loss_count = 0;
- (*ppv)->flags = flags;
-
- return 0;
-}
-
-void ngtcp2_pv_del(ngtcp2_pv *pv) {
- if (pv == NULL) {
- return;
- }
- ngtcp2_ringbuf_free(&pv->ents);
- ngtcp2_mem_free(pv->mem, pv);
-}
-
-void ngtcp2_pv_ensure_start(ngtcp2_pv *pv, ngtcp2_tstamp ts) {
- if (pv->started_ts) {
- return;
- }
- pv->started_ts = ts;
-}
-
-void ngtcp2_pv_add_entry(ngtcp2_pv *pv, const uint8_t *data,
- ngtcp2_tstamp expiry) {
- ngtcp2_pv_entry *ent = ngtcp2_ringbuf_push_back(&pv->ents);
- ngtcp2_pv_entry_init(ent, data, expiry);
-}
-
-int ngtcp2_pv_full(ngtcp2_pv *pv) { return ngtcp2_ringbuf_full(&pv->ents); }
-
-int ngtcp2_pv_validate(ngtcp2_pv *pv, const uint8_t *data) {
- size_t len = ngtcp2_ringbuf_len(&pv->ents);
- size_t i;
- ngtcp2_pv_entry *ent;
-
- if (len == 0) {
- return NGTCP2_ERR_INVALID_STATE;
- }
-
- for (i = 0; i < len; ++i) {
- ent = ngtcp2_ringbuf_get(&pv->ents, i);
- if (memcmp(ent->data, data, sizeof(ent->data)) == 0) {
- ngtcp2_log_info(pv->log, NGTCP2_LOG_EVENT_PTV, "path has been validated");
- return 0;
- }
- }
-
- return NGTCP2_ERR_INVALID_ARGUMENT;
-}
-
-void ngtcp2_pv_handle_entry_expiry(ngtcp2_pv *pv, ngtcp2_tstamp ts) {
- ngtcp2_pv_entry *ent;
-
- if (ngtcp2_ringbuf_len(&pv->ents) == 0) {
- return;
- }
-
- ent = ngtcp2_ringbuf_get(&pv->ents, 0);
- if (ent->expiry <= ts) {
- ++pv->loss_count;
-
- ngtcp2_ringbuf_pop_front(&pv->ents);
-
- for (; ngtcp2_ringbuf_len(&pv->ents);) {
- ent = ngtcp2_ringbuf_get(&pv->ents, 0);
- if (ent->expiry <= ts) {
- ngtcp2_ringbuf_pop_front(&pv->ents);
- continue;
- }
- break;
- }
- }
-}
-
-int ngtcp2_pv_validation_timed_out(ngtcp2_pv *pv, ngtcp2_tstamp ts) {
- return pv->started_ts + pv->timeout <= ts;
-}
-
-ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv) {
- ngtcp2_tstamp t = UINT64_MAX;
- ngtcp2_pv_entry *ent;
-
- if (pv->started_ts) {
- t = pv->started_ts + pv->timeout;
- }
-
- if (ngtcp2_ringbuf_len(&pv->ents) == 0) {
- return t;
- }
-
- ent = ngtcp2_ringbuf_get(&pv->ents, 0);
-
- return ngtcp2_min(t, ent->expiry);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_pv.h b/deps/ngtcp2/lib/ngtcp2_pv.h
deleted file mode 100644
index 0f1734ec3e..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_pv.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_PV_H
-#define NGTCP2_PV_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_cid.h"
-#include "ngtcp2_ringbuf.h"
-
-/* NGTCP2_PV_MAX_ENTRIES is the maximum number of entries that
- ngtcp2_pv can contain. It must be power of 2. */
-#define NGTCP2_PV_MAX_ENTRIES 4
-
-struct ngtcp2_log;
-typedef struct ngtcp2_log ngtcp2_log;
-
-struct ngtcp2_frame_chain;
-typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
-
-typedef struct {
- /* expiry is the timestamp when this PATH_CHALLENGE expires. */
- ngtcp2_tstamp expiry;
- /* data is a byte string included in PATH_CHALLENGE. */
- uint8_t data[8];
-} ngtcp2_pv_entry;
-
-void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data,
- ngtcp2_tstamp expiry);
-
-typedef enum {
- NGTCP2_PV_FLAG_NONE,
- /* NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE indicates that fallback DCID
- is available in ngtcp2_pv. If path validation fails, fallback to
- the fallback DCID. If path validation succeeds, fallback DCID is
- retired if it does not equal to the current DCID. */
- NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE = 0x04,
-} ngtcp2_pv_flag;
-
-struct ngtcp2_pv;
-typedef struct ngtcp2_pv ngtcp2_pv;
-
-/*
- * ngtcp2_pv is the context of a single path validation.
- */
-struct ngtcp2_pv {
- const ngtcp2_mem *mem;
- ngtcp2_log *log;
- /* dcid is DCID and path this path validation uses. */
- ngtcp2_dcid dcid;
- /* fallback_dcid is the usually validated DCID and used as a
- fallback if this path validation fails. */
- ngtcp2_dcid fallback_dcid;
- /* ents is the ring buffer of ngtcp2_pv_entry */
- ngtcp2_ringbuf ents;
- /* timeout is the duration within which this path validation should
- succeed. */
- ngtcp2_duration timeout;
- /* started_ts is the timestamp this path validation starts. */
- ngtcp2_tstamp started_ts;
- /* loss_count is the number of lost PATH_CHALLENGE */
- size_t loss_count;
- /* flags is bitwise-OR of zero or more of ngtcp2_pv_flag. */
- uint8_t flags;
-};
-
-/*
- * ngtcp2_pv_new creates new ngtcp2_pv object and assigns its pointer
- * to |*ppv|. This function makes a copy of |dcid|. |timeout| is a
- * duration within which this path validation must succeed.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_pv_new(ngtcp2_pv **ppv, const ngtcp2_dcid *dcid,
- ngtcp2_duration timeout, uint8_t flags, ngtcp2_log *log,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_pv_del deallocates |pv|. This function frees memory |pv|
- * points too.
- */
-void ngtcp2_pv_del(ngtcp2_pv *pv);
-
-/*
- * ngtcp2_pv_ensure_start sets started_ts field to |ts| if it is zero.
- */
-void ngtcp2_pv_ensure_start(ngtcp2_pv *pv, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_pv_add_entry adds new entry with |data|. |expiry| is the
- * expiry time of the entry.
- */
-void ngtcp2_pv_add_entry(ngtcp2_pv *pv, const uint8_t *data,
- ngtcp2_tstamp expiry);
-
-/*
- * ngtcp2_pv_full returns nonzero if |pv| is full of ngtcp2_pv_entry.
- */
-int ngtcp2_pv_full(ngtcp2_pv *pv);
-
-/*
- * ngtcp2_pv_validate validates that the received |data| matches the
- * one of the existing entry.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_PATH_VALIDATION_FAILED
- * path validation has failed and must be abandoned
- * NGTCP2_ERR_INVALID_STATE
- * |pv| includes no entry
- * NGTCP2_ERR_INVALID_ARGUMENT
- * |pv| does not have an entry which has |data| and |path|
- */
-int ngtcp2_pv_validate(ngtcp2_pv *pv, const uint8_t *data);
-
-/*
- * ngtcp2_pv_handle_entry_expiry checks expiry for each entry.
- */
-void ngtcp2_pv_handle_entry_expiry(ngtcp2_pv *pv, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_pv_validation_timed_out returns nonzero if the path
- * validation fails because of timeout.
- */
-int ngtcp2_pv_validation_timed_out(ngtcp2_pv *pv, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_pv_next_expiry returns the earliest expiry.
- */
-ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv);
-
-#endif /* NGTCP2_PV_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_qlog.c b/deps/ngtcp2/lib/ngtcp2_qlog.c
deleted file mode 100644
index 580b6a6fe0..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_qlog.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_qlog.h"
-
-#include <assert.h>
-
-#include "ngtcp2_str.h"
-#include "ngtcp2_vec.h"
-
-void ngtcp2_qlog_init(ngtcp2_qlog *qlog, ngtcp2_qlog_write write,
- ngtcp2_tstamp ts, void *user_data) {
- qlog->write = write;
- qlog->ts = qlog->last_ts = ts;
- qlog->user_data = user_data;
-}
-
-static uint8_t *write_string(uint8_t *p, const ngtcp2_vec *s) {
- *p++ = '"';
- if (s->len) {
- p = ngtcp2_cpymem(p, s->base, s->len);
- }
- *p++ = '"';
- return p;
-}
-
-#define NGTCP2_LOWER_XDIGITS "0123456789abcdef"
-
-static uint8_t *write_hex(uint8_t *p, const ngtcp2_vec *s) {
- const uint8_t *b = s->base, *end = s->base + s->len;
- *p++ = '"';
- for (; b != end; ++b) {
- *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b >> 4];
- *p++ = (uint8_t)NGTCP2_LOWER_XDIGITS[*b & 0xf];
- }
- *p++ = '"';
- return p;
-}
-
-static uint8_t *write_cid(uint8_t *p, const ngtcp2_cid *cid) {
- ngtcp2_vec value;
- return write_hex(p, ngtcp2_vec_init(&value, cid->data, cid->datalen));
-}
-
-static uint8_t *write_number(uint8_t *p, uint64_t n) {
- size_t nlen = 0;
- uint64_t t;
- uint8_t *res;
-
- if (n == 0) {
- *p++ = '0';
- return p;
- }
- for (t = n; t; t /= 10, ++nlen)
- ;
- p += nlen;
- res = p;
- for (; n; n /= 10) {
- *--p = (uint8_t)((n % 10) + '0');
- }
- return res;
-}
-
-static uint8_t *write_numstr(uint8_t *p, uint64_t n) {
- *p++ = '"';
- p = write_number(p, n);
- *p++ = '"';
- return p;
-}
-
-static uint8_t *write_tstamp(uint8_t *p, ngtcp2_tstamp ts) {
- return write_number(p, ts / NGTCP2_MILLISECONDS);
-}
-
-static uint8_t *write_duration(uint8_t *p, ngtcp2_duration duration) {
- return write_number(p, duration / NGTCP2_MILLISECONDS);
-}
-
-static uint8_t *write_bool(uint8_t *p, int b) {
- if (b) {
- return ngtcp2_cpymem(p, "true", sizeof("true") - 1);
- }
- return ngtcp2_cpymem(p, "false", sizeof("false") - 1);
-}
-
-static uint8_t *write_pair(uint8_t *p, const ngtcp2_vec *name,
- const ngtcp2_vec *value) {
- p = write_string(p, name);
- *p++ = ':';
- return write_string(p, value);
-}
-
-static uint8_t *write_pair_hex(uint8_t *p, const ngtcp2_vec *name,
- const ngtcp2_vec *value) {
- p = write_string(p, name);
- *p++ = ':';
- return write_hex(p, value);
-}
-
-static uint8_t *write_pair_numstr(uint8_t *p, const ngtcp2_vec *name,
- uint64_t value) {
- p = write_string(p, name);
- *p++ = ':';
- p = write_numstr(p, value);
- return p;
-}
-
-static uint8_t *write_pair_number(uint8_t *p, const ngtcp2_vec *name,
- uint64_t value) {
- p = write_string(p, name);
- *p++ = ':';
- return write_number(p, value);
-}
-
-static uint8_t *write_pair_duration(uint8_t *p, const ngtcp2_vec *name,
- ngtcp2_tstamp duration) {
- p = write_string(p, name);
- *p++ = ':';
- return write_duration(p, duration);
-}
-
-static uint8_t *write_pair_bool(uint8_t *p, const ngtcp2_vec *name, int b) {
- p = write_string(p, name);
- *p++ = ':';
- return write_bool(p, b);
-}
-
-static uint8_t *write_pair_cid(uint8_t *p, const ngtcp2_vec *name,
- const ngtcp2_cid *cid) {
- p = write_string(p, name);
- *p++ = ':';
- return write_cid(p, cid);
-}
-
-static uint8_t *write_trace_start(uint8_t *p, int server) {
-#define NGTCP2_M \
- "\"traces\":[{\"vantage_point\":{\"name\":\"ngtcp2\",\"type\":\""
- p = ngtcp2_cpymem(p, NGTCP2_M, sizeof(NGTCP2_M) - 1);
-#undef NGTCP2_M
- if (server) {
- p = ngtcp2_cpymem(p, "server", sizeof("server") - 1);
- } else {
- p = ngtcp2_cpymem(p, "client", sizeof("client") - 1);
- }
- *p++ = '"';
- *p++ = '}';
- *p++ = ',';
- return p;
-}
-
-static uint8_t *write_common_fields(uint8_t *p, const ngtcp2_cid *odcid) {
- ngtcp2_vec name;
-#define NGTCP2_M \
- "\"common_fields\":{\"protocol_type\":\"QUIC_HTTP3\",\"reference_" \
- "time\":\"0\","
- p = ngtcp2_cpymem(p, NGTCP2_M, sizeof(NGTCP2_M) - 1);
-#undef NGTCP2_M
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "group_id"), odcid);
- *p++ = ',';
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "ODCID"), odcid);
- *p++ = '}';
- *p++ = ',';
- return p;
-}
-
-static uint8_t *write_event_fields(uint8_t *p) {
-#define NGTCP2_M \
- "\"event_fields\":[\"relative_time\",\"category\",\"event\",\"data\"],"
- p = ngtcp2_cpymem(p, NGTCP2_M, sizeof(NGTCP2_M) - 1);
-#undef NGTCP2_M
- return p;
-}
-
-static uint8_t *write_events_start(uint8_t *p) {
-#define NGTCP2_M "\"events\":["
- p = ngtcp2_cpymem(p, NGTCP2_M, sizeof(NGTCP2_M) - 1);
-#undef NGTCP2_M
- return p;
-}
-
-static uint8_t *write_events_end(uint8_t *p) {
- *p++ = '[';
- *p++ = ']';
- *p++ = ']';
- return p;
-}
-
-static uint8_t *write_trace_end(uint8_t *p) {
- *p++ = '}';
- *p++ = ']';
- return p;
-}
-
-void ngtcp2_qlog_start(ngtcp2_qlog *qlog, const ngtcp2_cid *odcid, int server) {
- uint8_t buf[1024];
- ngtcp2_vec name, value;
- uint8_t *p = buf;
-
- if (!qlog->write) {
- return;
- }
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "qlog_version"),
- ngtcp2_vec_lit(&value, "draft-01"));
- *p++ = ',';
- p = write_trace_start(p, server);
- p = write_common_fields(p, odcid);
- p = write_event_fields(p);
- p = write_events_start(p);
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
- (size_t)(p - buf));
-}
-
-void ngtcp2_qlog_end(ngtcp2_qlog *qlog) {
- uint8_t buf[256];
- uint8_t *p = buf;
-
- if (!qlog->write) {
- return;
- }
-
- p = write_events_end(p);
- p = write_trace_end(p);
- *p++ = '}';
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_FIN, buf,
- (size_t)(p - buf));
-}
-
-static uint8_t *write_pkt_hd(uint8_t *p, const ngtcp2_pkt_hd *hd,
- size_t pktlen) {
- ngtcp2_vec value;
-
- /*
- * {"packet_number":"0000000000000000000","packet_size":0000000000000000000}
- */
-#define NGTCP2_QLOG_PKT_HD_OVERHEAD 73
-
- *p++ = '{';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&value, "packet_number"),
- (uint64_t)hd->pkt_num);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&value, "packet_size"), pktlen);
- /* TODO Write DCIL and DCID */
- /* TODO Write SCIL and SCID */
- *p++ = '}';
- return p;
-}
-
-static ngtcp2_vec *qlog_pkt_type(ngtcp2_vec *dest, const ngtcp2_pkt_hd *hd) {
- if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM) {
- switch (hd->type) {
- case NGTCP2_PKT_INITIAL:
- return ngtcp2_vec_lit(dest, "initial");
- case NGTCP2_PKT_HANDSHAKE:
- return ngtcp2_vec_lit(dest, "handshake");
- case NGTCP2_PKT_0RTT:
- return ngtcp2_vec_lit(dest, "0RTT");
- default:
- return ngtcp2_vec_lit(dest, "unknown");
- }
- }
-
- return ngtcp2_vec_lit(dest, "1RTT");
-}
-
-static uint8_t *write_padding_frame(uint8_t *p, const ngtcp2_padding *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /* {"frame_type":"padding"} */
-#define NGTCP2_QLOG_PADDING_FRAME_OVERHEAD 24
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "padding"));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_ping_frame(uint8_t *p, const ngtcp2_ping *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /* {"frame_type":"ping"} */
-#define NGTCP2_QLOG_PING_FRAME_OVERHEAD 21
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "ping"));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_ack_frame(uint8_t *p, const ngtcp2_ack *fr) {
- ngtcp2_vec name, value;
- int64_t largest_ack, min_ack;
- size_t i;
- const ngtcp2_ack_blk *blk;
-
- /*
- * {"frame_type":"ack","ack_delay":0000000000000000000,"acked_ranges":[]}
- *
- * each range:
- * ["0000000000000000000","0000000000000000000"],
- */
-#define NGTCP2_QLOG_ACK_FRAME_BASE_OVERHEAD 70
-#define NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD 46
-
- *p++ = '{';
- /* TODO Handle ACK ECN */
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "ack"));
- *p++ = ',';
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "ack_delay"),
- fr->ack_delay_unscaled);
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&name, "acked_ranges"));
- *p++ = ':';
- *p++ = '[';
-
- largest_ack = fr->largest_ack;
- min_ack = fr->largest_ack - (int64_t)fr->first_ack_blklen;
-
- *p++ = '[';
- p = write_numstr(p, (uint64_t)min_ack);
- if (largest_ack != min_ack) {
- *p++ = ',';
- p = write_numstr(p, (uint64_t)largest_ack);
- }
- *p++ = ']';
-
- for (i = 0; i < fr->num_blks; ++i) {
- blk = &fr->blks[i];
- largest_ack = min_ack - (int64_t)blk->gap - 2;
- min_ack = largest_ack - (int64_t)blk->blklen;
- *p++ = ',';
- *p++ = '[';
- p = write_numstr(p, (uint64_t)min_ack);
- if (largest_ack != min_ack) {
- *p++ = ',';
- p = write_numstr(p, (uint64_t)largest_ack);
- }
- *p++ = ']';
- }
-
- *p++ = ']';
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_reset_stream_frame(uint8_t *p,
- const ngtcp2_reset_stream *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"reset_stream","stream_id":"0000000000000000000","error_code":0000000000000000000,"final_size":"0000000000000000000"}
- */
-#define NGTCP2_QLOG_RESET_STREAM_FRAME_OVERHEAD 131
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "reset_stream"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "stream_id"),
- (uint64_t)fr->stream_id);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "error_code"),
- fr->app_error_code);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "final_size"), fr->final_size);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_stop_sending_frame(uint8_t *p,
- const ngtcp2_stop_sending *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"stop_sending","stream_id":"0000000000000000000","error_code":0000000000000000000}
- */
-#define NGTCP2_QLOG_STOP_SENDING_FRAME_OVERHEAD 96
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "stop_sending"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "stream_id"),
- (uint64_t)fr->stream_id);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "error_code"),
- fr->app_error_code);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_crypto_frame(uint8_t *p, const ngtcp2_crypto *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"crypto","offset":"0000000000000000000","length":0000000000000000000}
- */
-#define NGTCP2_QLOG_CRYPTO_FRAME_OVERHEAD 83
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "crypto"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "offset"), fr->offset);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "length"),
- ngtcp2_vec_len(fr->data, fr->datacnt));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_new_token_frame(uint8_t *p, const ngtcp2_new_token *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /*
- * {"frame_type":"new_token","length":0000000000000000000,"token":""}
- */
-#define NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD 66
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "new_token"));
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "length"), fr->token.len);
- *p++ = ',';
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "token"), &fr->token);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_stream_frame(uint8_t *p, const ngtcp2_stream *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"stream","stream_id":"0000000000000000000","offset":"0000000000000000000","length":0000000000000000000,"fin":true}
- */
-#define NGTCP2_QLOG_STREAM_FRAME_OVERHEAD 128
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "stream"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "stream_id"),
- (uint64_t)fr->stream_id);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "offset"), fr->offset);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "length"),
- ngtcp2_vec_len(fr->data, fr->datacnt));
- if (fr->fin) {
- *p++ = ',';
- p = write_pair_bool(p, ngtcp2_vec_lit(&name, "fin"), 1);
- }
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_max_data_frame(uint8_t *p, const ngtcp2_max_data *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"max_data","maximum":"0000000000000000000"}
- */
-#define NGTCP2_QLOG_MAX_DATA_FRAME_OVERHEAD 57
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "max_data"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "maximum"), fr->max_data);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_max_stream_data_frame(uint8_t *p,
- const ngtcp2_max_stream_data *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"max_stream_data","stream_id":"0000000000000000000","maximum":"0000000000000000000"}
- */
-#define NGTCP2_QLOG_MAX_STREAM_DATA_FRAME_OVERHEAD 98
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "max_stream_data"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "stream_id"),
- (uint64_t)fr->stream_id);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "maximum"),
- fr->max_stream_data);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_max_streams_frame(uint8_t *p,
- const ngtcp2_max_streams *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"max_streams","stream_type":"unidirectional","maximum":"0000000000000000000"}
- */
-#define NGTCP2_QLOG_MAX_STREAMS_FRAME_OVERHEAD 91
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "max_streams"));
- *p++ = ',';
- p = write_pair(p, ngtcp2_vec_lit(&name, "stream_type"),
- fr->type == NGTCP2_FRAME_MAX_STREAMS_BIDI
- ? ngtcp2_vec_lit(&value, "bidirectional")
- : ngtcp2_vec_lit(&value, "unidirectional"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "maximum"), fr->max_streams);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_data_blocked_frame(uint8_t *p,
- const ngtcp2_data_blocked *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /*
- * {"frame_type":"data_blocked"}
- */
-#define NGTCP2_QLOG_DATA_BLOCKED_FRAME_OVERHEAD 29
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "data_blocked"));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *
-write_stream_data_blocked_frame(uint8_t *p,
- const ngtcp2_stream_data_blocked *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /*
- * {"frame_type":"stream_data_blocked"}
- */
-#define NGTCP2_QLOG_STREAM_DATA_BLOCKED_FRAME_OVERHEAD 36
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "stream_data_blocked"));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_streams_blocked_frame(uint8_t *p,
- const ngtcp2_streams_blocked *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /*
- * {"frame_type":"streams_blocked"}
- */
-#define NGTCP2_QLOG_STREAMS_BLOCKED_FRAME_OVERHEAD 32
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "streams_blocked"));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *
-write_new_connection_id_frame(uint8_t *p, const ngtcp2_new_connection_id *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"new_connection_id","sequence_number":"0000000000000000000","retire_prior_to":"0000000000000000000","length":0000000000000000000,"connection_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","reset_token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
- */
-#define NGTCP2_QLOG_NEW_CONNECTION_ID_FRAME_OVERHEAD 251
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "new_connection_id"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "sequence_number"), fr->seq);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "retire_prior_to"),
- fr->retire_prior_to);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "length"), fr->cid.datalen);
- *p++ = ',';
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "connection_id"), &fr->cid);
- *p++ = ',';
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "reset_token"),
- ngtcp2_vec_init(&value, fr->stateless_reset_token,
- sizeof(fr->stateless_reset_token)));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *
-write_retire_connection_id_frame(uint8_t *p,
- const ngtcp2_retire_connection_id *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"retire_connection_id","sequence_number":"0000000000000000000"}
- */
-#define NGTCP2_QLOG_RETIRE_CONNECTION_ID_FRAME_OVERHEAD 77
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "retire_connection_id"));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "sequence_number"), fr->seq);
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_path_challenge_frame(uint8_t *p,
- const ngtcp2_path_challenge *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"path_challenge","data":"xxxxxxxxxxxxxxxx"}
- */
-#define NGTCP2_QLOG_PATH_CHALLENGE_FRAME_OVERHEAD 57
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "path_challenge"));
- *p++ = ',';
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "data"),
- ngtcp2_vec_init(&value, fr->data, sizeof(fr->data)));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_path_response_frame(uint8_t *p,
- const ngtcp2_path_response *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"path_response","data":"xxxxxxxxxxxxxxxx"}
- */
-#define NGTCP2_QLOG_PATH_RESPONSE_FRAME_OVERHEAD 56
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "path_response"));
- *p++ = ',';
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "data"),
- ngtcp2_vec_init(&value, fr->data, sizeof(fr->data)));
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *
-write_connection_close_frame(uint8_t *p, const ngtcp2_connection_close *fr) {
- ngtcp2_vec name, value;
-
- /*
- * {"frame_type":"connection_close","error_space":"application","error_code":0000000000000000000,"raw_error_code":0000000000000000000,"reason":""}
- */
-#define NGTCP2_QLOG_CONNECTION_CLOSE_FRAME_OVERHEAD 143
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "connection_close"));
- *p++ = ',';
- p = write_pair(p, ngtcp2_vec_lit(&name, "error_space"),
- fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
- ? ngtcp2_vec_lit(&value, "transport")
- : ngtcp2_vec_lit(&value, "application"));
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "error_code"), fr->error_code);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "raw_error_code"),
- fr->error_code);
- *p++ = ',';
- /* TODO Write reason by escaping non-printables */
- p = write_pair(p, ngtcp2_vec_lit(&name, "reason"),
- ngtcp2_vec_lit(&value, ""));
- /* TODO Write trigger_frame_type */
- *p++ = '}';
-
- return p;
-}
-
-static uint8_t *write_handshake_done_frame(uint8_t *p,
- const ngtcp2_handshake_done *fr) {
- ngtcp2_vec name, value;
- (void)fr;
-
- /*
- * {"frame_type":"handshake_done"}
- */
-#define NGTCP2_QLOG_HANDSHAKE_DONE_FRAME_OVERHEAD 31
-
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "frame_type"),
- ngtcp2_vec_lit(&value, "handshake_done"));
- *p++ = '}';
-
- return p;
-}
-
-static void qlog_pkt_write_start(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- int sent) {
- uint8_t *p;
- ngtcp2_vec name, value;
-
- if (!qlog->write) {
- return;
- }
-
- ngtcp2_buf_reset(&qlog->buf);
- p = qlog->buf.last;
-
- *p++ = '[';
- p = write_tstamp(p, qlog->last_ts - qlog->ts);
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "transport"));
- *p++ = ',';
- p = write_string(p, sent ? ngtcp2_vec_lit(&value, "packet_sent")
- : ngtcp2_vec_lit(&value, "packet_received"));
- *p++ = ',';
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "packet_type"),
- qlog_pkt_type(&value, hd));
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "frames"));
- *p++ = ':';
- *p++ = '[';
-
- qlog->buf.last = p;
-}
-
-static void qlog_pkt_write_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- size_t pktlen) {
- uint8_t *p = qlog->buf.last;
- ngtcp2_vec value;
-
- if (!qlog->write) {
- return;
- }
-
- /*
- * ],"header":}],
- */
-#define NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD (14 + NGTCP2_QLOG_PKT_HD_OVERHEAD)
-
- assert(ngtcp2_buf_left(&qlog->buf) >= NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD);
- assert(ngtcp2_buf_len(&qlog->buf));
-
- /* Eat last ',' */
- if (*(p - 1) == ',') {
- --p;
- }
- *p++ = ']';
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "header"));
- *p++ = ':';
- p = write_pkt_hd(p, hd, pktlen);
- *p++ = '}';
- *p++ = ']';
- *p++ = ',';
-
- qlog->buf.last = p;
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, qlog->buf.pos,
- ngtcp2_buf_len(&qlog->buf));
-}
-
-void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr) {
- uint8_t *p = qlog->buf.last;
-
- if (!qlog->write) {
- return;
- }
-
- switch (fr->type) {
- case NGTCP2_FRAME_PADDING:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_PADDING_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_padding_frame(p, &fr->padding);
- break;
- case NGTCP2_FRAME_PING:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_PING_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_ping_frame(p, &fr->ping);
- break;
- case NGTCP2_FRAME_ACK:
- case NGTCP2_FRAME_ACK_ECN:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_ACK_FRAME_BASE_OVERHEAD +
- NGTCP2_QLOG_ACK_FRAME_RANGE_OVERHEAD * (1 + fr->ack.num_blks) + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_ack_frame(p, &fr->ack);
- break;
- case NGTCP2_FRAME_RESET_STREAM:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_RESET_STREAM_FRAME_OVERHEAD +
- 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_reset_stream_frame(p, &fr->reset_stream);
- break;
- case NGTCP2_FRAME_STOP_SENDING:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_STOP_SENDING_FRAME_OVERHEAD +
- 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_stop_sending_frame(p, &fr->stop_sending);
- break;
- case NGTCP2_FRAME_CRYPTO:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_CRYPTO_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_crypto_frame(p, &fr->crypto);
- break;
- case NGTCP2_FRAME_NEW_TOKEN:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_NEW_TOKEN_FRAME_OVERHEAD +
- fr->new_token.token.len * 2 + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_new_token_frame(p, &fr->new_token);
- break;
- case NGTCP2_FRAME_STREAM:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_STREAM_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_stream_frame(p, &fr->stream);
- break;
- case NGTCP2_FRAME_MAX_DATA:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_MAX_DATA_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_max_data_frame(p, &fr->max_data);
- break;
- case NGTCP2_FRAME_MAX_STREAM_DATA:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_MAX_STREAM_DATA_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_max_stream_data_frame(p, &fr->max_stream_data);
- break;
- case NGTCP2_FRAME_MAX_STREAMS_BIDI:
- case NGTCP2_FRAME_MAX_STREAMS_UNI:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_MAX_STREAMS_FRAME_OVERHEAD +
- 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_max_streams_frame(p, &fr->max_streams);
- break;
- case NGTCP2_FRAME_DATA_BLOCKED:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_DATA_BLOCKED_FRAME_OVERHEAD +
- 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_data_blocked_frame(p, &fr->data_blocked);
- break;
- case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_STREAM_DATA_BLOCKED_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_stream_data_blocked_frame(p, &fr->stream_data_blocked);
- break;
- case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
- case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_STREAMS_BLOCKED_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_streams_blocked_frame(p, &fr->streams_blocked);
- break;
- case NGTCP2_FRAME_NEW_CONNECTION_ID:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_NEW_CONNECTION_ID_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_new_connection_id_frame(p, &fr->new_connection_id);
- break;
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_RETIRE_CONNECTION_ID_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_retire_connection_id_frame(p, &fr->retire_connection_id);
- break;
- case NGTCP2_FRAME_PATH_CHALLENGE:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_PATH_CHALLENGE_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_path_challenge_frame(p, &fr->path_challenge);
- break;
- case NGTCP2_FRAME_PATH_RESPONSE:
- if (ngtcp2_buf_left(&qlog->buf) < NGTCP2_QLOG_PATH_RESPONSE_FRAME_OVERHEAD +
- 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_path_response_frame(p, &fr->path_response);
- break;
- case NGTCP2_FRAME_CONNECTION_CLOSE:
- case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_CONNECTION_CLOSE_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_connection_close_frame(p, &fr->connection_close);
- break;
- case NGTCP2_FRAME_HANDSHAKE_DONE:
- if (ngtcp2_buf_left(&qlog->buf) <
- NGTCP2_QLOG_HANDSHAKE_DONE_FRAME_OVERHEAD + 1 +
- NGTCP2_QLOG_PKT_WRITE_END_OVERHEAD) {
- return;
- }
- p = write_handshake_done_frame(p, &fr->handshake_done);
- break;
- default:
- assert(0);
- }
-
- *p++ = ',';
-
- qlog->buf.last = p;
-}
-
-void ngtcp2_qlog_pkt_received_start(ngtcp2_qlog *qlog,
- const ngtcp2_pkt_hd *hd) {
- qlog_pkt_write_start(qlog, hd, /* sent = */ 0);
-}
-
-void ngtcp2_qlog_pkt_received_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- size_t pktlen) {
- qlog_pkt_write_end(qlog, hd, pktlen);
-}
-
-void ngtcp2_qlog_pkt_sent_start(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd) {
- qlog_pkt_write_start(qlog, hd, /* sent = */ 1);
-}
-
-void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- size_t pktlen) {
- qlog_pkt_write_end(qlog, hd, pktlen);
-}
-
-void ngtcp2_qlog_parameters_set_transport_params(
- ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
- ngtcp2_qlog_side side) {
- uint8_t buf[1024];
- uint8_t *p = buf;
- ngtcp2_vec name, value;
- const ngtcp2_preferred_addr *paddr;
-
- if (!qlog->write) {
- return;
- }
-
- *p++ = '[';
- p = write_tstamp(p, qlog->last_ts - qlog->ts);
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "transport"));
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "parameters_set"));
- *p++ = ',';
- *p++ = '{';
- p = write_pair(p, ngtcp2_vec_lit(&name, "owner"),
- side == NGTCP2_QLOG_SIDE_LOCAL
- ? ngtcp2_vec_lit(&value, "local")
- : ngtcp2_vec_lit(&value, "remote"));
- *p++ = ',';
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "initial_source_connection_id"),
- &params->initial_scid);
- *p++ = ',';
- if (side == (server ? NGTCP2_QLOG_SIDE_LOCAL : NGTCP2_QLOG_SIDE_REMOTE)) {
- p = write_pair_cid(
- p, ngtcp2_vec_lit(&name, "original_destination_connection_id"),
- &params->original_dcid);
- *p++ = ',';
- }
- if (params->retry_scid_present) {
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "retry_source_connection_id"),
- &params->retry_scid);
- *p++ = ',';
- }
- if (params->stateless_reset_token_present) {
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "stateless_reset_token"),
- ngtcp2_vec_init(&value, params->stateless_reset_token,
- sizeof(params->stateless_reset_token)));
- *p++ = ',';
- }
- p = write_pair_bool(p, ngtcp2_vec_lit(&name, "disable_active_migration"),
- params->disable_active_migration);
- *p++ = ',';
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "max_idle_timeout"),
- params->max_idle_timeout);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "max_udp_payload_size"),
- params->max_udp_payload_size);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "ack_delay_exponent"),
- params->ack_delay_exponent);
- *p++ = ',';
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "max_ack_delay"),
- params->max_ack_delay);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "active_connection_id_limit"),
- params->active_connection_id_limit);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "initial_max_data"),
- params->initial_max_data);
- *p++ = ',';
- p = write_pair_numstr(
- p, ngtcp2_vec_lit(&name, "initial_max_stream_data_bidi_local"),
- params->initial_max_stream_data_bidi_local);
- *p++ = ',';
- p = write_pair_numstr(
- p, ngtcp2_vec_lit(&name, "initial_max_stream_data_bidi_remote"),
- params->initial_max_stream_data_bidi_remote);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "initial_max_stream_data_uni"),
- params->initial_max_stream_data_uni);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "initial_max_streams_bidi"),
- params->initial_max_streams_bidi);
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "initial_max_streams_uni"),
- params->initial_max_streams_uni);
- if (params->preferred_address_present) {
- *p++ = ',';
- paddr = &params->preferred_address;
- p = write_string(p, ngtcp2_vec_lit(&name, "preferred_address"));
- *p++ = ':';
- *p++ = '{';
- p = write_pair_hex(
- p, ngtcp2_vec_lit(&name, "ip_v4"),
- ngtcp2_vec_init(&value, paddr->ipv4_addr, sizeof(paddr->ipv4_addr)));
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "port_v4"),
- paddr->ipv4_port);
- *p++ = ',';
- p = write_pair_hex(
- p, ngtcp2_vec_lit(&name, "ip_v6"),
- ngtcp2_vec_init(&value, paddr->ipv6_addr, sizeof(paddr->ipv6_addr)));
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "port_v6"),
- paddr->ipv6_port);
- *p++ = ',';
- p = write_pair_cid(p, ngtcp2_vec_lit(&name, "connection_id"), &paddr->cid);
- *p++ = ',';
- p = write_pair_hex(p, ngtcp2_vec_lit(&name, "stateless_reset_token"),
- ngtcp2_vec_init(&value, paddr->stateless_reset_token,
- sizeof(paddr->stateless_reset_token)));
- *p++ = '}';
- }
- *p++ = '}';
- *p++ = ']';
- *p++ = ',';
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
- (size_t)(p - buf));
-}
-
-void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
- const ngtcp2_conn_stat *cstat) {
- uint8_t buf[1024];
- uint8_t *p = buf;
- ngtcp2_vec name, value;
-
- if (!qlog->write) {
- return;
- }
-
- *p++ = '[';
- p = write_tstamp(p, qlog->last_ts - qlog->ts);
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "recovery"));
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "metrics_updated"));
- *p++ = ',';
- *p++ = '{';
-
- if (cstat->min_rtt != UINT64_MAX) {
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "min_rtt"),
- cstat->min_rtt);
- *p++ = ',';
- }
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "smoothed_rtt"),
- cstat->smoothed_rtt);
- *p++ = ',';
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "latest_rtt"),
- cstat->latest_rtt);
- *p++ = ',';
- p = write_pair_duration(p, ngtcp2_vec_lit(&name, "rtt_variance"),
- cstat->rttvar);
- *p++ = ',';
- /* TODO max_ack_delay? */
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "pto_count"),
- cstat->pto_count);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "congestion_window"),
- cstat->cwnd);
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "bytes_in_flight"),
- cstat->bytes_in_flight);
- if (cstat->ssthresh != UINT64_MAX) {
- *p++ = ',';
- p = write_pair_number(p, ngtcp2_vec_lit(&name, "ssthresh"),
- cstat->ssthresh);
- }
-
- *p++ = '}';
- *p++ = ']';
- *p++ = ',';
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
- (size_t)(p - buf));
-}
-
-void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent) {
- uint8_t buf[256];
- uint8_t *p = buf;
- ngtcp2_vec name, value;
- ngtcp2_pkt_hd hd;
-
- if (!qlog->write) {
- return;
- }
-
- *p++ = '[';
- p = write_tstamp(p, qlog->last_ts - qlog->ts);
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "recovery"));
- *p++ = ',';
- p = write_string(p, ngtcp2_vec_lit(&value, "packet_lost"));
- *p++ = ',';
- *p++ = '{';
-
- hd.type = ent->hd.type;
- hd.flags = ent->hd.flags;
-
- p = write_pair(p, ngtcp2_vec_lit(&name, "packet_type"),
- qlog_pkt_type(&value, &hd));
- *p++ = ',';
- p = write_pair_numstr(p, ngtcp2_vec_lit(&name, "packet_number"),
- (uint64_t)ent->hd.pkt_num);
- *p++ = '}';
- *p++ = ']';
- *p++ = ',';
-
- qlog->write(qlog->user_data, NGTCP2_QLOG_WRITE_FLAG_NONE, buf,
- (size_t)(p - buf));
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_qlog.h b/deps/ngtcp2/lib/ngtcp2_qlog.h
deleted file mode 100644
index 0709f92a36..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_qlog.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_QLOG_H
-#define NGTCP2_QLOG_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_pkt.h"
-#include "ngtcp2_cc.h"
-#include "ngtcp2_buf.h"
-#include "ngtcp2_rtb.h"
-
-/* NGTCP2_QLOG_BUFLEN is the length of heap allocated buffer for
- qlog. */
-#define NGTCP2_QLOG_BUFLEN 4096
-
-typedef enum ngtcp2_qlog_side {
- NGTCP2_QLOG_SIDE_LOCAL,
- NGTCP2_QLOG_SIDE_REMOTE,
-} ngtcp2_qlog_side;
-
-typedef struct ngtcp2_qlog {
- /* write is a callback function to write qlog. */
- ngtcp2_qlog_write write;
- /* ts is the initial timestamp */
- ngtcp2_tstamp ts;
- /* last_ts is the timestamp observed last time. */
- ngtcp2_tstamp last_ts;
- /* buf is a heap allocated buffer to write exclusively
- packet_received and packet_sent. */
- ngtcp2_buf buf;
- /* user_data is an opaque pointer which is passed to write
- callback. */
- void *user_data;
-} ngtcp2_qlog;
-
-/*
- * ngtcp2_qlog_init initializes |qlog|.
- */
-void ngtcp2_qlog_init(ngtcp2_qlog *qlog, ngtcp2_qlog_write write,
- ngtcp2_tstamp ts, void *user_data);
-
-/*
- * ngtcp2_qlog_start writes qlog preamble.
- */
-void ngtcp2_qlog_start(ngtcp2_qlog *qlog, const ngtcp2_cid *odcid, int server);
-
-/*
- * ngtcp2_qlog_end writes closing part of qlog.
- */
-void ngtcp2_qlog_end(ngtcp2_qlog *qlog);
-
-/*
- * ngtcp2_qlog_write_frame writes |fr| to qlog->buf.
- * ngtcp2_qlog_pkt_received_start or ngtcp2_qlog_pkt_sent_start must
- * be called before calling this function.
- */
-void ngtcp2_qlog_write_frame(ngtcp2_qlog *qlog, const ngtcp2_frame *fr);
-
-/*
- * ngtcp2_qlog_pkt_received_start starts to write packet_received
- * event. It initializes qlog->buf. It writes qlog to qlog->buf.
- * ngtcp2_qlog_pkt_received_end will flush the content of qlog->buf to
- * write callback.
- */
-void ngtcp2_qlog_pkt_received_start(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd);
-
-/*
- * ngtcp2_qlog_pkt_received_end ends packet_received event and sends
- * the content of qlog->buf to qlog->write callback.
- */
-void ngtcp2_qlog_pkt_received_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- size_t pktlen);
-
-/*
- * ngtcp2_qlog_pkt_sent_start starts to write packet_sent event. It
- * initializes qlog->buf. It writes qlog to qlog->buf.
- * ngtcp2_qlog_pkt_sent_end will flush the content of qlog->buf to
- * write callback.
- */
-void ngtcp2_qlog_pkt_sent_start(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd);
-
-/*
- * ngtcp2_qlog_pkt_sent_end ends packet_sent event and sends the
- * content of qlog->buf to qlog->write callback.
- */
-void ngtcp2_qlog_pkt_sent_end(ngtcp2_qlog *qlog, const ngtcp2_pkt_hd *hd,
- size_t pktlen);
-
-/*
- * ngtcp2_qlog_parameters_set_transport_params writes |params| to qlog
- * as parameters_set event. |server| is nonzero if the local endpoint
- * is server. If |local| is nonzero, it is "owner" field becomes
- * "local", otherwise "remote".
- */
-void ngtcp2_qlog_parameters_set_transport_params(
- ngtcp2_qlog *qlog, const ngtcp2_transport_params *params, int server,
- ngtcp2_qlog_side side);
-
-/*
- * ngtcp2_qlog_metrics_updated writes metrics_updated event of
- * recovery category.
- */
-void ngtcp2_qlog_metrics_updated(ngtcp2_qlog *qlog,
- const ngtcp2_conn_stat *cstat);
-
-/*
- * ngtcp2_qlog_pkt_lost writes packet_lost event.
- */
-void ngtcp2_qlog_pkt_lost(ngtcp2_qlog *qlog, ngtcp2_rtb_entry *ent);
-
-/* connection_id_updated */
-
-#endif /* NGTCP2_QLOG_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_range.c b/deps/ngtcp2/lib/ngtcp2_range.c
deleted file mode 100644
index 9379496b7d..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_range.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_range.h"
-#include "ngtcp2_macro.h"
-
-void ngtcp2_range_init(ngtcp2_range *r, uint64_t begin, uint64_t end) {
- r->begin = begin;
- r->end = end;
-}
-
-ngtcp2_range ngtcp2_range_intersect(const ngtcp2_range *a,
- const ngtcp2_range *b) {
- ngtcp2_range r = {0, 0};
- uint64_t begin = ngtcp2_max(a->begin, b->begin);
- uint64_t end = ngtcp2_min(a->end, b->end);
- if (begin < end) {
- ngtcp2_range_init(&r, begin, end);
- }
- return r;
-}
-
-uint64_t ngtcp2_range_len(const ngtcp2_range *r) { return r->end - r->begin; }
-
-int ngtcp2_range_eq(const ngtcp2_range *a, const ngtcp2_range *b) {
- return a->begin == b->begin && a->end == b->end;
-}
-
-void ngtcp2_range_cut(ngtcp2_range *left, ngtcp2_range *right,
- const ngtcp2_range *a, const ngtcp2_range *b) {
- /* Assume that b is included in a */
- left->begin = a->begin;
- left->end = b->begin;
- right->begin = b->end;
- right->end = a->end;
-}
-
-int ngtcp2_range_not_after(const ngtcp2_range *a, const ngtcp2_range *b) {
- return a->end <= b->end;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_range.h b/deps/ngtcp2/lib/ngtcp2_range.h
deleted file mode 100644
index 96b9a54b28..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_range.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_RANGE_H
-#define NGTCP2_RANGE_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/*
- * ngtcp2_range represents half-closed range [begin, end).
- */
-typedef struct {
- uint64_t begin;
- uint64_t end;
-} ngtcp2_range;
-
-/*
- * ngtcp2_range_init initializes |r| with the range [|begin|, |end|).
- */
-void ngtcp2_range_init(ngtcp2_range *r, uint64_t begin, uint64_t end);
-
-/*
- * ngtcp2_range_intersect returns the intersection of |a| and |b|. If
- * they do not overlap, it returns empty range.
- */
-ngtcp2_range ngtcp2_range_intersect(const ngtcp2_range *a,
- const ngtcp2_range *b);
-
-/*
- * ngtcp2_range_len returns the length of |r|.
- */
-uint64_t ngtcp2_range_len(const ngtcp2_range *r);
-
-/*
- * ngtcp2_range_eq returns nonzero if |a| equals |b|, such that
- * a->begin == b->begin, and a->end == b->end hold.
- */
-int ngtcp2_range_eq(const ngtcp2_range *a, const ngtcp2_range *b);
-
-/*
- * ngtcp2_range_cut returns the left and right range after removing
- * |b| from |a|. This function assumes that |a| completely includes
- * |b|. In other words, a->begin <= b->begin and b->end <= a->end
- * hold.
- */
-void ngtcp2_range_cut(ngtcp2_range *left, ngtcp2_range *right,
- const ngtcp2_range *a, const ngtcp2_range *b);
-
-/*
- * ngtcp2_range_not_after returns nonzero if the right edge of |a|
- * does not go beyond of the right edge of |b|.
- */
-int ngtcp2_range_not_after(const ngtcp2_range *a, const ngtcp2_range *b);
-
-#endif /* NGTCP2_RANGE_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rcvry.h b/deps/ngtcp2/lib/ngtcp2_rcvry.h
deleted file mode 100644
index e392c34ebf..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rcvry.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_RCVRY_H
-#define NGTCP2_RCVRY_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-/* NGTCP2_PKT_THRESHOLD is kPacketThreshold described in
- draft-ietf-quic-recovery-22. */
-#define NGTCP2_PKT_THRESHOLD 3
-
-/* NGTCP2_GRANULARITY is kGranularity described in
- draft-ietf-quic-recovery-17. */
-#define NGTCP2_GRANULARITY NGTCP2_MILLISECONDS
-
-#endif /* NGTCP2_RCVRY_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_ringbuf.c b/deps/ngtcp2/lib/ngtcp2_ringbuf.c
deleted file mode 100644
index e4deab1ff7..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ringbuf.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_ringbuf.h"
-
-#include <assert.h>
-#ifdef WIN32
-# include <intrin.h>
-#endif
-
-#include "ngtcp2_macro.h"
-
-#if defined(_MSC_VER) && defined(_M_ARM64)
-unsigned int __popcnt(unsigned int x) {
- unsigned int c = 0;
- for (; x; ++c) {
- x &= x - 1;
- }
- return c;
-}
-#endif
-
-int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
- const ngtcp2_mem *mem) {
-#ifdef WIN32
- assert(1 == __popcnt((unsigned int)nmemb));
-#else
- assert(1 == __builtin_popcount((unsigned int)nmemb));
-#endif
-
- rb->buf = ngtcp2_mem_malloc(mem, nmemb * size);
- if (rb->buf == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rb->mem = mem;
- rb->nmemb = nmemb;
- rb->size = size;
- rb->first = 0;
- rb->len = 0;
-
- return 0;
-}
-
-void ngtcp2_ringbuf_free(ngtcp2_ringbuf *rb) {
- if (rb == NULL) {
- return;
- }
-
- ngtcp2_mem_free(rb->mem, rb->buf);
-}
-
-void *ngtcp2_ringbuf_push_front(ngtcp2_ringbuf *rb) {
- rb->first = (rb->first - 1) & (rb->nmemb - 1);
- rb->len = ngtcp2_min(rb->nmemb, rb->len + 1);
-
- return (void *)&rb->buf[rb->first * rb->size];
-}
-
-void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb) {
- size_t offset = (rb->first + rb->len) & (rb->nmemb - 1);
-
- if (rb->len == rb->nmemb) {
- rb->first = (rb->first + 1) & (rb->nmemb - 1);
- } else {
- ++rb->len;
- }
-
- return (void *)&rb->buf[offset * rb->size];
-}
-
-void ngtcp2_ringbuf_pop_front(ngtcp2_ringbuf *rb) {
- rb->first = (rb->first + 1) & (rb->nmemb - 1);
- --rb->len;
-}
-
-void ngtcp2_ringbuf_pop_back(ngtcp2_ringbuf *rb) {
- assert(rb->len);
- --rb->len;
-}
-
-void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len) {
- assert(len <= rb->nmemb);
- rb->len = len;
-}
-
-void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset) {
- assert(offset < rb->len);
- offset = (rb->first + offset) & (rb->nmemb - 1);
- return &rb->buf[offset * rb->size];
-}
-
-int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb) { return rb->len == rb->nmemb; }
diff --git a/deps/ngtcp2/lib/ngtcp2_ringbuf.h b/deps/ngtcp2/lib/ngtcp2_ringbuf.h
deleted file mode 100644
index 6d546495f2..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_ringbuf.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_RINGBUF_H
-#define NGTCP2_RINGBUF_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-
-typedef struct {
- /* buf points to the underlying buffer. */
- uint8_t *buf;
- const ngtcp2_mem *mem;
- /* nmemb is the number of elements that can be stored in this ring
- buffer. */
- size_t nmemb;
- /* size is the size of each element. */
- size_t size;
- /* first is the offset to the first element. */
- size_t first;
- /* len is the number of elements actually stored. */
- size_t len;
-} ngtcp2_ringbuf;
-
-/*
- * ngtcp2_ringbuf_init initializes |rb|. |nmemb| is the number of
- * elements that can be stored in this buffer. |size| is the size of
- * each element. |size| must be power of 2.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_ringbuf_free frees resources allocated for |rb|. This
- * function does not free the memory pointed by |rb|.
- */
-void ngtcp2_ringbuf_free(ngtcp2_ringbuf *rb);
-
-/* ngtcp2_ringbuf_push_front moves the offset to the first element in
- the buffer backward, and returns the pointer to the element.
- Caller can store data to the buffer pointed by the returned
- pointer. If this action exceeds the capacity of the ring buffer,
- the last element is silently overwritten, and rb->len remains
- unchanged. */
-void *ngtcp2_ringbuf_push_front(ngtcp2_ringbuf *rb);
-
-/* ngtcp2_ringbuf_push_back moves the offset to the last element in
- the buffer forward, and returns the pointer to the element. Caller
- can store data to the buffer pointed by the returned pointer. If
- this action exceeds the capacity of the ring buffer, the first
- element is silently overwritten, and rb->len remains unchanged. */
-void *ngtcp2_ringbuf_push_back(ngtcp2_ringbuf *rb);
-
-/*
- * ngtcp2_ringbuf_pop_front removes first element in |rb|.
- */
-void ngtcp2_ringbuf_pop_front(ngtcp2_ringbuf *rb);
-
-/*
- * ngtcp2_ringbuf_pop_back removes the last element in |rb|.
- */
-void ngtcp2_ringbuf_pop_back(ngtcp2_ringbuf *rb);
-
-/* ngtcp2_ringbuf_resize changes the number of elements stored. This
- does not change the capacity of the underlying buffer. */
-void ngtcp2_ringbuf_resize(ngtcp2_ringbuf *rb, size_t len);
-
-/* ngtcp2_ringbuf_get returns the pointer to the element at
- |offset|. */
-void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset);
-
-/* ngtcp2_ringbuf_len returns the number of elements stored. */
-#define ngtcp2_ringbuf_len(RB) ((RB)->len)
-
-/* ngtcp2_ringbuf_full returns nonzero if |rb| is full. */
-int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb);
-
-#endif /* NGTCP2_RINGBUF_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rob.c b/deps/ngtcp2/lib/ngtcp2_rob.c
deleted file mode 100644
index 499c07ec6b..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rob.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_rob.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_macro.h"
-
-int ngtcp2_rob_gap_new(ngtcp2_rob_gap **pg, uint64_t begin, uint64_t end,
- const ngtcp2_mem *mem) {
- *pg = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_rob_gap));
- if (*pg == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- (*pg)->range.begin = begin;
- (*pg)->range.end = end;
-
- return 0;
-}
-
-void ngtcp2_rob_gap_del(ngtcp2_rob_gap *g, const ngtcp2_mem *mem) {
- ngtcp2_mem_free(mem, g);
-}
-
-int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk,
- const ngtcp2_mem *mem) {
- *pd = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_rob_data) + chunk);
- if (*pd == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- (*pd)->range.begin = offset;
- (*pd)->range.end = offset + chunk;
- (*pd)->begin = (uint8_t *)(*pd) + sizeof(ngtcp2_rob_data);
- (*pd)->end = (*pd)->begin + chunk;
-
- return 0;
-}
-
-void ngtcp2_rob_data_del(ngtcp2_rob_data *d, const ngtcp2_mem *mem) {
- ngtcp2_mem_free(mem, d);
-}
-
-int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem) {
- int rv;
- ngtcp2_rob_gap *g;
-
- rv = ngtcp2_ksl_init(&rob->gapksl, ngtcp2_ksl_range_compar,
- sizeof(ngtcp2_range), mem);
- if (rv != 0) {
- goto fail_gapksl_ksl_init;
- }
-
- rv = ngtcp2_rob_gap_new(&g, 0, UINT64_MAX, mem);
- if (rv != 0) {
- goto fail_rob_gap_new;
- }
-
- rv = ngtcp2_ksl_insert(&rob->gapksl, NULL, &g->range, g);
- if (rv != 0) {
- goto fail_gapksl_ksl_insert;
- }
-
- rv = ngtcp2_ksl_init(&rob->dataksl, ngtcp2_ksl_range_compar,
- sizeof(ngtcp2_range), mem);
- if (rv != 0) {
- goto fail_dataksl_ksl_init;
- }
-
- rob->chunk = chunk;
- rob->mem = mem;
-
- return 0;
-
-fail_dataksl_ksl_init:
-fail_gapksl_ksl_insert:
- ngtcp2_rob_gap_del(g, mem);
-fail_rob_gap_new:
- ngtcp2_ksl_free(&rob->gapksl);
-fail_gapksl_ksl_init:
- return rv;
-}
-
-void ngtcp2_rob_free(ngtcp2_rob *rob) {
- ngtcp2_ksl_it it;
-
- if (rob == NULL) {
- return;
- }
-
- for (it = ngtcp2_ksl_begin(&rob->dataksl); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ngtcp2_rob_data_del(ngtcp2_ksl_it_get(&it), rob->mem);
- }
-
- for (it = ngtcp2_ksl_begin(&rob->gapksl); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ngtcp2_rob_gap_del(ngtcp2_ksl_it_get(&it), rob->mem);
- }
-
- ngtcp2_ksl_free(&rob->dataksl);
- ngtcp2_ksl_free(&rob->gapksl);
-}
-
-static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
- size_t len) {
- size_t n;
- int rv;
- ngtcp2_rob_data *d;
- ngtcp2_range range = {offset, offset + len};
- ngtcp2_ksl_it it;
-
- for (it = ngtcp2_ksl_lower_bound_compar(&rob->dataksl, &range,
- ngtcp2_ksl_range_exclusive_compar);
- len; ngtcp2_ksl_it_next(&it)) {
- if (ngtcp2_ksl_it_end(&it)) {
- d = NULL;
- } else {
- d = ngtcp2_ksl_it_get(&it);
- }
-
- if (d == NULL || offset < d->range.begin) {
- rv = ngtcp2_rob_data_new(&d, (offset / rob->chunk) * rob->chunk,
- rob->chunk, rob->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_ksl_insert(&rob->dataksl, &it, &d->range, d);
- if (rv != 0) {
- ngtcp2_rob_data_del(d, rob->mem);
- return rv;
- }
- }
-
- n = (size_t)ngtcp2_min((uint64_t)len, d->range.begin + rob->chunk - offset);
- memcpy(d->begin + (offset - d->range.begin), data, n);
- offset += n;
- data += n;
- len -= n;
- }
-
- return 0;
-}
-
-int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
- size_t datalen) {
- int rv;
- ngtcp2_rob_gap *g;
- ngtcp2_range m, l, r, q = {offset, offset + datalen};
- ngtcp2_ksl_it it;
-
- it = ngtcp2_ksl_lower_bound_compar(&rob->gapksl, &q,
- ngtcp2_ksl_range_exclusive_compar);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- g = ngtcp2_ksl_it_get(&it);
-
- m = ngtcp2_range_intersect(&q, &g->range);
- if (!ngtcp2_range_len(&m)) {
- break;
- }
- if (ngtcp2_range_eq(&g->range, &m)) {
- ngtcp2_ksl_remove(&rob->gapksl, &it, &g->range);
- ngtcp2_rob_gap_del(g, rob->mem);
- rv = rob_write_data(rob, m.begin, data + (m.begin - offset),
- (size_t)ngtcp2_range_len(&m));
- if (rv != 0) {
- return rv;
- }
-
- continue;
- }
- ngtcp2_range_cut(&l, &r, &g->range, &m);
- if (ngtcp2_range_len(&l)) {
- ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &l);
- g->range = l;
-
- if (ngtcp2_range_len(&r)) {
- ngtcp2_rob_gap *ng;
- rv = ngtcp2_rob_gap_new(&ng, r.begin, r.end, rob->mem);
- if (rv != 0) {
- return rv;
- }
- rv = ngtcp2_ksl_insert(&rob->gapksl, &it, &ng->range, ng);
- if (rv != 0) {
- ngtcp2_rob_gap_del(ng, rob->mem);
- return rv;
- }
- }
- } else if (ngtcp2_range_len(&r)) {
- ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r);
- g->range = r;
- }
- rv = rob_write_data(rob, m.begin, data + (m.begin - offset),
- (size_t)ngtcp2_range_len(&m));
- if (rv != 0) {
- return rv;
- }
- ngtcp2_ksl_it_next(&it);
- }
- return 0;
-}
-
-int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset) {
- ngtcp2_rob_gap *g;
- ngtcp2_rob_data *d;
- ngtcp2_ksl_it it;
-
- it = ngtcp2_ksl_begin(&rob->gapksl);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- g = ngtcp2_ksl_it_get(&it);
- if (offset <= g->range.begin) {
- break;
- }
- if (offset < g->range.end) {
- ngtcp2_range r = {offset, g->range.end};
- ngtcp2_ksl_update_key(&rob->gapksl, &g->range, &r);
- g->range.begin = offset;
- break;
- }
- ngtcp2_ksl_remove(&rob->gapksl, &it, &g->range);
- ngtcp2_rob_gap_del(g, rob->mem);
- }
-
- it = ngtcp2_ksl_begin(&rob->dataksl);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- d = ngtcp2_ksl_it_get(&it);
- if (offset < d->range.begin + rob->chunk) {
- return 0;
- }
- ngtcp2_ksl_remove(&rob->dataksl, &it, &d->range);
- ngtcp2_rob_data_del(d, rob->mem);
- }
-
- return 0;
-}
-
-size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest,
- uint64_t offset) {
- ngtcp2_rob_gap *g;
- ngtcp2_rob_data *d;
- ngtcp2_ksl_it it;
-
- it = ngtcp2_ksl_begin(&rob->gapksl);
- if (ngtcp2_ksl_it_end(&it)) {
- return 0;
- }
-
- g = ngtcp2_ksl_it_get(&it);
-
- if (g->range.begin <= offset) {
- return 0;
- }
-
- it = ngtcp2_ksl_begin(&rob->dataksl);
- d = ngtcp2_ksl_it_get(&it);
-
- assert(d);
- assert(d->range.begin <= offset);
- assert(offset < d->range.begin + rob->chunk);
-
- *pdest = d->begin + (offset - d->range.begin);
-
- return (size_t)(ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) -
- offset);
-}
-
-void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) {
- ngtcp2_ksl_it it;
- ngtcp2_rob_data *d;
-
- it = ngtcp2_ksl_begin(&rob->dataksl);
- d = ngtcp2_ksl_it_get(&it);
-
- assert(d);
-
- if (offset + len < d->range.begin + rob->chunk) {
- return;
- }
-
- ngtcp2_ksl_remove(&rob->dataksl, NULL, &d->range);
- ngtcp2_rob_data_del(d, rob->mem);
-}
-
-uint64_t ngtcp2_rob_first_gap_offset(ngtcp2_rob *rob) {
- ngtcp2_ksl_it it = ngtcp2_ksl_begin(&rob->gapksl);
- ngtcp2_rob_gap *g;
-
- if (ngtcp2_ksl_it_end(&it)) {
- return UINT64_MAX;
- }
-
- g = ngtcp2_ksl_it_get(&it);
-
- return g->range.begin;
-}
-
-int ngtcp2_rob_data_buffered(ngtcp2_rob *rob) {
- return ngtcp2_ksl_len(&rob->dataksl) != 0;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_rob.h b/deps/ngtcp2/lib/ngtcp2_rob.h
deleted file mode 100644
index c6a039ce40..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rob.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_ROB_H
-#define NGTCP2_ROB_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-#include "ngtcp2_range.h"
-#include "ngtcp2_ksl.h"
-
-struct ngtcp2_rob_gap;
-typedef struct ngtcp2_rob_gap ngtcp2_rob_gap;
-
-/*
- * ngtcp2_rob_gap represents the gap, which is the range of stream
- * data that is not received yet.
- */
-struct ngtcp2_rob_gap {
- /* range is the range of this gap. */
- ngtcp2_range range;
-};
-
-/*
- * ngtcp2_rob_gap_new allocates new ngtcp2_rob_gap object, and assigns
- * its pointer to |*pg|. The caller should call ngtcp2_rob_gap_del to
- * delete it when it is no longer used. The range of the gap is
- * [begin, end). |mem| is custom memory allocator to allocate memory.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_rob_gap_new(ngtcp2_rob_gap **pg, uint64_t begin, uint64_t end,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rob_gap_del deallocates |g|. It deallocates the memory
- * pointed by |g| it self. |mem| is custom memory allocator to
- * deallocate memory.
- */
-void ngtcp2_rob_gap_del(ngtcp2_rob_gap *g, const ngtcp2_mem *mem);
-
-struct ngtcp2_rob_data;
-typedef struct ngtcp2_rob_data ngtcp2_rob_data;
-
-/*
- * ngtcp2_rob_data holds the buffered stream data.
- */
-struct ngtcp2_rob_data {
- /* range is the range of this gap. */
- ngtcp2_range range;
- /* begin points to the buffer. */
- uint8_t *begin;
- /* end points to the one beyond of the last byte of the buffer */
- uint8_t *end;
-};
-
-/*
- * ngtcp2_rob_data_new allocates new ngtcp2_rob_data object, and
- * assigns its pointer to |*pd|. The caller should call
- * ngtcp2_rob_data_del to delete it when it is no longer used.
- * |offset| is the stream offset of the first byte of this data.
- * |chunk| is the size of the buffer. |offset| must be multiple of
- * |chunk|. |mem| is custom memory allocator to allocate memory.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_rob_data_new(ngtcp2_rob_data **pd, uint64_t offset, size_t chunk,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rob_data_del deallocates |d|. It deallocates the memory
- * pointed by |d| itself. |mem| is custom memory allocator to
- * deallocate memory.
- */
-void ngtcp2_rob_data_del(ngtcp2_rob_data *d, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rob is the reorder buffer which reassembles stream data
- * received in out of order.
- */
-typedef struct {
- /* gapksl maintains the range of offset which is not received
- yet. Initially, its range is [0, UINT64_MAX). */
- ngtcp2_ksl gapksl;
- /* dataksl maintains the list of buffers which store received data
- ordered by stream offset. */
- ngtcp2_ksl dataksl;
- /* mem is custom memory allocator */
- const ngtcp2_mem *mem;
- /* chunk is the size of each buffer in data field */
- size_t chunk;
-} ngtcp2_rob;
-
-/*
- * ngtcp2_rob_init initializes |rob|. |chunk| is the size of buffer
- * per chunk.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_rob_init(ngtcp2_rob *rob, size_t chunk, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rob_free frees resources allocated for |rob|.
- */
-void ngtcp2_rob_free(ngtcp2_rob *rob);
-
-/*
- * ngtcp2_rob_push adds new data of length |datalen| at the stream
- * offset |offset|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_rob_push(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data,
- size_t datalen);
-
-/*
- * ngtcp2_rob_remove_prefix removes gap up to |offset|, exclusive. It
- * also removes data buffer if it is completely included in |offset|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_rob_remove_prefix(ngtcp2_rob *rob, uint64_t offset);
-
-/*
- * ngtcp2_rob_data_at stores the pointer to the buffer of stream
- * offset |offset| to |*pdest| if it is available, and returns the
- * valid length of available data. If no data is available, it
- * returns 0.
- */
-size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest,
- uint64_t offset);
-
-/*
- * ngtcp2_rob_pop clears data at stream offset |offset| of length
- * |len|.
- *
- * |offset| must be the offset given in ngtcp2_rob_data_at. |len|
- * must be the return value of ngtcp2_rob_data_at when |offset| is
- * passed.
- *
- * Caller should call this function from offset 0 in non-decreasing
- * order.
- */
-void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len);
-
-/*
- * ngtcp2_rob_first_gap_offset returns the offset to the first gap.
- * If there is no gap, it returns UINT64_MAX.
- */
-uint64_t ngtcp2_rob_first_gap_offset(ngtcp2_rob *rob);
-
-/*
- * ngtcp2_rob_data_buffered returns nonzero if any data is buffered.
- */
-int ngtcp2_rob_data_buffered(ngtcp2_rob *rob);
-
-#endif /* NGTCP2_ROB_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rst.c b/deps/ngtcp2/lib/ngtcp2_rst.c
deleted file mode 100644
index e546fdf85c..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rst.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_rst.h"
-#include "ngtcp2_rtb.h"
-#include "ngtcp2_cc.h"
-#include "ngtcp2_macro.h"
-
-void ngtcp2_rs_init(ngtcp2_rs *rs) {
- rs->interval = UINT64_MAX;
- rs->delivered = 0;
- rs->prior_delivered = 0;
- rs->prior_ts = 0;
- rs->send_elapsed = 0;
- rs->ack_elapsed = 0;
- rs->is_app_limited = 0;
-}
-
-void ngtcp2_rst_init(ngtcp2_rst *rst) {
- ngtcp2_rs_init(&rst->rs);
- rst->delivered = 0;
- rst->delivered_ts = 0;
- rst->first_sent_ts = 0;
- rst->app_limited = 0;
-}
-
-void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
- const ngtcp2_conn_stat *cstat) {
- if (cstat->bytes_in_flight == 0) {
- rst->first_sent_ts = rst->delivered_ts = ent->ts;
- }
- ent->rst.first_sent_ts = rst->first_sent_ts;
- ent->rst.delivered_ts = rst->delivered_ts;
- ent->rst.delivered = rst->delivered;
- ent->rst.is_app_limited = rst->app_limited != 0;
-}
-
-int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) {
- ngtcp2_rs *rs = &rst->rs;
-
- if (rst->app_limited && rst->delivered > rst->app_limited) {
- rst->app_limited = 0;
- }
-
- if (rs->prior_ts == 0) {
- return 0;
- }
-
- rs->interval = ngtcp2_max(rs->send_elapsed, rs->ack_elapsed);
-
- rs->delivered = rst->delivered - rs->prior_delivered;
-
- if (rs->interval < cstat->min_rtt) {
- rs->interval = UINT64_MAX;
- return 0;
- }
-
- if (rs->interval) {
- cstat->delivery_rate_sec = rs->delivered * NGTCP2_SECONDS / rs->interval;
- }
-
- return 0;
-}
-
-void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent,
- ngtcp2_tstamp ts) {
- ngtcp2_rs *rs = &rst->rs;
-
- rst->delivered += ent->pktlen;
- rst->delivered_ts = ts;
-
- if (ent->rst.delivered > rs->prior_delivered) {
- rs->prior_delivered = ent->rst.delivered;
- rs->prior_ts = ent->rst.delivered_ts;
- rs->is_app_limited = ent->rst.is_app_limited;
- rs->send_elapsed = ent->ts - ent->rst.first_sent_ts;
- rs->ack_elapsed = rst->delivered_ts - ent->rst.delivered_ts;
- rst->first_sent_ts = ent->ts;
- }
-}
-
-void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) {
- (void)rst;
- (void)cstat;
- /* TODO Not implemented */
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_rst.h b/deps/ngtcp2/lib/ngtcp2_rst.h
deleted file mode 100644
index f68a1f9b22..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rst.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_RST_H
-#define NGTCP2_RST_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-struct ngtcp2_rtb_entry;
-typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry;
-
-/**
- * @struct
- *
- * ngtcp2_rs contains connection state for delivery rate estimation.
- */
-typedef struct ngtcp2_rs {
- ngtcp2_duration interval;
- uint64_t delivered;
- uint64_t prior_delivered;
- ngtcp2_tstamp prior_ts;
- ngtcp2_duration send_elapsed;
- ngtcp2_duration ack_elapsed;
- int is_app_limited;
-} ngtcp2_rs;
-
-void ngtcp2_rs_init(ngtcp2_rs *rs);
-
-/*
- * ngtcp2_rst implements delivery rate estimation described in
- * https://tools.ietf.org/html/draft-cheng-iccrg-delivery-rate-estimation-00
- */
-typedef struct ngtcp2_rst {
- ngtcp2_rs rs;
- uint64_t delivered;
- ngtcp2_tstamp delivered_ts;
- ngtcp2_tstamp first_sent_ts;
- uint64_t app_limited;
-} ngtcp2_rst;
-
-void ngtcp2_rst_init(ngtcp2_rst *rst);
-
-void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
- const ngtcp2_conn_stat *cstat);
-int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat);
-void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent,
- ngtcp2_tstamp ts);
-void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat);
-
-#endif /* NGTCP2_RST_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/lib/ngtcp2_rtb.c
deleted file mode 100644
index d58a6b2ea1..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rtb.c
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_rtb.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "ngtcp2_macro.h"
-#include "ngtcp2_conn.h"
-#include "ngtcp2_log.h"
-#include "ngtcp2_vec.h"
-#include "ngtcp2_cc.h"
-#include "ngtcp2_rcvry.h"
-#include "ngtcp2_rst.h"
-
-int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem) {
- *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain));
- if (*pfrc == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_frame_chain_init(*pfrc);
-
- return 0;
-}
-
-int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen,
- const ngtcp2_mem *mem) {
- *pfrc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_frame_chain) + extralen);
- if (*pfrc == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- ngtcp2_frame_chain_init(*pfrc);
-
- return 0;
-}
-
-int ngtcp2_frame_chain_stream_datacnt_new(ngtcp2_frame_chain **pfrc,
- size_t datacnt,
- const ngtcp2_mem *mem) {
- size_t need = sizeof(ngtcp2_vec) * (datacnt - 1);
- size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_stream);
-
- if (datacnt > 0 && need > avail) {
- return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem);
- }
-
- return ngtcp2_frame_chain_new(pfrc, mem);
-}
-
-int ngtcp2_frame_chain_crypto_datacnt_new(ngtcp2_frame_chain **pfrc,
- size_t datacnt,
- const ngtcp2_mem *mem) {
- size_t need = sizeof(ngtcp2_vec) * (datacnt - 1);
- size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_crypto);
-
- if (datacnt > 0 && need > avail) {
- return ngtcp2_frame_chain_extralen_new(pfrc, need - avail, mem);
- }
-
- return ngtcp2_frame_chain_new(pfrc, mem);
-}
-
-int ngtcp2_frame_chain_new_token_new(ngtcp2_frame_chain **pfrc,
- const ngtcp2_vec *token,
- const ngtcp2_mem *mem) {
- size_t avail = sizeof(ngtcp2_frame) - sizeof(ngtcp2_new_token);
- int rv;
- uint8_t *p;
- ngtcp2_frame *fr;
-
- if (token->len > avail) {
- rv = ngtcp2_frame_chain_extralen_new(pfrc, token->len - avail, mem);
- } else {
- rv = ngtcp2_frame_chain_new(pfrc, mem);
- }
- if (rv != 0) {
- return rv;
- }
-
- fr = &(*pfrc)->fr;
- fr->type = NGTCP2_FRAME_NEW_TOKEN;
-
- p = (uint8_t *)(*pfrc) + sizeof(ngtcp2_new_token);
- memcpy(p, token->base, token->len);
-
- ngtcp2_vec_init(&fr->new_token.token, p, token->len);
-
- return 0;
-}
-
-void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem) {
- ngtcp2_frame_chain_binder *binder;
-
- if (frc == NULL) {
- return;
- }
-
- binder = frc->binder;
- if (binder && --binder->refcount == 0) {
- ngtcp2_mem_free(mem, binder);
- }
-
- ngtcp2_mem_free(mem, frc);
-}
-
-void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc) {
- frc->next = NULL;
- frc->binder = NULL;
-}
-
-void ngtcp2_frame_chain_list_del(ngtcp2_frame_chain *frc,
- const ngtcp2_mem *mem) {
- ngtcp2_frame_chain *next;
-
- for (; frc;) {
- next = frc->next;
- ngtcp2_frame_chain_del(frc, mem);
- frc = next;
- }
-}
-
-int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder,
- const ngtcp2_mem *mem) {
- *pbinder = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_frame_chain_binder));
- if (*pbinder == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- return 0;
-}
-
-int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b,
- const ngtcp2_mem *mem) {
- ngtcp2_frame_chain_binder *binder;
- int rv;
-
- assert(b->binder == NULL);
-
- if (a->binder == NULL) {
- rv = ngtcp2_frame_chain_binder_new(&binder, mem);
- if (rv != 0) {
- return rv;
- }
-
- a->binder = binder;
- ++a->binder->refcount;
- }
-
- b->binder = a->binder;
- ++b->binder->refcount;
-
- return 0;
-}
-
-int ngtcp2_rtb_entry_new(ngtcp2_rtb_entry **pent, const ngtcp2_pkt_hd *hd,
- ngtcp2_frame_chain *frc, ngtcp2_tstamp ts,
- size_t pktlen, uint8_t flags, const ngtcp2_mem *mem) {
- (*pent) = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_rtb_entry));
- if (*pent == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- (*pent)->hd.pkt_num = hd->pkt_num;
- (*pent)->hd.type = hd->type;
- (*pent)->hd.flags = hd->flags;
- (*pent)->frc = frc;
- (*pent)->ts = ts;
- (*pent)->lost_ts = UINT64_MAX;
- (*pent)->pktlen = pktlen;
- (*pent)->flags = flags;
- (*pent)->next = NULL;
-
- return 0;
-}
-
-void ngtcp2_rtb_entry_del(ngtcp2_rtb_entry *ent, const ngtcp2_mem *mem) {
- if (ent == NULL) {
- return;
- }
-
- ngtcp2_frame_chain_list_del(ent->frc, mem);
-
- ngtcp2_mem_free(mem, ent);
-}
-
-static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *(int64_t *)lhs > *(int64_t *)rhs;
-}
-
-void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
- ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
- ngtcp2_log *log, ngtcp2_qlog *qlog,
- const ngtcp2_mem *mem) {
- ngtcp2_ksl_init(&rtb->ents, greater, sizeof(int64_t), mem);
- rtb->crypto = crypto;
- rtb->rst = rst;
- rtb->cc = cc;
- rtb->log = log;
- rtb->qlog = qlog;
- rtb->mem = mem;
- rtb->largest_acked_tx_pkt_num = -1;
- rtb->num_ack_eliciting = 0;
- rtb->num_retransmittable = 0;
- rtb->probe_pkt_left = 0;
- rtb->pktns_id = pktns_id;
- rtb->cc_pkt_num = 0;
- rtb->cc_bytes_in_flight = 0;
- rtb->persistent_congestion_start_ts = UINT64_MAX;
- rtb->num_lost_pkts = 0;
-}
-
-void ngtcp2_rtb_free(ngtcp2_rtb *rtb) {
- ngtcp2_ksl_it it;
-
- if (rtb == NULL) {
- return;
- }
-
- it = ngtcp2_ksl_begin(&rtb->ents);
-
- for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
- ngtcp2_rtb_entry_del(ngtcp2_ksl_it_get(&it), rtb->mem);
- }
-
- ngtcp2_ksl_free(&rtb->ents);
-}
-
-static void rtb_on_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat) {
- ngtcp2_rst_on_pkt_sent(rtb->rst, ent, cstat);
-
- assert(rtb->cc_pkt_num <= ent->hd.pkt_num);
-
- cstat->bytes_in_flight += ent->pktlen;
- rtb->cc_bytes_in_flight += ent->pktlen;
-
- ngtcp2_rst_update_app_limited(rtb->rst, cstat);
-
- if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- ++rtb->num_ack_eliciting;
- }
- if (ent->flags & NGTCP2_RTB_FLAG_RETRANSMITTABLE) {
- ++rtb->num_retransmittable;
- }
-}
-
-static void rtb_on_remove(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat) {
- if (ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED) {
- return;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- assert(rtb->num_ack_eliciting);
- --rtb->num_ack_eliciting;
- }
-
- if ((ent->flags & NGTCP2_RTB_FLAG_RETRANSMITTABLE) &&
- !(ent->flags & NGTCP2_RTB_FLAG_PTO_RECLAIMED)) {
- assert(rtb->num_retransmittable);
- --rtb->num_retransmittable;
- }
-
- if (rtb->cc_pkt_num <= ent->hd.pkt_num) {
- assert(cstat->bytes_in_flight >= ent->pktlen);
- cstat->bytes_in_flight -= ent->pktlen;
-
- assert(rtb->cc_bytes_in_flight >= ent->pktlen);
- rtb->cc_bytes_in_flight -= ent->pktlen;
- }
-}
-
-/*
- * rtb_reclaim_frame queues unacknowledged frames included in |ent|
- * for retransmission. The re-queued frames are not deleted from
- * |ent|. It returns the number of frames queued.
- */
-static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns,
- ngtcp2_rtb_entry *ent) {
- ngtcp2_frame_chain *frc, *nfrc, **pfrc = &pktns->tx.frq;
- ngtcp2_frame *fr;
- ngtcp2_strm *strm;
- ngtcp2_range gap, range;
- size_t num_reclaimed = 0;
- int rv;
-
- /* PADDING only (or PADDING + ACK ) packets will have NULL
- ent->frc. */
- /* TODO Reconsider the order of pfrc */
- for (frc = ent->frc; frc; frc = frc->next) {
- fr = &frc->fr;
- /* Check that a late ACK acknowledged this frame. */
- if (frc->binder &&
- (frc->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK)) {
- continue;
- }
- switch (frc->fr.type) {
- case NGTCP2_FRAME_STREAM:
- strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id);
- if (strm == NULL) {
- continue;
- }
-
- gap = ngtcp2_strm_get_unacked_range_after(strm, fr->stream.offset);
-
- range.begin = fr->stream.offset;
- range.end = fr->stream.offset +
- ngtcp2_vec_len(fr->stream.data, fr->stream.datacnt);
- range = ngtcp2_range_intersect(&range, &gap);
- if (ngtcp2_range_len(&range) == 0 &&
- (!fr->stream.fin || (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED))) {
- continue;
- }
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, fr->stream.datacnt,
- rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr = *fr;
- ngtcp2_vec_copy(nfrc->fr.stream.data, fr->stream.data,
- fr->stream.datacnt);
-
- rv = ngtcp2_strm_streamfrq_push(strm, nfrc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- return rv;
- }
- if (!ngtcp2_strm_is_tx_queued(strm)) {
- strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn);
- rv = ngtcp2_conn_tx_strmq_push(conn, strm);
- if (rv != 0) {
- return rv;
- }
- }
-
- ++num_reclaimed;
-
- continue;
- case NGTCP2_FRAME_CRYPTO:
- /* Don't resend CRYPTO frame if the whole region it contains has
- been acknowledged */
- gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->crypto.offset);
-
- range.begin = fr->crypto.offset;
- range.end = fr->crypto.offset +
- ngtcp2_vec_len(fr->crypto.data, fr->crypto.datacnt);
- range = ngtcp2_range_intersect(&range, &gap);
- if (ngtcp2_range_len(&range) == 0) {
- continue;
- }
-
- rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, fr->crypto.datacnt,
- rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr = *fr;
- ngtcp2_vec_copy(nfrc->fr.crypto.data, fr->crypto.data,
- fr->crypto.datacnt);
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- &nfrc->fr.crypto.offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, conn->mem);
- return rv;
- }
-
- ++num_reclaimed;
-
- continue;
- case NGTCP2_FRAME_NEW_TOKEN:
- rv = ngtcp2_frame_chain_new_token_new(&nfrc, &fr->new_token.token,
- rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- break;
- default:
- rv = ngtcp2_frame_chain_new(&nfrc, rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- nfrc->fr = *fr;
-
- rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem);
- if (rv != 0) {
- return rv;
- }
-
- break;
- }
-
- ++num_reclaimed;
-
- nfrc->next = *pfrc;
- *pfrc = nfrc;
- pfrc = &nfrc->next;
- }
-
- return (ngtcp2_ssize)num_reclaimed;
-}
-
-static int rtb_on_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
- ngtcp2_rtb_entry *ent, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, ngtcp2_tstamp ts) {
- int rv;
- ngtcp2_ssize reclaimed;
-
- ngtcp2_log_pkt_lost(rtb->log, ent->hd.pkt_num, ent->hd.type, ent->hd.flags,
- ent->ts);
-
- if (rtb->qlog) {
- ngtcp2_qlog_pkt_lost(rtb->qlog, ent);
- }
-
- if (!(ent->flags & NGTCP2_RTB_FLAG_PROBE)) {
- if (ent->flags & NGTCP2_RTB_FLAG_PTO_RECLAIMED) {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " has already been reclaimed on PTO",
- ent->hd.pkt_num);
- assert(!(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED));
- assert(UINT64_MAX == ent->lost_ts);
-
- ent->flags |= NGTCP2_RTB_FLAG_LOST_RETRANSMITTED;
- ent->lost_ts = ts;
-
- ++rtb->num_lost_pkts;
-
- ngtcp2_ksl_it_next(it);
-
- return 0;
- }
-
- if (ent->frc) {
- assert(!(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED));
- assert(UINT64_MAX == ent->lost_ts);
-
- reclaimed = rtb_reclaim_frame(rtb, conn, pktns, ent);
- if (reclaimed < 0) {
- return (int)reclaimed;
- }
-
- if (reclaimed) {
- ent->flags |= NGTCP2_RTB_FLAG_LOST_RETRANSMITTED;
- ent->lost_ts = ts;
-
- ++rtb->num_lost_pkts;
-
- ngtcp2_ksl_it_next(it);
-
- return 0;
- }
- }
- } else {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64
- " is a probe packet, no retransmission is necessary",
- ent->hd.pkt_num);
- }
-
- rv = ngtcp2_ksl_remove(&rtb->ents, it, &ent->hd.pkt_num);
- assert(0 == rv);
-
- ngtcp2_rtb_entry_del(ent, rtb->mem);
-
- return 0;
-}
-
-int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat) {
- int rv;
-
- rv = ngtcp2_ksl_insert(&rtb->ents, NULL, &ent->hd.pkt_num, ent);
- if (rv != 0) {
- return rv;
- }
-
- rtb_on_add(rtb, ent, cstat);
-
- return 0;
-}
-
-ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb) {
- return ngtcp2_ksl_begin(&rtb->ents);
-}
-
-static void rtb_remove(ngtcp2_rtb *rtb, ngtcp2_ksl_it *it,
- ngtcp2_rtb_entry **pent, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat) {
- int rv;
- rv = ngtcp2_ksl_remove(&rtb->ents, it, &ent->hd.pkt_num);
- assert(0 == rv);
- rtb_on_remove(rtb, ent, cstat);
-
- assert(ent->next == NULL);
-
- ngtcp2_list_insert(ent, pent);
-}
-
-static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn *conn) {
- ngtcp2_frame_chain *frc;
- uint64_t prev_stream_offset, stream_offset;
- ngtcp2_strm *strm;
- int rv;
- uint64_t datalen;
- ngtcp2_strm *crypto = rtb->crypto;
- ngtcp2_crypto_level crypto_level;
-
- for (frc = ent->frc; frc; frc = frc->next) {
- if (frc->binder) {
- frc->binder->flags |= NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK;
- }
-
- switch (frc->fr.type) {
- case NGTCP2_FRAME_STREAM:
- strm = ngtcp2_conn_find_stream(conn, frc->fr.stream.stream_id);
- if (strm == NULL) {
- break;
- }
-
- if (frc->fr.stream.fin) {
- strm->flags |= NGTCP2_STRM_FLAG_FIN_ACKED;
- }
-
- prev_stream_offset = ngtcp2_strm_get_acked_offset(strm);
- rv = ngtcp2_strm_ack_data(
- strm, frc->fr.stream.offset,
- ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt));
- if (rv != 0) {
- return rv;
- }
-
- if (conn->callbacks.acked_stream_data_offset) {
- stream_offset = ngtcp2_strm_get_acked_offset(strm);
- datalen = stream_offset - prev_stream_offset;
- if (datalen == 0 && !frc->fr.stream.fin) {
- break;
- }
-
- rv = conn->callbacks.acked_stream_data_offset(
- conn, strm->stream_id, prev_stream_offset, datalen, conn->user_data,
- strm->stream_user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
-
- rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, NGTCP2_NO_ERROR);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGTCP2_FRAME_CRYPTO:
- prev_stream_offset = ngtcp2_strm_get_acked_offset(crypto);
- rv = ngtcp2_strm_ack_data(
- crypto, frc->fr.crypto.offset,
- ngtcp2_vec_len(frc->fr.crypto.data, frc->fr.crypto.datacnt));
- if (rv != 0) {
- return rv;
- }
-
- if (conn->callbacks.acked_crypto_offset) {
- stream_offset = ngtcp2_strm_get_acked_offset(crypto);
- datalen = stream_offset - prev_stream_offset;
- if (datalen == 0) {
- break;
- }
-
- switch (rtb->pktns_id) {
- case NGTCP2_PKTNS_ID_INITIAL:
- crypto_level = NGTCP2_CRYPTO_LEVEL_INITIAL;
- break;
- case NGTCP2_PKTNS_ID_HANDSHAKE:
- crypto_level = NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- break;
- case NGTCP2_PKTNS_ID_APP:
- crypto_level = NGTCP2_CRYPTO_LEVEL_APP;
- break;
- default:
- assert(0);
- }
-
- rv = conn->callbacks.acked_crypto_offset(
- conn, crypto_level, prev_stream_offset, datalen, conn->user_data);
- if (rv != 0) {
- return NGTCP2_ERR_CALLBACK_FAILURE;
- }
- }
- break;
- case NGTCP2_FRAME_RESET_STREAM:
- strm = ngtcp2_conn_find_stream(conn, frc->fr.reset_stream.stream_id);
- if (strm == NULL) {
- break;
- }
- strm->flags |= NGTCP2_STRM_FLAG_RST_ACKED;
- rv = ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, NGTCP2_NO_ERROR);
- if (rv != 0) {
- return rv;
- }
- break;
- case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
- assert(conn->dcid.num_retire_queued);
- --conn->dcid.num_retire_queued;
- break;
- }
- }
- return 0;
-}
-
-static void rtb_on_pkt_acked(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) {
- ngtcp2_cc *cc = rtb->cc;
- ngtcp2_cc_pkt pkt;
-
- ngtcp2_rst_update_rate_sample(rtb->rst, ent, ts);
-
- cc->on_pkt_acked(cc, cstat,
- ngtcp2_cc_pkt_init(&pkt, ent->hd.pkt_num, ent->pktlen,
- rtb->pktns_id, ent->ts),
- ts);
-
- if (!(ent->flags & NGTCP2_RTB_FLAG_PROBE) &&
- (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING)) {
- cstat->pto_count = 0;
- }
-}
-
-ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
- ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
- ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) {
- ngtcp2_rtb_entry *ent;
- int64_t largest_ack = fr->largest_ack, min_ack;
- size_t i;
- int rv;
- ngtcp2_ksl_it it;
- ngtcp2_ssize num_acked = 0;
- ngtcp2_tstamp largest_pkt_sent_ts = UINT64_MAX;
- int64_t pkt_num;
- ngtcp2_cc *cc = rtb->cc;
- ngtcp2_rtb_entry *acked_ent = NULL;
- int ack_eliciting_pkt_acked = 0;
-
- if (conn && (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED) &&
- largest_ack >= conn->pktns.crypto.tx.ckm->pkt_num) {
- conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED;
- conn->crypto.key_update.confirmed_ts = ts;
-
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_CRY, "key update confirmed");
- }
-
- rtb->largest_acked_tx_pkt_num =
- ngtcp2_max(rtb->largest_acked_tx_pkt_num, largest_ack);
-
- /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */
- it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
- if (ngtcp2_ksl_it_end(&it)) {
- return 0;
- }
-
- min_ack = largest_ack - (int64_t)fr->first_ack_blklen;
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
-
- assert(pkt_num <= largest_ack);
-
- if (pkt_num < min_ack) {
- break;
- }
-
- ent = ngtcp2_ksl_it_get(&it);
-
- if (largest_ack == pkt_num) {
- largest_pkt_sent_ts = ent->ts;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- ack_eliciting_pkt_acked = 1;
- }
-
- rtb_remove(rtb, &it, &acked_ent, ent, cstat);
- ++num_acked;
- }
-
- for (i = 0; i < fr->num_blks;) {
- largest_ack = min_ack - (int64_t)fr->blks[i].gap - 2;
- min_ack = largest_ack - (int64_t)fr->blks[i].blklen;
-
- it = ngtcp2_ksl_lower_bound(&rtb->ents, &largest_ack);
- if (ngtcp2_ksl_it_end(&it)) {
- break;
- }
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- pkt_num = *(int64_t *)ngtcp2_ksl_it_key(&it);
- if (pkt_num < min_ack) {
- break;
- }
- ent = ngtcp2_ksl_it_get(&it);
-
- if (ent->flags & NGTCP2_RTB_FLAG_ACK_ELICITING) {
- ack_eliciting_pkt_acked = 1;
- }
-
- rtb_remove(rtb, &it, &acked_ent, ent, cstat);
- ++num_acked;
- }
-
- ++i;
- }
-
- if (largest_pkt_sent_ts != UINT64_MAX && ack_eliciting_pkt_acked) {
- ngtcp2_conn_update_rtt(conn, pkt_ts - largest_pkt_sent_ts,
- fr->ack_delay_unscaled);
- if (cc->new_rtt_sample) {
- cc->new_rtt_sample(cc, cstat, ts);
- }
- }
-
- ngtcp2_rst_on_ack_recv(rtb->rst, cstat);
-
- if (conn) {
- for (ent = acked_ent; ent; ent = acked_ent) {
- rv = rtb_process_acked_pkt(rtb, ent, conn);
- if (rv != 0) {
- goto fail;
- }
-
- rtb_on_pkt_acked(rtb, ent, cstat, ts);
- acked_ent = ent->next;
- ngtcp2_rtb_entry_del(ent, rtb->mem);
- }
- } else {
- /* For unit tests */
- for (ent = acked_ent; ent; ent = acked_ent) {
- rtb_on_pkt_acked(rtb, ent, cstat, ts);
- acked_ent = ent->next;
- ngtcp2_rtb_entry_del(ent, rtb->mem);
- }
- }
-
- cc->on_ack_recv(cc, cstat, ts);
-
- return num_acked;
-
-fail:
- for (ent = acked_ent; ent; ent = acked_ent) {
- acked_ent = ent->next;
- ngtcp2_rtb_entry_del(ent, rtb->mem);
- }
-
- return rv;
-}
-
-static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat,
- const ngtcp2_rtb_entry *ent, uint64_t loss_delay,
- ngtcp2_tstamp lost_send_time, uint64_t pkt_thres) {
- ngtcp2_tstamp loss_time;
-
- if (ent->ts <= lost_send_time ||
- rtb->largest_acked_tx_pkt_num >= ent->hd.pkt_num + (int64_t)pkt_thres) {
- return 1;
- }
-
- loss_time = cstat->loss_time[rtb->pktns_id];
-
- if (loss_time == UINT64_MAX) {
- loss_time = ent->ts + loss_delay;
- } else {
- loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay);
- }
-
- cstat->loss_time[rtb->pktns_id] = loss_time;
-
- return 0;
-}
-
-/*
- * rtb_compute_pkt_loss_delay computes loss delay.
- */
-static ngtcp2_duration compute_pkt_loss_delay(const ngtcp2_conn_stat *cstat) {
- /* 9/8 is kTimeThreshold */
- ngtcp2_duration loss_delay =
- ngtcp2_max(cstat->latest_rtt, cstat->smoothed_rtt) * 9 / 8;
- return ngtcp2_max(loss_delay, NGTCP2_GRANULARITY);
-}
-
-int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
- ngtcp2_duration pto, ngtcp2_tstamp ts) {
- ngtcp2_rtb_entry *ent;
- ngtcp2_duration loss_delay;
- ngtcp2_tstamp lost_send_time;
- ngtcp2_ksl_it it;
- ngtcp2_tstamp latest_ts, oldest_ts;
- int64_t last_lost_pkt_num;
- ngtcp2_duration loss_window, congestion_period;
- ngtcp2_cc *cc = rtb->cc;
- int rv;
- uint64_t pkt_thres =
- rtb->cc_bytes_in_flight / cstat->max_udp_payload_size / 2;
-
- pkt_thres = ngtcp2_max(pkt_thres, NGTCP2_PKT_THRESHOLD);
- cstat->loss_time[rtb->pktns_id] = UINT64_MAX;
- loss_delay = compute_pkt_loss_delay(cstat);
- lost_send_time = ts - loss_delay;
-
- it = ngtcp2_ksl_lower_bound(&rtb->ents, &rtb->largest_acked_tx_pkt_num);
- for (; !ngtcp2_ksl_it_end(&it); ngtcp2_ksl_it_next(&it)) {
- ent = ngtcp2_ksl_it_get(&it);
-
- if (ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED) {
- break;
- }
-
- if (rtb_pkt_lost(rtb, cstat, ent, loss_delay, lost_send_time, pkt_thres)) {
- /* All entries from ent are considered to be lost. */
- latest_ts = oldest_ts = ent->ts;
- last_lost_pkt_num = ent->hd.pkt_num;
-
- congestion_period = pto * NGTCP2_PERSISTENT_CONGESTION_THRESHOLD;
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- ent = ngtcp2_ksl_it_get(&it);
-
- if (last_lost_pkt_num == ent->hd.pkt_num + 1 &&
- ent->ts >= rtb->persistent_congestion_start_ts) {
- last_lost_pkt_num = ent->hd.pkt_num;
- oldest_ts = ent->ts;
- } else {
- last_lost_pkt_num = -1;
- }
-
- if ((ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED)) {
- if (rtb->pktns_id != NGTCP2_PKTNS_ID_APP || last_lost_pkt_num == -1 ||
- latest_ts - oldest_ts >= congestion_period) {
- break;
- }
- ngtcp2_ksl_it_next(&it);
- continue;
- }
-
- rtb_on_remove(rtb, ent, cstat);
- rv = rtb_on_pkt_lost(rtb, &it, ent, conn, pktns, ts);
- if (rv != 0) {
- return rv;
- }
- }
-
- cc->congestion_event(cc, cstat, latest_ts, ts);
-
- loss_window = latest_ts - oldest_ts;
- /* Persistent congestion situation is only evaluated for app
- * packet number space and for the packets sent after handshake
- * is confirmed. During handshake, there is not much packets
- * sent and also people seem to do lots of effort not to trigger
- * persistent congestion there, then it is a lot easier to just
- * not enable it during handshake.
- */
- if (rtb->pktns_id == NGTCP2_PKTNS_ID_APP && loss_window > 0) {
- if (loss_window >= congestion_period) {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "persistent congestion loss_window=%" PRIu64
- " congestion_period=%" PRIu64,
- loss_window, congestion_period);
-
- cc->on_persistent_congestion(cc, cstat, ts);
- }
- }
-
- break;
- }
- }
-
- ngtcp2_rtb_remove_excessive_lost_pkt(rtb, pkt_thres);
-
- return 0;
-}
-
-void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n) {
- ngtcp2_ksl_it it = ngtcp2_ksl_end(&rtb->ents);
- ngtcp2_rtb_entry *ent;
- int rv;
-
- for (; rtb->num_lost_pkts > n;) {
- assert(ngtcp2_ksl_it_end(&it));
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
-
- assert(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED);
-
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "removing stale lost pkn=%" PRId64, ent->hd.pkt_num);
-
- --rtb->num_lost_pkts;
- rv = ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
- assert(0 == rv);
- ngtcp2_rtb_entry_del(ent, rtb->mem);
- }
-}
-
-void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto,
- ngtcp2_tstamp ts) {
- ngtcp2_ksl_it it;
- ngtcp2_rtb_entry *ent;
- int rv;
-
- if (ngtcp2_ksl_len(&rtb->ents) == 0) {
- return;
- }
-
- it = ngtcp2_ksl_end(&rtb->ents);
-
- for (;;) {
- assert(ngtcp2_ksl_it_end(&it));
-
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
-
- if (!(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED) ||
- ts - ent->lost_ts < pto) {
- return;
- }
-
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "removing stale lost pkn=%" PRId64, ent->hd.pkt_num);
-
- --rtb->num_lost_pkts;
- rv = ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
- assert(0 == rv);
- ngtcp2_rtb_entry_del(ent, rtb->mem);
-
- if (ngtcp2_ksl_len(&rtb->ents) == 0) {
- return;
- }
- }
-}
-
-ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb) {
- ngtcp2_ksl_it it;
- ngtcp2_rtb_entry *ent;
-
- if (ngtcp2_ksl_len(&rtb->ents) == 0) {
- return UINT64_MAX;
- }
-
- it = ngtcp2_ksl_end(&rtb->ents);
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
-
- if (!(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED)) {
- return UINT64_MAX;
- }
-
- return ent->lost_ts;
-}
-
-static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns,
- ngtcp2_rtb_entry *ent) {
- ngtcp2_frame_chain **pfrc, *frc;
- ngtcp2_stream *sfr;
- ngtcp2_strm *strm;
- int rv;
-
- ngtcp2_log_pkt_lost(rtb->log, ent->hd.pkt_num, ent->hd.type, ent->hd.flags,
- ent->ts);
-
- if (rtb->qlog) {
- ngtcp2_qlog_pkt_lost(rtb->qlog, ent);
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_PROBE) {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64
- " is a probe packet, no retransmission is necessary",
- ent->hd.pkt_num);
- return 0;
- }
-
- if (!ent->frc) {
- /* PADDING only (or PADDING + ACK ) packets will have NULL
- ent->frc. */
- assert(!(ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED));
- assert(!(ent->flags & NGTCP2_RTB_FLAG_PTO_RECLAIMED));
- return 0;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED) {
- --rtb->num_lost_pkts;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_LOST_RETRANSMITTED) {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64
- " was declared lost and has already been retransmitted",
- ent->hd.pkt_num);
- return 0;
- }
-
- if (ent->flags & NGTCP2_RTB_FLAG_PTO_RECLAIMED) {
- ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_RCV,
- "pkn=%" PRId64 " has already been reclaimed on PTO",
- ent->hd.pkt_num);
- return 0;
- }
-
- pfrc = &ent->frc;
-
- for (; *pfrc;) {
- switch ((*pfrc)->fr.type) {
- case NGTCP2_FRAME_STREAM:
- frc = *pfrc;
-
- *pfrc = frc->next;
- frc->next = NULL;
- sfr = &frc->fr.stream;
-
- strm = ngtcp2_conn_find_stream(conn, sfr->stream_id);
- if (!strm) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- break;
- }
- rv = ngtcp2_strm_streamfrq_push(strm, frc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- if (!ngtcp2_strm_is_tx_queued(strm)) {
- strm->cycle = ngtcp2_conn_tx_strmq_first_cycle(conn);
- rv = ngtcp2_conn_tx_strmq_push(conn, strm);
- if (rv != 0) {
- return rv;
- }
- }
- break;
- case NGTCP2_FRAME_CRYPTO:
- frc = *pfrc;
-
- *pfrc = frc->next;
- frc->next = NULL;
-
- rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL,
- &frc->fr.crypto.offset, frc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, conn->mem);
- return rv;
- }
- break;
- default:
- pfrc = &(*pfrc)->next;
- }
- }
-
- *pfrc = pktns->tx.frq;
- pktns->tx.frq = ent->frc;
- ent->frc = NULL;
-
- return 0;
-}
-
-int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat) {
- ngtcp2_rtb_entry *ent;
- ngtcp2_ksl_it it;
- int rv;
-
- it = ngtcp2_ksl_begin(&rtb->ents);
-
- for (; !ngtcp2_ksl_it_end(&it);) {
- ent = ngtcp2_ksl_it_get(&it);
-
- rtb_on_remove(rtb, ent, cstat);
- rv = ngtcp2_ksl_remove(&rtb->ents, &it, &ent->hd.pkt_num);
- assert(0 == rv);
-
- rv = rtb_on_pkt_lost_resched_move(rtb, conn, pktns, ent);
- ngtcp2_rtb_entry_del(ent, rtb->mem);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-int ngtcp2_rtb_empty(ngtcp2_rtb *rtb) {
- return ngtcp2_ksl_len(&rtb->ents) == 0;
-}
-
-void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num) {
- rtb->cc_pkt_num = cc_pkt_num;
- rtb->cc_bytes_in_flight = 0;
-}
-
-ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, size_t num_pkts) {
- ngtcp2_ksl_it it;
- ngtcp2_rtb_entry *ent;
- ngtcp2_ssize reclaimed;
- size_t atmost = num_pkts;
-
- it = ngtcp2_ksl_end(&rtb->ents);
- for (; !ngtcp2_ksl_it_begin(&it) && num_pkts >= 1;) {
- ngtcp2_ksl_it_prev(&it);
- ent = ngtcp2_ksl_it_get(&it);
-
- if ((ent->flags & (NGTCP2_RTB_FLAG_LOST_RETRANSMITTED |
- NGTCP2_RTB_FLAG_PTO_RECLAIMED)) ||
- !(ent->flags & NGTCP2_RTB_FLAG_RETRANSMITTABLE)) {
- continue;
- }
-
- assert(ent->frc);
-
- reclaimed = rtb_reclaim_frame(rtb, conn, pktns, ent);
- if (reclaimed < 0) {
- return reclaimed;
- }
-
- /* Mark reclaimed even if reclaimed == 0 so that we can skip it in
- the next run. */
- ent->flags |= NGTCP2_RTB_FLAG_PTO_RECLAIMED;
-
- assert(rtb->num_retransmittable);
- --rtb->num_retransmittable;
-
- if (reclaimed) {
- --num_pkts;
- }
- }
-
- return (ngtcp2_ssize)(atmost - num_pkts);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_rtb.h b/deps/ngtcp2/lib/ngtcp2_rtb.h
deleted file mode 100644
index 0d0b738f39..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_rtb.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_RTB_H
-#define NGTCP2_RTB_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_pkt.h"
-#include "ngtcp2_ksl.h"
-#include "ngtcp2_pq.h"
-
-struct ngtcp2_conn;
-typedef struct ngtcp2_conn ngtcp2_conn;
-
-typedef struct ngtcp2_pktns ngtcp2_pktns;
-
-struct ngtcp2_frame_chain;
-typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
-
-struct ngtcp2_log;
-typedef struct ngtcp2_log ngtcp2_log;
-
-struct ngtcp2_qlog;
-typedef struct ngtcp2_qlog ngtcp2_qlog;
-
-struct ngtcp2_strm;
-typedef struct ngtcp2_strm ngtcp2_strm;
-
-struct ngtcp2_rst;
-typedef struct ngtcp2_rst ngtcp2_rst;
-
-typedef enum ngtcp2_frame_chain_binder_flag {
- NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE = 0x00,
- /* NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK indicates that an information
- which a frame carries has been acknowledged. */
- NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK = 0x01,
-} ngtcp2_frame_chain_binder_flag;
-
-/*
- * ngtcp2_frame_chain_binder binds 2 or more of ngtcp2_frame_chain to
- * share the acknowledgement state. In general, all
- * ngtcp2_frame_chains bound to the same binder must have the same
- * information.
- */
-typedef struct ngtcp2_frame_chain_binder {
- size_t refcount;
- uint32_t flags;
-} ngtcp2_frame_chain_binder;
-
-int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using
- * new or existing ngtcp2_frame_chain_binder. |a| might have non-NULL
- * a->binder. |b| must not have non-NULL b->binder.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain chains frames in a single packet.
- */
-struct ngtcp2_frame_chain {
- ngtcp2_frame_chain *next;
- ngtcp2_frame_chain_binder *binder;
- ngtcp2_frame fr;
-};
-
-/* NGTCP2_MAX_STREAM_DATACNT is the maximum number of ngtcp2_vec that
- a ngtcp2_stream can include. */
-#define NGTCP2_MAX_STREAM_DATACNT 256
-
-/* NGTCP2_MAX_CRYPTO_DATACNT is the maximum number of ngtcp2_vec that
- a ngtcp2_crypto can include. */
-#define NGTCP2_MAX_CRYPTO_DATACNT 8
-
-/*
- * ngtcp2_frame_chain_new allocates ngtcp2_frame_chain object and
- * assigns its pointer to |*pfrc|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain_extralen_new works like ngtcp2_frame_chain_new,
- * but it allocates extra memory |extralen| in order to extend
- * ngtcp2_frame.
- */
-int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain_stream_datacnt_new works like
- * ngtcp2_frame_chain_new, but it allocates enough data to store
- * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream
- * object. If |datacnt| equals to 1, ngtcp2_frame_chain_new is called
- * internally.
- */
-int ngtcp2_frame_chain_stream_datacnt_new(ngtcp2_frame_chain **pfrc,
- size_t datacnt,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain_crypto_datacnt_new works like
- * ngtcp2_frame_chain_new, but it allocates enough data to store
- * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_crypto
- * object. If |datacnt| equals to 1, ngtcp2_frame_chain_new is called
- * internally.
- */
-int ngtcp2_frame_chain_crypto_datacnt_new(ngtcp2_frame_chain **pfrc,
- size_t datacnt,
- const ngtcp2_mem *mem);
-
-int ngtcp2_frame_chain_new_token_new(ngtcp2_frame_chain **pfrc,
- const ngtcp2_vec *token,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain_del deallocates |frc|. It also deallocates the
- * memory pointed by |frc|.
- */
-void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_frame_chain_init initializes |frc|.
- */
-void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc);
-
-/*
- * ngtcp2_frame_chain_list_del deletes |frc|, and all objects
- * connected by next field.
- */
-void ngtcp2_frame_chain_list_del(ngtcp2_frame_chain *frc,
- const ngtcp2_mem *mem);
-
-typedef enum {
- NGTCP2_RTB_FLAG_NONE = 0x00,
- /* NGTCP2_RTB_FLAG_PROBE indicates that the entry includes a probe
- packet. */
- NGTCP2_RTB_FLAG_PROBE = 0x01,
- /* NGTCP2_RTB_FLAG_RETRANSMITTABLE indicates that the entry includes
- a frame which must be retransmitted until it is acknowledged. In
- most cases, this flag is used along with
- NGTCP2_RTB_FLAG_ACK_ELICITING. We have these 2 flags because
- NGTCP2_RTB_FLAG_RETRANSMITTABLE triggers PTO, but just
- NGTCP2_RTB_FLAG_ACK_ELICITING does not. */
- NGTCP2_RTB_FLAG_RETRANSMITTABLE = 0x02,
- /* NGTCP2_RTB_FLAG_ACK_ELICITING indicates that the entry elicits
- acknowledgement. */
- NGTCP2_RTB_FLAG_ACK_ELICITING = 0x04,
- /* NGTCP2_RTB_FLAG_PTO_RECLAIMED indicates that the packet has been
- reclaimed on PTO. It is not marked lost yet and still consumes
- congestion window. */
- NGTCP2_RTB_FLAG_PTO_RECLAIMED = 0x08,
- /* NGTCP2_RTB_FLAG_LOST_RETRANSMITTED indicates that the entry has
- been marked lost and scheduled to retransmit. */
- NGTCP2_RTB_FLAG_LOST_RETRANSMITTED = 0x10,
-} ngtcp2_rtb_flag;
-
-struct ngtcp2_rtb_entry;
-typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry;
-
-/*
- * ngtcp2_rtb_entry is an object stored in ngtcp2_rtb. It corresponds
- * to the one packet which is waiting for its ACK.
- */
-struct ngtcp2_rtb_entry {
- ngtcp2_rtb_entry *next;
-
- struct {
- int64_t pkt_num;
- uint8_t type;
- uint8_t flags;
- } hd;
- ngtcp2_frame_chain *frc;
- /* ts is the time point when a packet included in this entry is sent
- to a peer. */
- ngtcp2_tstamp ts;
- /* lost_ts is the time when this entry is marked lost. */
- ngtcp2_tstamp lost_ts;
- /* pktlen is the length of QUIC packet */
- size_t pktlen;
- struct {
- uint64_t delivered;
- ngtcp2_tstamp delivered_ts;
- ngtcp2_tstamp first_sent_ts;
- int is_app_limited;
- } rst;
- /* flags is bitwise-OR of zero or more of ngtcp2_rtb_flag. */
- uint8_t flags;
-};
-
-/*
- * ngtcp2_rtb_entry_new allocates ngtcp2_rtb_entry object, and assigns
- * its pointer to |*pent|. On success, |*pent| takes ownership of
- * |frc|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory.
- */
-int ngtcp2_rtb_entry_new(ngtcp2_rtb_entry **pent, const ngtcp2_pkt_hd *hd,
- ngtcp2_frame_chain *frc, ngtcp2_tstamp ts,
- size_t pktlen, uint8_t flags, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rtb_entry_del deallocates |ent|. It also frees memory
- * pointed by |ent|.
- */
-void ngtcp2_rtb_entry_del(ngtcp2_rtb_entry *ent, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rtb tracks sent packets, and its ACK timeout for
- * retransmission.
- */
-typedef struct {
- /* ents includes ngtcp2_rtb_entry sorted by decreasing order of
- packet number. */
- ngtcp2_ksl ents;
- /* crypto is CRYPTO stream. */
- ngtcp2_strm *crypto;
- ngtcp2_rst *rst;
- ngtcp2_cc *cc;
- ngtcp2_log *log;
- ngtcp2_qlog *qlog;
- const ngtcp2_mem *mem;
- /* largest_acked_tx_pkt_num is the largest packet number
- acknowledged by the peer. */
- int64_t largest_acked_tx_pkt_num;
- /* num_ack_eliciting is the number of ACK eliciting entries. */
- size_t num_ack_eliciting;
- /* num_retransmittable is the number of packets which contain frames
- that must be retransmitted on loss. */
- size_t num_retransmittable;
- /* probe_pkt_left is the number of probe packet to send */
- size_t probe_pkt_left;
- /* pktns_id is the identifier of packet number space. */
- ngtcp2_pktns_id pktns_id;
- /* cc_pkt_num is the smallest packet number that is contributed to
- ngtcp2_conn_stat.bytes_in_flight. */
- int64_t cc_pkt_num;
- /* cc_bytes_in_flight is the number of in-flight bytes that is
- contributed to ngtcp2_conn_stat.bytes_in_flight. It only
- includes the bytes after congestion state is reset. */
- uint64_t cc_bytes_in_flight;
- /* persistent_congestion_start_ts is the time when persistent
- congestion evaluation is started. It happens roughly after
- handshake is confirmed. */
- ngtcp2_tstamp persistent_congestion_start_ts;
- /* num_lost_pkts is the number entries in ents which has
- NGTCP2_RTB_FLAG_LOST_RETRANSMITTED flag set. */
- size_t num_lost_pkts;
-} ngtcp2_rtb;
-
-/*
- * ngtcp2_rtb_init initializes |rtb|.
- */
-void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
- ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
- ngtcp2_log *log, ngtcp2_qlog *qlog, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_rtb_free deallocates resources allocated for |rtb|.
- */
-void ngtcp2_rtb_free(ngtcp2_rtb *rtb);
-
-/*
- * ngtcp2_rtb_add adds |ent| to |rtb|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
- ngtcp2_conn_stat *cstat);
-
-/*
- * ngtcp2_rtb_head returns the iterator which points to the entry
- * which has the largest packet number. If there is no entry,
- * returned value satisfies ngtcp2_ksl_it_end(&it) != 0.
- */
-ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb);
-
-/*
- * ngtcp2_rtb_recv_ack removes acked ngtcp2_rtb_entry from |rtb|.
- * |pkt_num| is a packet number which includes |fr|. |pkt_ts| is the
- * timestamp when packet is received. |ts| should be the current
- * time. Usually they are the same, but for buffered packets,
- * |pkt_ts| would be earlier than |ts|.
- *
- * This function returns the number of newly acknowledged packets if
- * it succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_CALLBACK_FAILURE
- * User callback failed
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
- ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
- ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_rtb_detect_lost_pkt detects lost packets and prepends the
- * frames contained them to |*pfrc|. Even when this function fails,
- * some frames might be prepended to |*pfrc| and the caller should
- * handle them. |pto| is PTO.
- */
-int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
- ngtcp2_duration pto, ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_rtb_remove_expired_lost_pkt removes expired lost packet.
- */
-void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto,
- ngtcp2_tstamp ts);
-
-/*
- * ngtcp2_rtb_lost_pkt_ts returns the earliest time when the still
- * retained packet was lost. It returns UINT64_MAX if no such packet
- * exists.
- */
-ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb);
-
-/*
- * ngtcp2_rtb_remove_all removes all packets from |rtb| and prepends
- * all frames to |*pfrc|. Even when this function fails, some frames
- * might be prepended to |*pfrc| and the caller should handle them.
- */
-int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat);
-
-/*
- * ngtcp2_rtb_empty returns nonzero if |rtb| have no entry.
- */
-int ngtcp2_rtb_empty(ngtcp2_rtb *rtb);
-
-/*
- * ngtcp2_rtb_reset_cc_state resets congestion state in |rtb|.
- * |cc_pkt_num| is the next outbound packet number which is sent under
- * new congestion state.
- */
-void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num);
-
-/*
- * ngtcp2_rtb_remove_expired_lost_pkt ensures that the number of lost
- * packets at most |n|.
- */
-void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n);
-
-/*
- * ngtcp2_rtb_reclaim_on_pto reclaims up to |num_pkts| packets which
- * are in-flight and not marked lost to send them in PTO probe. The
- * reclaimed frames are chained to |*pfrc|.
- *
- * This function returns the number of packets reclaimed if it
- * succeeds, or one of the following negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
- ngtcp2_pktns *pktns, size_t num_pkts);
-
-#endif /* NGTCP2_RTB_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_str.c b/deps/ngtcp2/lib/ngtcp2_str.c
deleted file mode 100644
index b7502e3bd0..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_str.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_str.h"
-
-#include <string.h>
-
-void *ngtcp2_cpymem(void *dest, const void *src, size_t n) {
- memcpy(dest, src, n);
- return (uint8_t *)dest + n;
-}
-
-uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n) {
- memset(dest, b, n);
- return dest + n;
-}
-
-#define LOWER_XDIGITS "0123456789abcdef"
-
-uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) {
- size_t i;
- uint8_t *p = dest;
-
- for (i = 0; i < len; ++i) {
- *p++ = (uint8_t)LOWER_XDIGITS[data[i] >> 4];
- *p++ = (uint8_t)LOWER_XDIGITS[data[i] & 0xf];
- }
-
- *p = '\0';
-
- return dest;
-}
-
-char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
- size_t len) {
- size_t i;
- char *p = dest;
- uint8_t c;
-
- for (i = 0; i < len; ++i) {
- c = data[i];
- if (0x20 <= c && c <= 0x7e) {
- *p++ = (char)c;
- } else {
- *p++ = '.';
- }
- }
-
- *p = '\0';
-
- return dest;
-}
-
-int ngtcp2_verify_stateless_reset_token(const uint8_t *want,
- const uint8_t *got) {
- return !ngtcp2_check_invalid_stateless_reset_token(got) &&
- ngtcp2_cmemeq(want, got, NGTCP2_STATELESS_RESET_TOKENLEN)
- ? 0
- : NGTCP2_ERR_INVALID_ARGUMENT;
-}
-
-int ngtcp2_check_invalid_stateless_reset_token(const uint8_t *token) {
- static uint8_t invalid_token[NGTCP2_STATELESS_RESET_TOKENLEN] = {0};
-
- return 0 == memcmp(invalid_token, token, NGTCP2_STATELESS_RESET_TOKENLEN);
-}
-
-int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n) {
- size_t i;
- int rv = 0;
-
- for (i = 0; i < n; ++i) {
- rv |= a[i] ^ b[i];
- }
-
- return rv == 0;
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_str.h b/deps/ngtcp2/lib/ngtcp2_str.h
deleted file mode 100644
index 104b1f1a03..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_str.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_STR_H
-#define NGTCP2_STR_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-void *ngtcp2_cpymem(void *dest, const void *src, size_t n);
-
-/*
- * ngtcp2_setmem writes a string of length |n| consisting only |b| to
- * the buffer pointed by |dest|. It returns dest + n;
- */
-uint8_t *ngtcp2_setmem(uint8_t *dest, uint8_t b, size_t n);
-/*
- * ngtcp2_encode_hex encodes |data| of length |len| in hex string. It
- * writes additional NULL bytes at the end of the buffer. The buffer
- * pointed by |dest| must have at least |len| * 2 + 1 bytes space.
- * This function returns |dest|.
- */
-uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len);
-
-/*
- * ngtcp2_encode_printable_ascii encodes |data| of length |len| in
- * |dest| in the following manner: printable ascii characters are
- * copied as is. The other characters are converted to ".". It
- * writes additional NULL bytes at the end of the buffer. |dest| must
- * have at least |len| + 1 bytes. This function returns |dest|.
- */
-char *ngtcp2_encode_printable_ascii(char *dest, const uint8_t *data,
- size_t len);
-
-/*
- * ngtcp2_verify_stateless_reset_token verifies stateless reset token
- * |want| and |got|. This function returns 0 if |want| equals |got|
- * and |got| is not all zero, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_INVALID_ARGUMENT
- * Token does not match; or token is all zero.
- */
-int ngtcp2_verify_stateless_reset_token(const uint8_t *want,
- const uint8_t *got);
-
-/*
- * ngtcp2_check_invalid_stateless_reset_token returns nonzero if
- * |token| is invalid stateless reset token. Currently, token which
- * consists of all zeros is considered invalid.
- */
-int ngtcp2_check_invalid_stateless_reset_token(const uint8_t *token);
-
-/*
- * ngtcp2_cmemeq returns nonzero if the first |n| bytes of the buffers
- * pointed by |a| and |b| are equal. The comparison is done in a
- * constant time manner.
- */
-int ngtcp2_cmemeq(const uint8_t *a, const uint8_t *b, size_t n);
-
-#endif /* NGTCP2_STR_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/lib/ngtcp2_strm.c
deleted file mode 100644
index 6fb73dc072..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_strm.c
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_strm.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_rtb.h"
-#include "ngtcp2_pkt.h"
-#include "ngtcp2_vec.h"
-
-static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
- return *(int64_t *)lhs < *(int64_t *)rhs;
-}
-
-int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
- uint64_t max_rx_offset, uint64_t max_tx_offset,
- void *stream_user_data, const ngtcp2_mem *mem) {
- strm->cycle = 0;
- strm->tx.acked_offset = NULL;
- strm->tx.cont_acked_offset = 0;
- strm->tx.streamfrq = NULL;
- strm->tx.offset = 0;
- strm->tx.max_offset = max_tx_offset;
- strm->rx.rob = NULL;
- strm->rx.cont_offset = 0;
- strm->rx.last_offset = 0;
- strm->stream_id = stream_id;
- strm->flags = flags;
- strm->stream_user_data = stream_user_data;
- strm->rx.max_offset = strm->rx.unsent_max_offset = max_rx_offset;
- strm->me.key = (uint64_t)stream_id;
- strm->me.next = NULL;
- strm->pe.index = NGTCP2_PQ_BAD_INDEX;
- strm->mem = mem;
- strm->app_error_code = 0;
-
- return 0;
-}
-
-void ngtcp2_strm_free(ngtcp2_strm *strm) {
- ngtcp2_ksl_it it;
-
- if (strm == NULL) {
- return;
- }
-
- if (strm->tx.streamfrq) {
- for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- ngtcp2_frame_chain_del(ngtcp2_ksl_it_get(&it), strm->mem);
- }
-
- ngtcp2_ksl_free(strm->tx.streamfrq);
- ngtcp2_mem_free(strm->mem, strm->tx.streamfrq);
- }
-
- ngtcp2_rob_free(strm->rx.rob);
- ngtcp2_mem_free(strm->mem, strm->rx.rob);
- ngtcp2_gaptr_free(strm->tx.acked_offset);
- ngtcp2_mem_free(strm->mem, strm->tx.acked_offset);
-}
-
-static int strm_rob_init(ngtcp2_strm *strm) {
- int rv;
- ngtcp2_rob *rob = ngtcp2_mem_malloc(strm->mem, sizeof(*rob));
-
- if (rob == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_rob_init(rob, 8 * 1024, strm->mem);
- if (rv != 0) {
- ngtcp2_mem_free(strm->mem, rob);
- return rv;
- }
-
- strm->rx.rob = rob;
-
- return 0;
-}
-
-uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) {
- if (strm->rx.rob == NULL) {
- return strm->rx.cont_offset;
- }
- return ngtcp2_rob_first_gap_offset(strm->rx.rob);
-}
-
-int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
- size_t datalen, uint64_t offset) {
- int rv;
-
- if (strm->rx.rob == NULL) {
- rv = strm_rob_init(strm);
- if (rv != 0) {
- return rv;
- }
-
- if (strm->rx.cont_offset) {
- rv = ngtcp2_rob_remove_prefix(strm->rx.rob, strm->rx.cont_offset);
- if (rv != 0) {
- return rv;
- }
- }
- }
-
- return ngtcp2_rob_push(strm->rx.rob, offset, data, datalen);
-}
-
-int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) {
- if (strm->rx.rob == NULL) {
- strm->rx.cont_offset = offset;
- return 0;
- }
-
- return ngtcp2_rob_remove_prefix(strm->rx.rob, offset);
-}
-
-void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) {
- strm->flags |= flags & NGTCP2_STRM_FLAG_SHUT_RDWR;
-}
-
-static int strm_streamfrq_init(ngtcp2_strm *strm) {
- int rv;
- ngtcp2_ksl *streamfrq = ngtcp2_mem_malloc(strm->mem, sizeof(*streamfrq));
- if (streamfrq == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_ksl_init(streamfrq, offset_less, sizeof(uint64_t), strm->mem);
- if (rv != 0) {
- ngtcp2_mem_free(strm->mem, streamfrq);
- return rv;
- }
-
- strm->tx.streamfrq = streamfrq;
-
- return 0;
-}
-
-int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) {
- int rv;
-
- assert(frc->fr.type == NGTCP2_FRAME_STREAM);
- assert(frc->next == NULL);
-
- if (strm->tx.streamfrq == NULL) {
- rv = strm_streamfrq_init(strm);
- if (rv != 0) {
- return rv;
- }
- }
-
- return ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &frc->fr.stream.offset,
- frc);
-}
-
-static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm,
- ngtcp2_frame_chain **pfrc) {
- ngtcp2_frame_chain *frc, *nfrc;
- ngtcp2_stream *fr, *nfr;
- uint64_t offset, end_offset;
- size_t idx, end_idx;
- uint64_t base_offset, end_base_offset;
- ngtcp2_range gap;
- ngtcp2_vec *v;
- int rv;
- ngtcp2_ksl_it it;
-
- *pfrc = NULL;
-
- assert(strm->tx.streamfrq);
- assert(ngtcp2_ksl_len(strm->tx.streamfrq));
-
- for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);) {
- frc = ngtcp2_ksl_it_get(&it);
- fr = &frc->fr.stream;
-
- ngtcp2_ksl_remove(strm->tx.streamfrq, &it, &fr->offset);
-
- idx = 0;
- offset = fr->offset;
- base_offset = 0;
-
- gap = ngtcp2_strm_get_unacked_range_after(strm, offset);
- if (gap.begin < offset) {
- gap.begin = offset;
- }
-
- for (; idx < fr->datacnt && offset < gap.begin; ++idx) {
- v = &fr->data[idx];
- if (offset + v->len > gap.begin) {
- base_offset = gap.begin - offset;
- break;
- }
-
- offset += v->len;
- }
-
- if (idx == fr->datacnt) {
- if (fr->fin) {
- if (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) {
- ngtcp2_frame_chain_del(frc, strm->mem);
- assert(ngtcp2_ksl_len(strm->tx.streamfrq) == 0);
- return 0;
- }
-
- fr->offset = fr->offset + ngtcp2_vec_len(fr->data, fr->datacnt);
- fr->datacnt = 0;
-
- *pfrc = frc;
-
- return 0;
- }
- ngtcp2_frame_chain_del(frc, strm->mem);
- continue;
- }
-
- assert(gap.begin == offset + base_offset);
-
- end_idx = idx;
- end_offset = offset;
- end_base_offset = 0;
-
- for (; end_idx < fr->datacnt; ++end_idx) {
- v = &fr->data[end_idx];
- if (end_offset + v->len > gap.end) {
- end_base_offset = gap.end - end_offset;
- break;
- }
-
- end_offset += v->len;
- }
-
- if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) {
- *pfrc = frc;
- return 0;
- }
-
- if (fr->datacnt == end_idx) {
- memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
-
- assert(fr->data[0].len > base_offset);
-
- fr->offset = offset + base_offset;
- fr->datacnt = end_idx - idx;
- fr->data[0].base += base_offset;
- fr->data[0].len -= (size_t)base_offset;
-
- *pfrc = frc;
- return 0;
- }
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, fr->datacnt - end_idx,
- strm->mem);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.stream;
- memcpy(nfr->data, fr->data + end_idx,
- sizeof(nfr->data[0]) * (fr->datacnt - end_idx));
-
- assert(nfr->data[0].len > end_base_offset);
-
- nfr->type = NGTCP2_FRAME_STREAM;
- nfr->flags = 0;
- nfr->fin = fr->fin;
- nfr->stream_id = fr->stream_id;
- nfr->offset = end_offset + end_base_offset;
- nfr->datacnt = fr->datacnt - end_idx;
- nfr->data[0].base += end_base_offset;
- nfr->data[0].len -= (size_t)end_base_offset;
-
- rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- if (end_base_offset) {
- ++end_idx;
- }
-
- memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
-
- assert(fr->data[0].len > base_offset);
-
- fr->fin = 0;
- fr->offset = offset + base_offset;
- fr->datacnt = end_idx - idx;
- if (end_base_offset) {
- assert(fr->data[fr->datacnt - 1].len > end_base_offset);
- fr->data[fr->datacnt - 1].len = (size_t)end_base_offset;
- }
- fr->data[0].base += base_offset;
- fr->data[0].len -= (size_t)base_offset;
-
- *pfrc = frc;
- return 0;
- }
-
- return 0;
-}
-
-int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
- size_t left) {
- ngtcp2_stream *fr, *nfr;
- ngtcp2_frame_chain *frc, *nfrc;
- int rv;
- size_t nmerged;
- size_t datalen;
- ngtcp2_vec a[NGTCP2_MAX_STREAM_DATACNT];
- ngtcp2_vec b[NGTCP2_MAX_STREAM_DATACNT];
- size_t acnt, bcnt;
- uint64_t unacked_offset;
-
- if (strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0) {
- *pfrc = NULL;
- return 0;
- }
-
- rv = strm_streamfrq_unacked_pop(strm, &frc);
- if (rv != 0) {
- return rv;
- }
- if (frc == NULL) {
- *pfrc = NULL;
- return 0;
- }
-
- fr = &frc->fr.stream;
- datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
-
- if (left == 0) {
- /* datalen could be zero if 0 length STREAM has been sent */
- if (datalen || ngtcp2_ksl_len(strm->tx.streamfrq) > 1) {
- rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &fr->offset, frc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
- *pfrc = NULL;
- return 0;
- }
- }
-
- if (datalen > left) {
- ngtcp2_vec_copy(a, fr->data, fr->datacnt);
- acnt = fr->datacnt;
-
- bcnt = 0;
- ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_STREAM_DATACNT);
-
- assert(acnt > 0);
- assert(bcnt > 0);
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, bcnt, strm->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.stream;
- nfr->type = NGTCP2_FRAME_STREAM;
- nfr->flags = 0;
- nfr->fin = fr->fin;
- nfr->stream_id = fr->stream_id;
- nfr->offset = fr->offset + left;
- nfr->datacnt = bcnt;
- ngtcp2_vec_copy(nfr->data, b, bcnt);
-
- rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, acnt, strm->mem);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.stream;
- *nfr = *fr;
- nfr->fin = 0;
- nfr->datacnt = acnt;
- ngtcp2_vec_copy(nfr->data, a, acnt);
-
- ngtcp2_frame_chain_del(frc, strm->mem);
-
- *pfrc = nfrc;
-
- return 0;
- }
-
- left -= datalen;
-
- ngtcp2_vec_copy(a, fr->data, fr->datacnt);
- acnt = fr->datacnt;
-
- for (; left && ngtcp2_ksl_len(strm->tx.streamfrq);) {
- unacked_offset = ngtcp2_strm_streamfrq_unacked_offset(strm);
- if (unacked_offset != fr->offset + datalen) {
- assert(fr->offset + datalen < unacked_offset);
- break;
- }
-
- rv = strm_streamfrq_unacked_pop(strm, &nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
- if (nfrc == NULL) {
- break;
- }
-
- nfr = &nfrc->fr.stream;
-
- if (nfr->fin && nfr->datacnt == 0) {
- fr->fin = 1;
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- break;
- }
-
- nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
- NGTCP2_MAX_STREAM_DATACNT);
- if (nmerged == 0) {
- rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- assert(ngtcp2_err_is_fatal(rv));
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
- break;
- }
-
- datalen += nmerged;
- left -= nmerged;
-
- if (nfr->datacnt == 0) {
- fr->fin = nfr->fin;
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- continue;
- }
-
- nfr->offset += nmerged;
-
- rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
- if (rv != 0) {
- ngtcp2_frame_chain_del(nfrc, strm->mem);
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- break;
- }
-
- if (acnt == fr->datacnt) {
- if (acnt > 0) {
- fr->data[acnt - 1] = a[acnt - 1];
- }
-
- *pfrc = frc;
- return 0;
- }
-
- assert(acnt > fr->datacnt);
-
- rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, acnt, strm->mem);
- if (rv != 0) {
- ngtcp2_frame_chain_del(frc, strm->mem);
- return rv;
- }
-
- nfr = &nfrc->fr.stream;
- *nfr = *fr;
- nfr->datacnt = acnt;
- ngtcp2_vec_copy(nfr->data, a, acnt);
-
- ngtcp2_frame_chain_del(frc, strm->mem);
-
- *pfrc = nfrc;
-
- return 0;
-}
-
-uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) {
- ngtcp2_frame_chain *frc;
- ngtcp2_stream *fr;
- ngtcp2_range gap;
- ngtcp2_ksl_it it;
- size_t datalen;
-
- assert(strm->tx.streamfrq);
- assert(ngtcp2_ksl_len(strm->tx.streamfrq));
-
- for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- frc = ngtcp2_ksl_it_get(&it);
- fr = &frc->fr.stream;
-
- gap = ngtcp2_strm_get_unacked_range_after(strm, fr->offset);
-
- datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
-
- if (gap.begin <= fr->offset) {
- return fr->offset;
- }
- if (gap.begin < fr->offset + datalen) {
- return gap.begin;
- }
- if (fr->offset + datalen == gap.begin && fr->fin &&
- !(strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED)) {
- return fr->offset + datalen;
- }
- }
-
- return (uint64_t)-1;
-}
-
-ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm) {
- ngtcp2_ksl_it it;
-
- assert(strm->tx.streamfrq);
- assert(ngtcp2_ksl_len(strm->tx.streamfrq));
-
- it = ngtcp2_ksl_begin(strm->tx.streamfrq);
- return ngtcp2_ksl_it_get(&it);
-}
-
-int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm) {
- return strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0;
-}
-
-void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm) {
- ngtcp2_frame_chain *frc;
- ngtcp2_ksl_it it;
-
- if (strm->tx.streamfrq == NULL) {
- return;
- }
-
- for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
- ngtcp2_ksl_it_next(&it)) {
- frc = ngtcp2_ksl_it_get(&it);
- ngtcp2_frame_chain_del(frc, strm->mem);
- }
- ngtcp2_ksl_clear(strm->tx.streamfrq);
-}
-
-int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) {
- return strm->pe.index != NGTCP2_PQ_BAD_INDEX;
-}
-
-int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) {
- if (strm->tx.acked_offset == NULL) {
- return strm->tx.cont_acked_offset == strm->tx.offset;
- }
-
- return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset) ==
- strm->tx.offset;
-}
-
-ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
- uint64_t offset) {
- ngtcp2_ksl_it gapit;
- ngtcp2_range gap;
-
- if (strm->tx.acked_offset == NULL) {
- gap.begin = strm->tx.cont_acked_offset;
- gap.end = UINT64_MAX;
- return gap;
- }
-
- gapit = ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset);
- return *(ngtcp2_range *)ngtcp2_ksl_it_key(&gapit);
-}
-
-uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm) {
- if (strm->tx.acked_offset == NULL) {
- return strm->tx.cont_acked_offset;
- }
-
- return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset);
-}
-
-static int strm_acked_offset_init(ngtcp2_strm *strm) {
- int rv;
- ngtcp2_gaptr *acked_offset =
- ngtcp2_mem_malloc(strm->mem, sizeof(*acked_offset));
-
- if (acked_offset == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- rv = ngtcp2_gaptr_init(acked_offset, strm->mem);
- if (rv != 0) {
- ngtcp2_mem_free(strm->mem, acked_offset);
- return rv;
- }
-
- strm->tx.acked_offset = acked_offset;
-
- return 0;
-}
-
-int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) {
- int rv;
-
- if (strm->tx.acked_offset == NULL) {
- if (strm->tx.cont_acked_offset == offset) {
- strm->tx.cont_acked_offset += len;
- return 0;
- }
-
- rv = strm_acked_offset_init(strm);
- if (rv != 0) {
- return rv;
- }
-
- rv =
- ngtcp2_gaptr_push(strm->tx.acked_offset, 0, strm->tx.cont_acked_offset);
- if (rv != 0) {
- return rv;
- }
- }
-
- return ngtcp2_gaptr_push(strm->tx.acked_offset, offset, len);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_strm.h b/deps/ngtcp2/lib/ngtcp2_strm.h
deleted file mode 100644
index 7da8437e66..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_strm.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2017 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_STRM_H
-#define NGTCP2_STRM_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_rob.h"
-#include "ngtcp2_map.h"
-#include "ngtcp2_gaptr.h"
-#include "ngtcp2_ksl.h"
-#include "ngtcp2_pq.h"
-
-struct ngtcp2_frame_chain;
-typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
-
-typedef enum {
- NGTCP2_STRM_FLAG_NONE = 0,
- /* NGTCP2_STRM_FLAG_SHUT_RD indicates that further reception of
- stream data is not allowed. */
- NGTCP2_STRM_FLAG_SHUT_RD = 0x01,
- /* NGTCP2_STRM_FLAG_SHUT_WR indicates that further transmission of
- stream data is not allowed. */
- NGTCP2_STRM_FLAG_SHUT_WR = 0x02,
- NGTCP2_STRM_FLAG_SHUT_RDWR =
- NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_SHUT_WR,
- /* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is sent from
- the local endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_WR is
- also set. */
- NGTCP2_STRM_FLAG_SENT_RST = 0x04,
- /* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is received
- from the remote endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_RD
- is also set. */
- NGTCP2_STRM_FLAG_RECV_RST = 0x08,
- /* NGTCP2_STRM_FLAG_STOP_SENDING indicates that STOP_SENDING is sent
- from the local endpoint. */
- NGTCP2_STRM_FLAG_STOP_SENDING = 0x10,
- /* NGTCP2_STRM_FLAG_RST_ACKED indicates that the outgoing RST_STREAM
- is acknowledged by peer. */
- NGTCP2_STRM_FLAG_RST_ACKED = 0x20,
- /* NGTCP2_STRM_FLAG_FIN_ACKED indicates that a STREAM with FIN bit
- set is acknowledged by a remote endpoint. */
- NGTCP2_STRM_FLAG_FIN_ACKED = 0x40,
-} ngtcp2_strm_flags;
-
-struct ngtcp2_strm;
-typedef struct ngtcp2_strm ngtcp2_strm;
-
-struct ngtcp2_strm {
- ngtcp2_map_entry me;
- ngtcp2_pq_entry pe;
- uint64_t cycle;
-
- struct {
- /* acked_offset tracks acknowledged outgoing data. */
- ngtcp2_gaptr *acked_offset;
- /* cont_acked_offset is the offset that all data up to this offset
- is acknowledged by a remote endpoint. It is used until the
- remote endpoint acknowledges data in out-of-order. After that,
- acked_offset is used instead. */
- uint64_t cont_acked_offset;
- /* streamfrq contains STREAM frame for retransmission. The flow
- control credits have been paid when they are transmitted first
- time. There are no restriction regarding flow control for
- retransmission. */
- ngtcp2_ksl *streamfrq;
- /* offset is the next offset of outgoing data. In other words, it
- is the number of bytes sent in this stream without
- duplication. */
- uint64_t offset;
- /* max_tx_offset is the maximum offset that local endpoint can
- send for this stream. */
- uint64_t max_offset;
- } tx;
-
- struct {
- /* rob is the reorder buffer for incoming stream data. The data
- received in out of order is buffered and sorted by its offset
- in this object. */
- ngtcp2_rob *rob;
- /* cont_offset is the largest offset of consecutive data. It is
- used until the endpoint receives out-of-order data. After
- that, rob is used to track the offset and data. */
- uint64_t cont_offset;
- /* last_offset is the largest offset of stream data received for
- this stream. */
- uint64_t last_offset;
- /* max_offset is the maximum offset that remote endpoint can send
- to this stream. */
- uint64_t max_offset;
- /* unsent_max_offset is the maximum offset that remote endpoint
- can send to this stream, and it is not notified to the remote
- endpoint. unsent_max_offset >= max_offset must be hold. */
- uint64_t unsent_max_offset;
- } rx;
-
- const ngtcp2_mem *mem;
- int64_t stream_id;
- void *stream_user_data;
- /* flags is bit-wise OR of zero or more of ngtcp2_strm_flags. */
- uint32_t flags;
- /* app_error_code is an error code the local endpoint sent in
- RST_STREAM or STOP_SENDING. */
- uint64_t app_error_code;
-};
-
-/*
- * ngtcp2_strm_init initializes |strm|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
- uint64_t max_rx_offset, uint64_t max_tx_offset,
- void *stream_user_data, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_strm_free deallocates memory allocated for |strm|. This
- * function does not free the memory pointed by |strm| itself.
- */
-void ngtcp2_strm_free(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_rx_offset returns the minimum offset of stream data
- * which is not received yet.
- */
-uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_recv_reordering handles reordered data.
- *
- * It returns 0 if it succeeds, or one of the following negative error
- * codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
- size_t datalen, uint64_t offset);
-
-/*
- * ngtcp2_strm_update_rx_offset tells that data up to offset bytes are
- * received in order.
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset);
-
-/*
- * ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be
- * NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR.
- */
-void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags);
-
-/*
- * ngtcp2_strm_streamfrq_push pushes |frc| to streamfrq for
- * retransmission.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc);
-
-/*
- * ngtcp2_strm_streamfrq_pop pops the first ngtcp2_frame_chain and
- * assigns it to |*pfrc|. This function splits into or merges several
- * ngtcp2_frame_chain objects so that the returned ngtcp2_frame_chain
- * has at most |left| data length. If there is no frames to send,
- * this function returns 0 and |*pfrc| is NULL.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGTCP2_ERR_NOMEM
- * Out of memory
- */
-int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
- size_t left);
-
-/*
- * ngtcp2_strm_streamfrq_unacked_offset returns the smallest offset of
- * unacknowledged stream data held in strm->tx.streamfrq.
- */
-uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_streamfrq_top returns the first ngtcp2_frame_chain.
- * The queue must not be empty.
- */
-ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_streamfrq_empty returns nonzero if streamfrq is empty.
- */
-int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_streamfrq_clear removes all frames from streamfrq.
- */
-void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_is_tx_queued returns nonzero if |strm| is queued.
- */
-int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_is_all_tx_data_acked returns nonzero if all outgoing
- * data for |strm| which have sent so far have been acknowledged.
- */
-int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_get_unacked_range_after returns the range that is not
- * acknowledged yet and intersects or comes after |offset|.
- */
-ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
- uint64_t offset);
-
-/*
- * ngtcp2_strm_get_acked_offset returns offset, that is the data up to
- * this offset have been acknowledged by a remote endpoint. It
- * returns 0 if no data is acknowledged.
- */
-uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm);
-
-/*
- * ngtcp2_strm_ack_data tells |strm| that the data [offset,
- * offset+len) is acknowledged by a remote endpoint.
- */
-int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len);
-
-#endif /* NGTCP2_STRM_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_vec.c b/deps/ngtcp2/lib/ngtcp2_vec.c
deleted file mode 100644
index 7a6f8afa05..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_vec.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "ngtcp2_vec.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "ngtcp2_str.h"
-
-ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) {
- vec->base = (uint8_t *)base;
- vec->len = len;
- return vec;
-}
-
-int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen,
- const ngtcp2_mem *mem) {
- size_t len;
- uint8_t *p;
-
- len = sizeof(ngtcp2_vec) + datalen;
-
- *pvec = ngtcp2_mem_malloc(mem, len);
- if (*pvec == NULL) {
- return NGTCP2_ERR_NOMEM;
- }
-
- p = (uint8_t *)(*pvec) + sizeof(ngtcp2_vec);
- (*pvec)->base = p;
- (*pvec)->len = datalen;
- if (datalen) {
- /* p = */ ngtcp2_cpymem(p, data, datalen);
- }
-
- return 0;
-}
-
-void ngtcp2_vec_del(ngtcp2_vec *vec, const ngtcp2_mem *mem) {
- ngtcp2_mem_free(mem, vec);
-}
-
-size_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n) {
- size_t i;
- size_t res = 0;
-
- for (i = 0; i < n; ++i) {
- res += vec[i].len;
- }
-
- return res;
-}
-
-ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst,
- size_t *pdstcnt, size_t left, size_t maxcnt) {
- size_t i;
- size_t srccnt = *psrccnt;
- size_t nmove;
- size_t extra = 0;
-
- for (i = 0; i < srccnt; ++i) {
- if (left >= src[i].len) {
- left -= src[i].len;
- continue;
- }
-
- if (*pdstcnt && src[srccnt - 1].base + src[srccnt - 1].len == dst[0].base) {
- if (*pdstcnt + srccnt - i - 1 > maxcnt) {
- return -1;
- }
-
- dst[0].len += src[srccnt - 1].len;
- dst[0].base = src[srccnt - 1].base;
- extra = src[srccnt - 1].len;
- --srccnt;
- } else if (*pdstcnt + srccnt - i > maxcnt) {
- return -1;
- }
-
- if (left == 0) {
- *psrccnt = i;
- } else {
- *psrccnt = i + 1;
- }
-
- nmove = srccnt - i;
- if (nmove) {
- memmove(dst + nmove, dst, sizeof(ngtcp2_vec) * (*pdstcnt));
- *pdstcnt += nmove;
- memcpy(dst, src + i, sizeof(ngtcp2_vec) * nmove);
- }
-
- dst[0].len -= left;
- dst[0].base += left;
- src[i].len = left;
-
- if (nmove == 0) {
- extra -= left;
- }
-
- return (ngtcp2_ssize)(ngtcp2_vec_len(dst, nmove) + extra);
- }
-
- return 0;
-}
-
-size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src,
- size_t *psrccnt, size_t left, size_t maxcnt) {
- size_t orig_left = left;
- size_t i;
- ngtcp2_vec *a, *b;
-
- assert(maxcnt);
-
- if (*pdstcnt == 0) {
- if (*psrccnt == 0) {
- return 0;
- }
-
- a = &dst[0];
- b = &src[0];
-
- if (left >= b->len) {
- *a = *b;
- ++*pdstcnt;
- left -= b->len;
- i = 1;
- } else {
- a->len = left;
- a->base = b->base;
-
- b->len -= left;
- b->base += left;
-
- return left;
- }
- } else {
- i = 0;
- }
-
- for (; left && i < *psrccnt; ++i) {
- a = &dst[*pdstcnt - 1];
- b = &src[i];
-
- if (left >= b->len) {
- if (a->base + a->len == b->base) {
- a->len += b->len;
- } else if (*pdstcnt == maxcnt) {
- break;
- } else {
- dst[(*pdstcnt)++] = *b;
- }
- left -= b->len;
- continue;
- }
-
- if (a->base + a->len == b->base) {
- a->len += left;
- } else if (*pdstcnt == maxcnt) {
- break;
- } else {
- dst[*pdstcnt].len = left;
- dst[*pdstcnt].base = b->base;
- ++*pdstcnt;
- }
-
- b->len -= left;
- b->base += left;
- left = 0;
-
- break;
- }
-
- memmove(src, src + i, sizeof(ngtcp2_vec) * (*psrccnt - i));
- *psrccnt -= i;
-
- return orig_left - left;
-}
-
-size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t *pnwritten,
- size_t dstcnt, const ngtcp2_vec *src,
- size_t srccnt, size_t left) {
- size_t i, j;
- size_t len = left;
-
- *pnwritten = 0;
-
- for (i = 0, j = 0; left > 0 && i < srccnt && j < dstcnt;) {
- if (src[i].len == 0) {
- ++i;
- continue;
- }
- dst[j] = src[i];
- if (dst[j].len > left) {
- dst[j].len = left;
- *pnwritten = len;
- return j + 1;
- }
- left -= dst[j].len;
- ++i;
- ++j;
- }
-
- *pnwritten = len - left;
-
- return j;
-}
-
-void ngtcp2_vec_copy(ngtcp2_vec *dst, const ngtcp2_vec *src, size_t cnt) {
- memcpy(dst, src, sizeof(ngtcp2_vec) * cnt);
-}
diff --git a/deps/ngtcp2/lib/ngtcp2_vec.h b/deps/ngtcp2/lib/ngtcp2_vec.h
deleted file mode 100644
index 077820a9ef..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_vec.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2018 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NGTCP2_VEC_H
-#define NGTCP2_VEC_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-#include "ngtcp2_mem.h"
-
-/*
- * ngtcp2_vec_lit is a convenient macro to fill the object pointed by
- * |DEST| with the literal string |LIT|.
- */
-#define ngtcp2_vec_lit(DEST, LIT) \
- ((DEST)->base = (uint8_t *)(LIT), (DEST)->len = sizeof(LIT) - 1, (DEST))
-
-/*
- * ngtcp2_vec_init initializes |vec| with the given parameters. It
- * returns |vec|.
- */
-ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len);
-
-/*
- * ngtcp2_vec_new allocates and initializes |*pvec| with given |data|
- * of length |datalen|. This function allocates memory for |*pvec|
- * and the given data with a single allocation, and the contents
- * pointed by |data| is copied into the allocated memory space. To
- * free the allocated memory, call ngtcp2_vec_del.
- */
-int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen,
- const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_vec_del frees the memory allocated by |vec| which is
- * allocated and initialized by ngtcp2_vec_new.
- */
-void ngtcp2_vec_del(ngtcp2_vec *vec, const ngtcp2_mem *mem);
-
-/*
- * ngtcp2_vec_len returns the sum of length in |vec| of |n| elements.
- */
-size_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n);
-
-/*
- * ngtcp2_vec_split splits |src| to |dst| so that the sum of the
- * length in |src| does not exceed |left| bytes. The |maxcnt| is the
- * maximum number of elements which |dst| array can contain. The
- * caller must set |*psrccnt| to the number of elements of |src|.
- * Similarly, the caller must set |*pdstcnt| to the number of elements
- * of |dst|. The split does not necessarily occur at the boundary of
- * ngtcp2_vec object. After split has done, this function updates
- * |*psrccnt| and |*pdstcnt|. This function returns the number of
- * bytes moved from |src| to |dst|. If split cannot be made because
- * doing so exceeds |maxcnt|, this function returns -1.
- */
-ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst,
- size_t *pdstcnt, size_t left, size_t maxcnt);
-
-/*
- * ngtcp2_vec_merge merges |src| into |dst| by moving at most |left|
- * bytes from |src|. The |maxcnt| is the maximum number of elements
- * which |dst| array can contain. The caller must set |*pdstcnt| to
- * the number of elements of |dst|. Similarly, the caller must set
- * |*psrccnt| to the number of elements of |src|. After merge has
- * done, this function updates |*psrccnt| and |*pdstcnt|. This
- * function returns the number of bytes moved from |src| to |dst|.
- */
-size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src,
- size_t *psrccnt, size_t left, size_t maxcnt);
-
-/*
- * ngtcp2_vec_copy_at_most copies |src| of length |srccnt| to |dst| of
- * length |dstcnt|. The total number of bytes which the copied
- * ngtcp2_vec refers to is at most |left| and is assigned to
- * |*pnwritten|. The empty elements in |src| are ignored. This
- * function returns the number of elements copied.
- */
-size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t *pnwritten,
- size_t dstcnt, const ngtcp2_vec *src,
- size_t srccnt, size_t left);
-
-/*
- * ngtcp2_vec_copy copies |src| of length |cnt| to |dst|. |dst| must
- * have sufficient capacity.
- */
-void ngtcp2_vec_copy(ngtcp2_vec *dst, const ngtcp2_vec *src, size_t cnt);
-
-#endif /* NGTCP2_VEC_H */
diff --git a/deps/ngtcp2/lib/ngtcp2_version.c b/deps/ngtcp2/lib/ngtcp2_version.c
deleted file mode 100644
index 40f3ae3f9e..0000000000
--- a/deps/ngtcp2/lib/ngtcp2_version.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * ngtcp2
- *
- * Copyright (c) 2019 ngtcp2 contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ngtcp2/ngtcp2.h>
-
-static ngtcp2_info version = {NGTCP2_VERSION_AGE, NGTCP2_VERSION_NUM,
- NGTCP2_VERSION};
-
-ngtcp2_info *ngtcp2_version(int least_version) {
- if (least_version > NGTCP2_VERSION_NUM) {
- return NULL;
- }
- return &version;
-}
diff --git a/deps/ngtcp2/ngtcp2.gyp b/deps/ngtcp2/ngtcp2.gyp
deleted file mode 100644
index fbdd556895..0000000000
--- a/deps/ngtcp2/ngtcp2.gyp
+++ /dev/null
@@ -1,118 +0,0 @@
-{
- 'target_defaults': {
- 'defines': [
- '_U_='
- ]
- },
- 'targets': [
- {
- 'target_name': 'ngtcp2',
- 'type': 'static_library',
- 'include_dirs': [
- 'lib/includes',
- 'lib',
- 'crypto/includes',
- 'crypto'
- ],
- 'defines': [
- 'BUILDING_NGTCP2',
- 'NGTCP2_STATICLIB',
- ],
- 'dependencies': [
- '../openssl/openssl.gyp:openssl'
- ],
- 'conditions': [
- ['OS=="win"', {
- 'defines': [
- 'WIN32',
- '_WINDOWS',
- 'HAVE_CONFIG_H',
- ],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'CompileAs': '1'
- },
- },
- }],
- ['OS=="linux"', {
- 'defines': [
- 'HAVE_ARPA_INET_H',
- 'HAVE_NETINET_IN_H',
- ],
- }],
- ],
- 'direct_dependent_settings': {
- 'defines': [ 'NGTCP2_STATICLIB' ],
- 'include_dirs': [
- 'lib/includes',
- 'crypto/includes',
- ]
- },
- 'sources': [
- 'lib/ngtcp2_acktr.c',
- 'lib/ngtcp2_acktr.h',
- 'lib/ngtcp2_addr.c',
- 'lib/ngtcp2_addr.h',
- 'lib/ngtcp2_buf.c',
- 'lib/ngtcp2_buf.h',
- 'lib/ngtcp2_cc.c',
- 'lib/ngtcp2_cc.h',
- 'lib/ngtcp2_cid.c',
- 'lib/ngtcp2_cid.h',
- 'lib/ngtcp2_conn.c',
- 'lib/ngtcp2_conn.h',
- 'lib/ngtcp2_conv.c',
- 'lib/ngtcp2_conv.h',
- 'lib/ngtcp2_crypto.c',
- 'lib/ngtcp2_crypto.h',
- 'lib/ngtcp2_err.c',
- 'lib/ngtcp2_err.h',
- 'lib/ngtcp2_gaptr.c',
- 'lib/ngtcp2_gaptr.h',
- 'lib/ngtcp2_idtr.c',
- 'lib/ngtcp2_idtr.h',
- 'lib/ngtcp2_ksl.c',
- 'lib/ngtcp2_ksl.h',
- 'lib/ngtcp2_log.c',
- 'lib/ngtcp2_log.h',
- 'lib/ngtcp2_macro.h',
- 'lib/ngtcp2_map.c',
- 'lib/ngtcp2_map.h',
- 'lib/ngtcp2_mem.c',
- 'lib/ngtcp2_mem.h',
- 'lib/ngtcp2_path.c',
- 'lib/ngtcp2_path.h',
- 'lib/ngtcp2_pkt.c',
- 'lib/ngtcp2_pkt.h',
- 'lib/ngtcp2_ppe.c',
- 'lib/ngtcp2_ppe.h',
- 'lib/ngtcp2_pq.c',
- 'lib/ngtcp2_pq.h',
- 'lib/ngtcp2_pv.c',
- 'lib/ngtcp2_pv.h',
- 'lib/ngtcp2_qlog.c',
- 'lib/ngtcp2_qlog.h',
- 'lib/ngtcp2_range.c',
- 'lib/ngtcp2_range.h',
- 'lib/ngtcp2_ringbuf.c',
- 'lib/ngtcp2_ringbuf.h',
- 'lib/ngtcp2_rob.c',
- 'lib/ngtcp2_rob.h',
- 'lib/ngtcp2_rtb.c',
- 'lib/ngtcp2_rtb.h',
- 'lib/ngtcp2_rst.c',
- 'lib/ngtcp2_rst.h',
- 'lib/ngtcp2_str.c',
- 'lib/ngtcp2_str.h',
- 'lib/ngtcp2_strm.c',
- 'lib/ngtcp2_strm.h',
- 'lib/ngtcp2_vec.c',
- 'lib/ngtcp2_vec.h',
- 'lib/ngtcp2_version.c',
- 'crypto/shared.c',
- 'crypto/shared.h',
- 'crypto/openssl/openssl.c'
- ]
- }
- ]
-}
diff --git a/deps/openssl/openssl.gyp b/deps/openssl/openssl.gyp
index 3dfe0b8c8a..4609d83baa 100644
--- a/deps/openssl/openssl.gyp
+++ b/deps/openssl/openssl.gyp
@@ -16,13 +16,6 @@
'OPENSSL_NO_HW',
],
'conditions': [
- [
- # Disable building QUIC support in openssl if experimental_quic
- # is not enabled.
- 'experimental_quic!=1', {
- 'defines': ['OPENSSL_NO_QUIC=1'],
- }
- ],
[ 'openssl_no_asm==1', {
'includes': ['./openssl_no_asm.gypi'],
}, 'target_arch=="arm64" and OS=="win"', {
diff --git a/deps/openssl/patches/0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch b/deps/openssl/patches/0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch
deleted file mode 100644
index e526302fa1..0000000000
--- a/deps/openssl/patches/0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch
+++ /dev/null
@@ -1,2363 +0,0 @@
-From d82945ead1320ea893c237e1c0f37c4afd933eed Mon Sep 17 00:00:00 2001
-From: Todd Short <tshort@akamai.com>
-Date: Fri, 12 Apr 2019 11:13:25 -0400
-Subject: [PATCH 1/3] deps: add support for BoringSSL QUIC APIs
-
-Acquired from: https://github.com/akamai/openssl/tree/OpenSSL_1_1_1f-quic
-
-Squashed:
-
-*
-https://github.com/akamai/openssl/commit/2ef7c58b2cb432abd4e371322667228d7ce2637b
-*
-https://github.com/akamai/openssl/commit/3f8eda3128f52f4d14399a1a912d1fdfacd86a86
-*
-https://github.com/akamai/openssl/commit/b37f665884be2e17e8ff4ad919138626fb13f6c9
-*
-https://github.com/akamai/openssl/commit/6b235895a16da3c0dd36a24cf8dfbe249c6cda3c
-*
-https://github.com/akamai/openssl/commit/3a793e06a5031311ce7ce094455be87fa92b8240
-
----
-
-This is a cherry-pick of 2a4b03a306439307e0b822b17eda3bdabddfbb68
-on the master-quic-support2 branch (2019-10-07)
-Which was a rebase/squash of master-quic-support:
-
-* 5aa62ce Add support for more secrets - Todd Short/Todd Short (master-quic-support)
-* 58e0643 Tweeks to quic_change_cipher_state() - Todd Short/Todd Short
-* 8169702 Move QUIC code out of tls13_change_cipher_state() - Todd Short/Todd Short
-* a08cfe6 Correctly disable middlebox compat - Todd Short/Todd Short
-* 3a9eabf Add OPENSSL_NO_QUIC wrapper - Todd Short/Todd Short
-* f550eca Add client early traffic secret storage - Todd Short/Todd Short
-* 1b787ae Quick fix: s2c to c2s for early secret - Todd Short/Todd Short
-* f97e6a9 Don't process an incomplete message - Todd Short/Todd Short
-* 81f0ce2 Reset init state in SSL_process_quic_post_handshake() - Todd Short/Todd Short
-* 5d59cf9 Fix quic_transport constructors/parsers - Todd Short/Todd Short
-* 5e5f91c Fix INSTALL nit. - Todd Short/Todd Short
-* bd290ab Fix duplicate word in docs - Todd Short/Todd Short
-* 699590b fixup! Handle partial handshake messages - Todd Short/Todd Short
-* a472a8d Handle partial handshake messages - Todd Short/Todd Short
-* 363cf3d fixup! Use proper secrets for handshake - Todd Short/Todd Short
-* b03fee6 Use proper secrets for handshake - Todd Short/Todd Short
-* 2ab1aa0 Move QUIC transport params to encrypted extensions - Todd Short/Todd Short
-* 0d16af9 Make temp secret names less confusing - Todd Short/Todd Short
-* abb6f39 New method to get QUIC secret length - Todd Short/Todd Short
-* 05fdae9 Add support for BoringSSL QUIC APIs - Todd Short/Todd Short
-
-This adds a compatible API for BoringSSL's QUIC support, based
-on the current |draft-ietf-quic-tls|.
-
-Based on BoringSSL commit 3c034b2cf386b3131f75520705491871a2e0cafe
-Based on BoringSSL commit c8e0f90f83b9ec38ea833deb86b5a41360b62b6a
-Based on BoringSSL commit 3cbb0299a28a8bd0136257251a78b91a96c5eec8
-Based on BoringSSL commit cc9d935256539af2d3b7f831abf57c0d685ffd81
-Based on BoringSSL commit e6eef1ca16a022e476bbaedffef044597cfc8f4b
-Based on BoringSSL commit 6f733791148cf8a076bf0e95498235aadbe5926d
-Based on BoringSSL commit 384d0eaf1930af1ebc47eda751f0c78dfcba1c03
-Based on BoringSSL commit a0373182eb5cc7b81d49f434596b473c7801c942
-Based on BoringSSL commit b1b76aee3cb43ce11889403c5334283d951ebd37
-
-New method to get QUIC secret length
-
-Make temp secret names less confusing
-
-Move QUIC transport params to encrypted extensions
-
-Use proper secrets for handshake
-
-fixup! Use proper secrets for handshake
-
-Handle partial handshake messages
-
-fixup! Handle partial handshake messages
-
-Fix duplicate word in docs
-
-Fix INSTALL nit.
-
-Fix quic_transport constructors/parsers
-
-Reset init state in SSL_process_quic_post_handshake()
-
-Don't process an incomplete message
-
-Quick fix: s2c to c2s for early secret
-
-Add client early traffic secret storage
-
-Add OPENSSL_NO_QUIC wrapper
-
-Correctly disable middlebox compat
-
-Move QUIC code out of tls13_change_cipher_state()
-
-Create quic_change_cipher_state() that does the minimal required
-to generate the QUIC secrets. (e.g. encryption contexts are not
-initialized).
-
-Tweeks to quic_change_cipher_state()
-
-Add support for more secrets
-
-Fix resumption secret
-
-(cherry picked from commit 16fafdf4e0ec6cddd5705f407e5dca26cb30914d)
-
-QUIC: Handle EndOfEarlyData and MaxEarlyData
-
-QUIC: Increase HKDF_MAXBUF to 2048
-
-Fall-through for 0RTT
-
-Signed-off-by: James M Snell <jasnell@gmail.com>
----
- deps/openssl/openssl/CHANGES | 3 +
- deps/openssl/openssl/Configure | 3 +
- deps/openssl/openssl/INSTALL | 3 +
- deps/openssl/openssl/crypto/err/openssl.txt | 20 +-
- deps/openssl/openssl/crypto/kdf/hkdf.c | 2 +-
- .../openssl/doc/man3/SSL_CIPHER_get_name.pod | 13 +
- .../doc/man3/SSL_CTX_set_quic_method.pod | 232 ++++++++++++++
- deps/openssl/openssl/include/openssl/evp.h | 4 +
- .../openssl/include/openssl/ossl_typ.h | 2 +
- deps/openssl/openssl/include/openssl/ssl.h | 45 +++
- deps/openssl/openssl/include/openssl/sslerr.h | 18 +-
- deps/openssl/openssl/include/openssl/tls1.h | 3 +
- deps/openssl/openssl/ssl/build.info | 3 +-
- deps/openssl/openssl/ssl/s3_msg.c | 12 +-
- deps/openssl/openssl/ssl/ssl_ciph.c | 32 ++
- deps/openssl/openssl/ssl/ssl_err.c | 26 ++
- deps/openssl/openssl/ssl/ssl_lib.c | 41 ++-
- deps/openssl/openssl/ssl/ssl_local.h | 44 +++
- deps/openssl/openssl/ssl/ssl_quic.c | 285 ++++++++++++++++++
- deps/openssl/openssl/ssl/statem/extensions.c | 29 ++
- .../openssl/ssl/statem/extensions_clnt.c | 52 ++++
- .../openssl/ssl/statem/extensions_srvr.c | 55 +++-
- deps/openssl/openssl/ssl/statem/statem.c | 21 +-
- deps/openssl/openssl/ssl/statem/statem_clnt.c | 8 +
- deps/openssl/openssl/ssl/statem/statem_lib.c | 19 +-
- .../openssl/openssl/ssl/statem/statem_local.h | 19 ++
- deps/openssl/openssl/ssl/statem/statem_quic.c | 109 +++++++
- deps/openssl/openssl/ssl/statem/statem_srvr.c | 3 +-
- deps/openssl/openssl/ssl/tls13_enc.c | 155 ++++++++--
- deps/openssl/openssl/test/sslapitest.c | 132 ++++++++
- deps/openssl/openssl/test/ssltestlib.c | 5 +
- deps/openssl/openssl/test/tls13secretstest.c | 7 +
- deps/openssl/openssl/util/libssl.num | 11 +
- deps/openssl/openssl/util/private.num | 2 +
- 34 files changed, 1383 insertions(+), 35 deletions(-)
- create mode 100644 deps/openssl/openssl/doc/man3/SSL_CTX_set_quic_method.pod
- create mode 100644 deps/openssl/openssl/ssl/ssl_quic.c
- create mode 100644 deps/openssl/openssl/ssl/statem/statem_quic.c
-
-diff --git a/deps/openssl/openssl/CHANGES b/deps/openssl/openssl/CHANGES
-index 057405b0bf..f660c799f0 100644
---- a/deps/openssl/openssl/CHANGES
-+++ b/deps/openssl/openssl/CHANGES
-@@ -115,6 +115,9 @@
-
- Changes between 1.1.1c and 1.1.1d [10 Sep 2019]
-
-+ *) Implement BoringSSL's QUIC API
-+ [Todd Short]
-+
- *) Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random
- number generator (RNG). This was intended to include protection in the
- event of a fork() system call in order to ensure that the parent and child
-diff --git a/deps/openssl/openssl/Configure b/deps/openssl/openssl/Configure
-index 2e9efaa5f3..79a60d0cb5 100755
---- a/deps/openssl/openssl/Configure
-+++ b/deps/openssl/openssl/Configure
-@@ -391,6 +391,7 @@ my @disablables = (
- "poly1305",
- "posix-io",
- "psk",
-+ "quic",
- "rc2",
- "rc4",
- "rc5",
-@@ -507,6 +508,8 @@ my @disable_cascades = (
- sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
-
- sub { !$disabled{"msan"} } => [ "asm" ],
-+
-+ "tls1_3" => [ "quic" ],
- );
-
- # Avoid protocol support holes. Also disable all versions below N, if version
-diff --git a/deps/openssl/openssl/INSTALL b/deps/openssl/openssl/INSTALL
-index f5118428b3..5938e185a1 100644
---- a/deps/openssl/openssl/INSTALL
-+++ b/deps/openssl/openssl/INSTALL
-@@ -456,6 +456,9 @@
- no-psk
- Don't build support for Pre-Shared Key based ciphersuites.
-
-+ no-quic
-+ Don't build with support for QUIC.
-+
- no-rdrand
- Don't use hardware RDRAND capabilities.
-
-diff --git a/deps/openssl/openssl/crypto/err/openssl.txt b/deps/openssl/openssl/crypto/err/openssl.txt
-index 35512f9caf..e7b8799070 100644
---- a/deps/openssl/openssl/crypto/err/openssl.txt
-+++ b/deps/openssl/openssl/crypto/err/openssl.txt
-@@ -1180,7 +1180,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
- SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
- ossl_statem_server_post_process_message
- SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
--SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:
-+SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:ossl_statem_server_pre_work
- SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
- SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
- SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
-@@ -1189,6 +1189,9 @@ SSL_F_PARSE_CA_NAMES:541:parse_ca_names
- SSL_F_PITEM_NEW:624:pitem_new
- SSL_F_PQUEUE_NEW:625:pqueue_new
- SSL_F_PROCESS_KEY_SHARE_EXT:439:*
-+SSL_F_QUIC_CHANGE_CIPHER_STATE:639:quic_change_cipher_state
-+SSL_F_QUIC_GET_MESSAGE:641:quic_get_message
-+SSL_F_QUIC_SET_ENCRYPTION_SECRETS:642:quic_set_encryption_secrets
- SSL_F_READ_STATE_MACHINE:352:read_state_machine
- SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite
- SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET:595:srp_generate_client_master_secret
-@@ -1199,7 +1202,9 @@ SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM:130:ssl3_check_cert_and_algorithm
- SSL_F_SSL3_CTRL:213:ssl3_ctrl
- SSL_F_SSL3_CTX_CTRL:133:ssl3_ctx_ctrl
- SSL_F_SSL3_DIGEST_CACHED_RECORDS:293:ssl3_digest_cached_records
-+SSL_F_SSL3_DISPATCH_ALERT:643:ssl3_dispatch_alert
- SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC:292:ssl3_do_change_cipher_spec
-+SSL_F_SSL3_DO_WRITE:644:ssl3_do_write
- SSL_F_SSL3_ENC:608:ssl3_enc
- SSL_F_SSL3_FINAL_FINISH_MAC:285:ssl3_final_finish_mac
- SSL_F_SSL3_FINISH_MAC:587:ssl3_finish_mac
-@@ -1307,6 +1312,8 @@ SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT:311:*
- SSL_F_SSL_PEEK:270:SSL_peek
- SSL_F_SSL_PEEK_EX:432:SSL_peek_ex
- SSL_F_SSL_PEEK_INTERNAL:522:ssl_peek_internal
-+SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE:645:SSL_process_quic_post_handshake
-+SSL_F_SSL_PROVIDE_QUIC_DATA:646:SSL_provide_quic_data
- SSL_F_SSL_READ:223:SSL_read
- SSL_F_SSL_READ_EARLY_DATA:529:SSL_read_early_data
- SSL_F_SSL_READ_EX:434:SSL_read_ex
-@@ -1356,6 +1363,7 @@ SSL_F_SSL_WRITE_EARLY_DATA:526:SSL_write_early_data
- SSL_F_SSL_WRITE_EARLY_FINISH:527:*
- SSL_F_SSL_WRITE_EX:433:SSL_write_ex
- SSL_F_SSL_WRITE_INTERNAL:524:ssl_write_internal
-+SSL_F_STATEM_FLUSH:647:statem_flush
- SSL_F_STATE_MACHINE:353:state_machine
- SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg
- SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs
-@@ -1419,6 +1427,8 @@ SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH:619:\
- tls_construct_ctos_post_handshake_auth
- SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk
- SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES:509:tls_construct_ctos_psk_kex_modes
-+SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS:648:\
-+ tls_construct_ctos_quic_transport_params
- SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE:473:tls_construct_ctos_renegotiate
- SSL_F_TLS_CONSTRUCT_CTOS_SCT:474:tls_construct_ctos_sct
- SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME:475:tls_construct_ctos_server_name
-@@ -1460,6 +1470,8 @@ SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share
- SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN:548:tls_construct_stoc_maxfragmentlen
- SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg
- SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk
-+SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS:649:\
-+ tls_construct_stoc_quic_transport_params
- SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate
- SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME:459:tls_construct_stoc_server_name
- SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET:460:tls_construct_stoc_session_ticket
-@@ -1488,6 +1500,8 @@ SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen
- SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH:620:tls_parse_ctos_post_handshake_auth
- SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk
- SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes
-+SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS:650:\
-+ tls_parse_ctos_quic_transport_params
- SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate
- SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name
- SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket
-@@ -1506,6 +1520,8 @@ SSL_F_TLS_PARSE_STOC_KEY_SHARE:445:tls_parse_stoc_key_share
- SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN:581:tls_parse_stoc_maxfragmentlen
- SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn
- SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk
-+SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS:651:\
-+ tls_parse_stoc_quic_transport_params
- SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate
- SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct
- SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name
-@@ -2706,6 +2722,7 @@ SSL_R_INCONSISTENT_EARLY_DATA_ALPN:222:inconsistent early data alpn
- SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni
- SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms
- SSL_R_INSUFFICIENT_SECURITY:241:insufficient security
-+SSL_R_INTERNAL_ERROR:295:internal error
- SSL_R_INVALID_ALERT:205:invalid alert
- SSL_R_INVALID_CCS_MESSAGE:260:invalid ccs message
- SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg
-@@ -2881,6 +2898,7 @@ SSL_R_VERSION_TOO_LOW:396:version too low
- SSL_R_WRONG_CERTIFICATE_TYPE:383:wrong certificate type
- SSL_R_WRONG_CIPHER_RETURNED:261:wrong cipher returned
- SSL_R_WRONG_CURVE:378:wrong curve
-+SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED:296:wrong encryption level received
- SSL_R_WRONG_SIGNATURE_LENGTH:264:wrong signature length
- SSL_R_WRONG_SIGNATURE_SIZE:265:wrong signature size
- SSL_R_WRONG_SIGNATURE_TYPE:370:wrong signature type
-diff --git a/deps/openssl/openssl/crypto/kdf/hkdf.c b/deps/openssl/openssl/crypto/kdf/hkdf.c
-index 25bf4b729f..6d1a32c885 100644
---- a/deps/openssl/openssl/crypto/kdf/hkdf.c
-+++ b/deps/openssl/openssl/crypto/kdf/hkdf.c
-@@ -15,7 +15,7 @@
- #include "internal/cryptlib.h"
- #include "crypto/evp.h"
-
--#define HKDF_MAXBUF 1024
-+#define HKDF_MAXBUF 2048
-
- static unsigned char *HKDF(const EVP_MD *evp_md,
- const unsigned char *salt, size_t salt_len,
-diff --git a/deps/openssl/openssl/doc/man3/SSL_CIPHER_get_name.pod b/deps/openssl/openssl/doc/man3/SSL_CIPHER_get_name.pod
-index 26edae3d80..20437b76e8 100644
---- a/deps/openssl/openssl/doc/man3/SSL_CIPHER_get_name.pod
-+++ b/deps/openssl/openssl/doc/man3/SSL_CIPHER_get_name.pod
-@@ -13,6 +13,7 @@ SSL_CIPHER_get_digest_nid,
- SSL_CIPHER_get_handshake_digest,
- SSL_CIPHER_get_kx_nid,
- SSL_CIPHER_get_auth_nid,
-+SSL_CIPHER_get_prf_nid,
- SSL_CIPHER_is_aead,
- SSL_CIPHER_find,
- SSL_CIPHER_get_id,
-@@ -34,6 +35,7 @@ SSL_CIPHER_get_protocol_id
- const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
- int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
- int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
-+ int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c);
- int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
- const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
- uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
-@@ -91,6 +93,15 @@ TLS 1.3 cipher suites) B<NID_auth_any> is returned. Examples (not comprehensive)
- NID_auth_ecdsa
- NID_auth_psk
-
-+SSL_CIPHER_get_prf_nid() retuns the pseudo-random function NID for B<c>. If B<c> is
-+a pre-TLS-1.2 cipher, it returns B<NID_md5_sha1> but note these ciphers use
-+SHA-256 in TLS 1.2. Other return values may be treated uniformly in all
-+applicable versions. Examples (not comprehensive):
-+
-+ NID_md5_sha1
-+ NID_sha256
-+ NID_sha384
-+
- SSL_CIPHER_is_aead() returns 1 if the cipher B<c> is AEAD (e.g. GCM or
- ChaCha20/Poly1305), and 0 if it is not AEAD.
-
-@@ -201,6 +212,8 @@ required to enable this function.
-
- The OPENSSL_cipher_name() function was added in OpenSSL 1.1.1.
-
-+The SSL_CIPHER_get_prf_nid() function was added in OpenSSL 3.0.0.
-+
- =head1 COPYRIGHT
-
- Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
-diff --git a/deps/openssl/openssl/doc/man3/SSL_CTX_set_quic_method.pod b/deps/openssl/openssl/doc/man3/SSL_CTX_set_quic_method.pod
-new file mode 100644
-index 0000000000..60bf704944
---- /dev/null
-+++ b/deps/openssl/openssl/doc/man3/SSL_CTX_set_quic_method.pod
-@@ -0,0 +1,232 @@
-+=pod
-+
-+=head1 NAME
-+
-+SSL_QUIC_METHOD,
-+OSSL_ENCRYPTION_LEVEL,
-+SSL_CTX_set_quic_method,
-+SSL_set_quic_method,
-+SSL_set_quic_transport_params,
-+SSL_get_peer_quic_transport_params,
-+SSL_quic_max_handshake_flight_len,
-+SSL_quic_read_level,
-+SSL_quic_write_level,
-+SSL_provide_quic_data,
-+SSL_process_quic_post_handshake,
-+SSL_is_quic
-+- QUIC support
-+
-+=head1 SYNOPSIS
-+
-+ #include <openssl/ssl.h>
-+
-+ typedef struct ssl_quic_method_st SSL_QUIC_METHOD;
-+ typedef enum ssl_encryption_level_t OSSL_ENCRYPTION_LEVEL;
-+
-+ int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method);
-+ int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method);
-+ int SSL_set_quic_transport_params(SSL *ssl,
-+ const uint8_t *params,
-+ size_t params_len);
-+ void SSL_get_peer_quic_transport_params(const SSL *ssl,
-+ const uint8_t **out_params,
-+ size_t *out_params_len);
-+ size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
-+ OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl);
-+ OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl);
-+ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len);
-+ int SSL_process_quic_post_handshake(SSL *ssl);
-+ int SSL_is_quic(SSL *ssl);
-+
-+=head1 DESCRIPTION
-+
-+SSL_CTX_set_quic_method() and SSL_set_quic_method() configures the QUIC methods.
-+This should only be configured with a minimum version of TLS 1.3. B<quic_method>
-+must remain valid for the lifetime of B<ctx> or B<ssl>. Calling this disables
-+the SSL_OP_ENABLE_MIDDLEBOX_COMPAT option, which is not required for QUIC.
-+
-+SSL_set_quic_transport_params() configures B<ssl> to send B<params> (of length
-+B<params_len>) in the quic_transport_parameters extension in either the
-+ClientHello or EncryptedExtensions handshake message. This extension will
-+only be sent if the TLS version is at least 1.3, and for a server, only if
-+the client sent the extension. The buffer pointed to by B<params> only need be
-+valid for the duration of the call to this function.
-+
-+SSL_get_peer_quic_transport_params() provides the caller with the value of the
-+quic_transport_parameters extension sent by the peer. A pointer to the buffer
-+containing the TransportParameters will be put in B<*out_params>, and its
-+length in B<*out_params_len>. This buffer will be valid for the lifetime of the
-+B<ssl>. If no params were received from the peer, B<*out_params_len> will be 0.
-+
-+SSL_quic_max_handshake_flight_len() returns the maximum number of bytes
-+that may be received at the given encryption level. This function should be
-+used to limit buffering in the QUIC implementation.
-+
-+See https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-4.4.
-+
-+SSL_quic_read_level() returns the current read encryption level.
-+
-+SSL_quic_write_level() returns the current write encryption level.
-+
-+SSL_provide_quic_data() provides data from QUIC at a particular encryption
-+level B<level>. It is an error to call this function outside of the handshake
-+or with an encryption level other than the current read level. It returns one
-+on success and zero on error.
-+
-+SSL_process_quic_post_handshake() processes any data that QUIC has provided
-+after the handshake has completed. This includes NewSessionTicket messages
-+sent by the server.
-+
-+SSL_is_quic() indicates whether a connection uses QUIC.
-+
-+=head1 NOTES
-+
-+These APIs are implementations of BoringSSL's QUIC APIs.
-+
-+QUIC acts as an underlying transport for the TLS 1.3 handshake. The following
-+functions allow a QUIC implementation to serve as the underlying transport as
-+described in draft-ietf-quic-tls.
-+
-+When configured for QUIC, SSL_do_handshake() will drive the handshake as
-+before, but it will not use the configured B<BIO>. It will call functions on
-+B<SSL_QUIC_METHOD> to configure secrets and send data. If data is needed from
-+the peer, it will return B<SSL_ERROR_WANT_READ>. When received, the caller
-+should call SSL_provide_quic_data() and then SSL_do_handshake() to continue
-+the handshake. After the handshake is complete, the caller should call
-+SSL_provide_quic_data() for any post-handshake data, followed by
-+SSL_process_quic_post_handshake() to process it. It is an error to call
-+SSL_read()/SSL_read_ex() and SSL_write()/SSL_write_ex() in QUIC.
-+
-+Note that secrets for an encryption level may be available to QUIC before the
-+level is active in TLS. Callers should use SSL_quic_read_level() to determine
-+the active read level for SSL_provide_quic_data(). SSL_do_handshake() will
-+pass the active write level to add_handshake_data() when writing data. Callers
-+can use SSL_quic_write_level() to query the active write level when
-+generating their own errors.
-+
-+See https://tools.ietf.org/html/draft-ietf-quic-tls-15#section-4.1 for more
-+details.
-+
-+To avoid DoS attacks, the QUIC implementation must limit the amount of data
-+being queued up. The implementation can call
-+SSL_quic_max_handshake_flight_len() to get the maximum buffer length at each
-+encryption level.
-+
-+draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters
-+used by QUIC for each endpoint to unilaterally declare its supported
-+transport parameters. draft-ietf-quic-transport (section 7.4) defines the
-+contents of that extension (a TransportParameters struct) and describes how
-+to handle it and its semantic meaning.
-+
-+OpenSSL handles this extension as an opaque byte string. The caller is
-+responsible for serializing and parsing it.
-+
-+=head2 OSSL_ENCRYPTION_LEVEL
-+
-+B<OSSL_ENCRYPTION_LEVEL> (B<enum ssl_encryption_level_t>) represents the
-+encryption levels:
-+
-+=over 4
-+
-+=item ssl_encryption_initial
-+
-+The initial encryption level that is used for client and server hellos.
-+
-+=item ssl_encryption_early_data
-+
-+The encryption level for early data. This is a write-level for the client
-+and a read-level for the server.
-+
-+=item ssl_encryption_handshake
-+
-+The encryption level for the remainder of the handshake.
-+
-+=item ssl_encryption_application
-+
-+The encryption level for the application data.
-+
-+=back
-+
-+=head2 SSL_QUIC_METHOD
-+
-+The B<SSL_QUIC_METHOD> (B<struct ssl_quic_method_st>) describes the
-+QUIC methods.
-+
-+ struct ssl_quic_method_st {
-+ int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *read_secret,
-+ const uint8_t *write_secret, size_t secret_len);
-+ int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len);
-+ int (*flush_flight)(SSL *ssl);
-+ int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert);
-+ };
-+ typedef struct ssl_quic_method_st SSL_QUIC_METHOD;
-+
-+set_encryption_secrets() configures the read and write secrets for the given
-+encryption level. This function will always be called before an encryption
-+level other than B<ssl_encryption_initial> is used. Note, however, that
-+secrets for a level may be configured before TLS is ready to send or accept
-+data at that level.
-+
-+When reading packets at a given level, the QUIC implementation must send
-+ACKs at the same level, so this function provides read and write secrets
-+together. The exception is B<ssl_encryption_early_data>, where secrets are
-+only available in the client to server direction. The other secret will be
-+NULL. The server acknowledges such data at B<ssl_encryption_application>,
-+which will be configured in the same SSL_do_handshake() call.
-+
-+This function should use SSL_get_current_cipher() to determine the TLS
-+cipher suite.
-+
-+add_handshake_data() adds handshake data to the current flight at the given
-+encryption level. It returns one on success and zero on error.
-+
-+OpenSSL will pack data from a single encryption level together, but a
-+single handshake flight may include multiple encryption levels. Callers
-+should defer writing data to the network until flush_flight() to better
-+pack QUIC packets into transport datagrams.
-+
-+flush_flight() is called when the current flight is complete and should be
-+written to the transport. Note a flight may contain data at several
-+encryption levels.
-+
-+send_alert() sends a fatal alert at the specified encryption level.
-+
-+All QUIC methods return 1 on success and 0 on error.
-+
-+=head1 RETURN VALUES
-+
-+SSL_CTX_set_quic_method(),
-+SSL_set_quic_method(),
-+SSL_set_quic_transport_params(), and
-+SSL_process_quic_post_handshake()
-+return 1 on success, and 0 on error.
-+
-+SSL_quic_read_level() and SSL_quic_write_level() return the current
-+encryption level as B<OSSL_ENCRYPTION_LEVEL> (B<enum ssl_encryption_level_t>).
-+
-+SSL_quic_max_handshake_flight_len() returns the maximum length of a flight
-+for a given encryption level.
-+
-+SSL_is_quic() returns 1 if QUIC is being used, 0 if not.
-+
-+=head1 SEE ALSO
-+
-+L<ssl(7)>, L<SSL_CIPHER_get_prf_nid(3)>, L<SSL_do_handshake(3)>
-+
-+=head1 HISTORY
-+
-+These functions were added in OpenSSL 3.0.0.
-+
-+=head1 COPYRIGHT
-+
-+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
-+
-+Licensed under the Apache License 2.0 (the "License"). You may not use
-+this file except in compliance with the License. You can obtain a copy
-+in the file LICENSE in the source distribution or at
-+L<https://www.openssl.org/source/license.html>.
-+
-+=cut
-diff --git a/deps/openssl/openssl/include/openssl/evp.h b/deps/openssl/openssl/include/openssl/evp.h
-index a411f3f2f9..275b7a4acc 100644
---- a/deps/openssl/openssl/include/openssl/evp.h
-+++ b/deps/openssl/openssl/include/openssl/evp.h
-@@ -1324,6 +1324,10 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
- */
- # define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4
-
-+/* Used by Chromium/QUIC */
-+# define X25519_PRIVATE_KEY_LEN 32
-+# define X25519_PUBLIC_VALUE_LEN 32
-+
- const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
- EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
- void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
-diff --git a/deps/openssl/openssl/include/openssl/ossl_typ.h b/deps/openssl/openssl/include/openssl/ossl_typ.h
-index e0edfaaf47..d2fdce8fdf 100644
---- a/deps/openssl/openssl/include/openssl/ossl_typ.h
-+++ b/deps/openssl/openssl/include/openssl/ossl_typ.h
-@@ -176,6 +176,8 @@ typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX;
- typedef struct ossl_store_info_st OSSL_STORE_INFO;
- typedef struct ossl_store_search_st OSSL_STORE_SEARCH;
-
-+typedef struct ssl_quic_method_st SSL_QUIC_METHOD;
-+
- #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
- defined(INTMAX_MAX) && defined(UINTMAX_MAX)
- typedef intmax_t ossl_intmax_t;
-diff --git a/deps/openssl/openssl/include/openssl/ssl.h b/deps/openssl/openssl/include/openssl/ssl.h
-index 6724ccf2d2..f21458cd5e 100644
---- a/deps/openssl/openssl/include/openssl/ssl.h
-+++ b/deps/openssl/openssl/include/openssl/ssl.h
-@@ -2432,6 +2432,51 @@ void SSL_set_allow_early_data_cb(SSL *s,
- SSL_allow_early_data_cb_fn cb,
- void *arg);
-
-+# ifndef OPENSSL_NO_QUIC
-+/*
-+ * QUIC integration - The QUIC interface matches BoringSSL
-+ *
-+ * ssl_encryption_level_t represents a specific QUIC encryption level used to
-+ * transmit handshake messages. BoringSSL has this as an 'enum'.
-+ */
-+typedef enum ssl_encryption_level_t {
-+ ssl_encryption_initial = 0,
-+ ssl_encryption_early_data,
-+ ssl_encryption_handshake,
-+ ssl_encryption_application
-+} OSSL_ENCRYPTION_LEVEL;
-+
-+struct ssl_quic_method_st {
-+ int (*set_encryption_secrets)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *read_secret,
-+ const uint8_t *write_secret, size_t secret_len);
-+ int (*add_handshake_data)(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len);
-+ int (*flush_flight)(SSL *ssl);
-+ int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert);
-+};
-+
-+__owur int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method);
-+__owur int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method);
-+__owur int SSL_set_quic_transport_params(SSL *ssl,
-+ const uint8_t *params,
-+ size_t params_len);
-+void SSL_get_peer_quic_transport_params(const SSL *ssl,
-+ const uint8_t **out_params,
-+ size_t *out_params_len);
-+__owur size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
-+__owur OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl);
-+__owur OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl);
-+__owur int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len);
-+__owur int SSL_process_quic_post_handshake(SSL *ssl);
-+
-+__owur int SSL_is_quic(SSL *ssl);
-+
-+# endif
-+
-+int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c);
-+
- # ifdef __cplusplus
- }
- # endif
-diff --git a/deps/openssl/openssl/include/openssl/sslerr.h b/deps/openssl/openssl/include/openssl/sslerr.h
-index 82983d3c1e..e3915c0a55 100644
---- a/deps/openssl/openssl/include/openssl/sslerr.h
-+++ b/deps/openssl/openssl/include/openssl/sslerr.h
-@@ -11,9 +11,7 @@
- #ifndef HEADER_SSLERR_H
- # define HEADER_SSLERR_H
-
--# ifndef HEADER_SYMHACKS_H
--# include <openssl/symhacks.h>
--# endif
-+# include <openssl/symhacks.h>
-
- # ifdef __cplusplus
- extern "C"
-@@ -96,6 +94,9 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_PITEM_NEW 624
- # define SSL_F_PQUEUE_NEW 625
- # define SSL_F_PROCESS_KEY_SHARE_EXT 439
-+# define SSL_F_QUIC_CHANGE_CIPHER_STATE 639
-+# define SSL_F_QUIC_GET_MESSAGE 641
-+# define SSL_F_QUIC_SET_ENCRYPTION_SECRETS 642
- # define SSL_F_READ_STATE_MACHINE 352
- # define SSL_F_SET_CLIENT_CIPHERSUITE 540
- # define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET 595
-@@ -106,7 +107,9 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_SSL3_CTRL 213
- # define SSL_F_SSL3_CTX_CTRL 133
- # define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293
-+# define SSL_F_SSL3_DISPATCH_ALERT 643
- # define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292
-+# define SSL_F_SSL3_DO_WRITE 644
- # define SSL_F_SSL3_ENC 608
- # define SSL_F_SSL3_FINAL_FINISH_MAC 285
- # define SSL_F_SSL3_FINISH_MAC 587
-@@ -211,6 +214,8 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_SSL_PEEK 270
- # define SSL_F_SSL_PEEK_EX 432
- # define SSL_F_SSL_PEEK_INTERNAL 522
-+# define SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE 645
-+# define SSL_F_SSL_PROVIDE_QUIC_DATA 646
- # define SSL_F_SSL_READ 223
- # define SSL_F_SSL_READ_EARLY_DATA 529
- # define SSL_F_SSL_READ_EX 434
-@@ -260,6 +265,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_SSL_WRITE_EARLY_FINISH 527
- # define SSL_F_SSL_WRITE_EX 433
- # define SSL_F_SSL_WRITE_INTERNAL 524
-+# define SSL_F_STATEM_FLUSH 647
- # define SSL_F_STATE_MACHINE 353
- # define SSL_F_TLS12_CHECK_PEER_SIGALG 333
- # define SSL_F_TLS12_COPY_SIGALGS 533
-@@ -319,6 +325,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH 619
- # define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501
- # define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509
-+# define SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS 648
- # define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473
- # define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474
- # define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 475
-@@ -358,6 +365,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 548
- # define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457
- # define SSL_F_TLS_CONSTRUCT_STOC_PSK 504
-+# define SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS 649
- # define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458
- # define SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME 459
- # define SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET 460
-@@ -383,6 +391,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH 620
- # define SSL_F_TLS_PARSE_CTOS_PSK 505
- # define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES 572
-+# define SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS 650
- # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE 464
- # define SSL_F_TLS_PARSE_CTOS_SERVER_NAME 573
- # define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET 574
-@@ -401,6 +410,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN 581
- # define SSL_F_TLS_PARSE_STOC_NPN 582
- # define SSL_F_TLS_PARSE_STOC_PSK 502
-+# define SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS 651
- # define SSL_F_TLS_PARSE_STOC_RENEGOTIATE 448
- # define SSL_F_TLS_PARSE_STOC_SCT 564
- # define SSL_F_TLS_PARSE_STOC_SERVER_NAME 583
-@@ -565,6 +575,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_R_INCONSISTENT_EARLY_DATA_SNI 231
- # define SSL_R_INCONSISTENT_EXTMS 104
- # define SSL_R_INSUFFICIENT_SECURITY 241
-+# define SSL_R_INTERNAL_ERROR 295
- # define SSL_R_INVALID_ALERT 205
- # define SSL_R_INVALID_CCS_MESSAGE 260
- # define SSL_R_INVALID_CERTIFICATE_OR_ALG 238
-@@ -762,6 +773,7 @@ int ERR_load_SSL_strings(void);
- # define SSL_R_WRONG_CERTIFICATE_TYPE 383
- # define SSL_R_WRONG_CIPHER_RETURNED 261
- # define SSL_R_WRONG_CURVE 378
-+# define SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED 296
- # define SSL_R_WRONG_SIGNATURE_LENGTH 264
- # define SSL_R_WRONG_SIGNATURE_SIZE 265
- # define SSL_R_WRONG_SIGNATURE_TYPE 370
-diff --git a/deps/openssl/openssl/include/openssl/tls1.h b/deps/openssl/openssl/include/openssl/tls1.h
-index 76d9fda46e..6e16c97316 100644
---- a/deps/openssl/openssl/include/openssl/tls1.h
-+++ b/deps/openssl/openssl/include/openssl/tls1.h
-@@ -148,6 +148,9 @@ extern "C" {
- /* Temporary extension type */
- # define TLSEXT_TYPE_renegotiate 0xff01
-
-+/* ExtensionType value from draft-ietf-quic-tls-13 */
-+# define TLSEXT_TYPE_quic_transport_parameters 0xffa5
-+
- # ifndef OPENSSL_NO_NEXTPROTONEG
- /* This is not an IANA defined extension number */
- # define TLSEXT_TYPE_next_proto_neg 13172
-diff --git a/deps/openssl/openssl/ssl/build.info b/deps/openssl/openssl/ssl/build.info
-index bb2f1deb53..eec0d14f2c 100644
---- a/deps/openssl/openssl/ssl/build.info
-+++ b/deps/openssl/openssl/ssl/build.info
-@@ -12,4 +12,5 @@ SOURCE[../libssl]=\
- ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \
- bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \
- record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \
-- statem/statem.c record/ssl3_record_tls13.c
-+ statem/statem.c record/ssl3_record_tls13.c \
-+ ssl_quic.c statem/statem_quic.c
-diff --git a/deps/openssl/openssl/ssl/s3_msg.c b/deps/openssl/openssl/ssl/s3_msg.c
-index 339fb2774a..8d3cd442aa 100644
---- a/deps/openssl/openssl/ssl/s3_msg.c
-+++ b/deps/openssl/openssl/ssl/s3_msg.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
-+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
-@@ -75,6 +75,16 @@ int ssl3_dispatch_alert(SSL *s)
-
- s->s3->alert_dispatch = 0;
- alertlen = 2;
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ if (!s->quic_method->send_alert(s, s->quic_write_level,
-+ s->s3->send_alert[1])) {
-+ SSLerr(SSL_F_SSL3_DISPATCH_ALERT, SSL_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ i = 1;
-+ } else
-+#endif
- i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0,
- &written);
- if (i <= 0) {
-diff --git a/deps/openssl/openssl/ssl/ssl_ciph.c b/deps/openssl/openssl/ssl/ssl_ciph.c
-index 735a483c64..a3fe97597b 100644
---- a/deps/openssl/openssl/ssl/ssl_ciph.c
-+++ b/deps/openssl/openssl/ssl/ssl_ciph.c
-@@ -2162,3 +2162,35 @@ int ssl_cert_is_disabled(size_t idx)
- return 1;
- return 0;
- }
-+
-+int SSL_CIPHER_get_prf_nid(const SSL_CIPHER *c)
-+{
-+ switch (c->algorithm2 & (0xFF << TLS1_PRF_DGST_SHIFT)) {
-+ default:
-+ break;
-+ case TLS1_PRF_SHA1_MD5: /* TLS1_PRF */
-+ return NID_md5_sha1;
-+ case TLS1_PRF_SHA256:
-+ return NID_sha256;
-+ case TLS1_PRF_SHA384:
-+ return NID_sha384;
-+ case TLS1_PRF_GOST94:
-+ return NID_id_GostR3411_94_prf;
-+ case TLS1_PRF_GOST12_256:
-+ return NID_id_GostR3411_2012_256;
-+ case TLS1_PRF_GOST12_512:
-+ return NID_id_GostR3411_2012_512;
-+ }
-+ /* TLSv1.3 ciphers don't specify separate PRF */
-+ switch (c->algorithm2 & SSL_HANDSHAKE_MAC_MASK) {
-+ default:
-+ break;
-+ case SSL_HANDSHAKE_MAC_MD5_SHA1: /* SSL_HANDSHAKE_MAC_DEFAULT */
-+ return NID_md5_sha1;
-+ case SSL_HANDSHAKE_MAC_SHA256:
-+ return NID_sha256;
-+ case SSL_HANDSHAKE_MAC_SHA384:
-+ return NID_sha384;
-+ }
-+ return NID_undef;
-+}
-diff --git a/deps/openssl/openssl/ssl/ssl_err.c b/deps/openssl/openssl/ssl/ssl_err.c
-index 4b12ed1485..3cdbee2ffa 100644
---- a/deps/openssl/openssl/ssl/ssl_err.c
-+++ b/deps/openssl/openssl/ssl/ssl_err.c
-@@ -112,6 +112,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- "ossl_statem_server_post_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0),
- "ossl_statem_server_post_work"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PRE_WORK, 0),
-+ "ossl_statem_server_pre_work"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0),
- "ossl_statem_server_process_message"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0),
-@@ -122,6 +124,11 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PITEM_NEW, 0), "pitem_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PQUEUE_NEW, 0), "pqueue_new"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_PROCESS_KEY_SHARE_EXT, 0), ""},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_QUIC_CHANGE_CIPHER_STATE, 0),
-+ "quic_change_cipher_state"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_QUIC_GET_MESSAGE, 0), "quic_get_message"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_QUIC_SET_ENCRYPTION_SECRETS, 0),
-+ "quic_set_encryption_secrets"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_READ_STATE_MACHINE, 0), "read_state_machine"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SET_CLIENT_CIPHERSUITE, 0),
- "set_client_ciphersuite"},
-@@ -139,8 +146,11 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CTX_CTRL, 0), "ssl3_ctx_ctrl"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DIGEST_CACHED_RECORDS, 0),
- "ssl3_digest_cached_records"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DISPATCH_ALERT, 0),
-+ "ssl3_dispatch_alert"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, 0),
- "ssl3_do_change_cipher_spec"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_DO_WRITE, 0), "ssl3_do_write"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_ENC, 0), "ssl3_enc"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINAL_FINISH_MAC, 0),
- "ssl3_final_finish_mac"},
-@@ -302,6 +312,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK, 0), "SSL_peek"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_EX, 0), "SSL_peek_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PEEK_INTERNAL, 0), "ssl_peek_internal"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE, 0),
-+ "SSL_process_quic_post_handshake"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PROVIDE_QUIC_DATA, 0),
-+ "SSL_provide_quic_data"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ, 0), "SSL_read"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_READ_EARLY_DATA, 0),
- "SSL_read_early_data"},
-@@ -378,6 +392,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EARLY_FINISH, 0), ""},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_EX, 0), "SSL_write_ex"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_WRITE_INTERNAL, 0), "ssl_write_internal"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_STATEM_FLUSH, 0), "statem_flush"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_STATE_MACHINE, 0), "state_machine"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_CHECK_PEER_SIGALG, 0),
- "tls12_check_peer_sigalg"},
-@@ -479,6 +494,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- "tls_construct_ctos_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, 0),
- "tls_construct_ctos_psk_kex_modes"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS, 0),
-+ "tls_construct_ctos_quic_transport_params"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, 0),
- "tls_construct_ctos_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_SCT, 0),
-@@ -550,6 +567,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- "tls_construct_stoc_next_proto_neg"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_PSK, 0),
- "tls_construct_stoc_psk"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, 0),
-+ "tls_construct_stoc_quic_transport_params"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, 0),
- "tls_construct_stoc_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, 0),
-@@ -596,6 +615,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK, 0), "tls_parse_ctos_psk"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, 0),
- "tls_parse_ctos_psk_kex_modes"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, 0),
-+ "tls_parse_ctos_quic_transport_params"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, 0),
- "tls_parse_ctos_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, 0),
-@@ -628,6 +649,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
- "tls_parse_stoc_maxfragmentlen"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_NPN, 0), "tls_parse_stoc_npn"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_PSK, 0), "tls_parse_stoc_psk"},
-+ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, 0),
-+ "tls_parse_stoc_quic_transport_params"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, 0),
- "tls_parse_stoc_renegotiate"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SCT, 0), "tls_parse_stoc_sct"},
-@@ -905,6 +928,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INSUFFICIENT_SECURITY),
- "insufficient security"},
-+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INTERNAL_ERROR), "internal error"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_ALERT), "invalid alert"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CCS_MESSAGE),
- "invalid ccs message"},
-@@ -1248,6 +1272,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CIPHER_RETURNED),
- "wrong cipher returned"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_CURVE), "wrong curve"},
-+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED),
-+ "wrong encryption level received"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_LENGTH),
- "wrong signature length"},
- {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_WRONG_SIGNATURE_SIZE),
-diff --git a/deps/openssl/openssl/ssl/ssl_lib.c b/deps/openssl/openssl/ssl/ssl_lib.c
-index b9adc45a8e..9b318de506 100644
---- a/deps/openssl/openssl/ssl/ssl_lib.c
-+++ b/deps/openssl/openssl/ssl/ssl_lib.c
-@@ -839,6 +839,10 @@ SSL *SSL_new(SSL_CTX *ctx)
-
- s->job = NULL;
-
-+#ifndef OPENSSL_NO_QUIC
-+ s->quic_method = ctx->quic_method;
-+#endif
-+
- #ifndef OPENSSL_NO_CT
- if (!SSL_set_ct_validation_callback(s, ctx->ct_validation_callback,
- ctx->ct_validation_callback_arg))
-@@ -1204,6 +1208,18 @@ void SSL_free(SSL *s)
- OPENSSL_free(s->pha_context);
- EVP_MD_CTX_free(s->pha_dgst);
-
-+#ifndef OPENSSL_NO_QUIC
-+ OPENSSL_free(s->ext.quic_transport_params);
-+ OPENSSL_free(s->ext.peer_quic_transport_params);
-+ while (s->quic_input_data_head != NULL) {
-+ QUIC_DATA *qd;
-+
-+ qd = s->quic_input_data_head;
-+ s->quic_input_data_head = qd->next;
-+ OPENSSL_free(qd);
-+ }
-+#endif
-+
- sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free);
- sk_X509_NAME_pop_free(s->client_ca_names, X509_NAME_free);
-
-@@ -1723,6 +1739,12 @@ static int ssl_io_intern(void *vargs)
-
- int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
- {
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-+ return -1;
-+ }
-+#endif
- if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_READ_INTERNAL, SSL_R_UNINITIALIZED);
- return -1;
-@@ -1855,6 +1877,12 @@ int SSL_get_early_data_status(const SSL *s)
-
- static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
- {
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ SSLerr(SSL_F_SSL_PEEK_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-+ return -1;
-+ }
-+#endif
- if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_PEEK_INTERNAL, SSL_R_UNINITIALIZED);
- return -1;
-@@ -1915,6 +1943,12 @@ int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
-
- int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
- {
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-+ return -1;
-+ }
-+#endif
- if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_UNINITIALIZED);
- return -1;
-@@ -3565,6 +3599,11 @@ int SSL_get_error(const SSL *s, int i)
- }
-
- if (SSL_want_read(s)) {
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ return SSL_ERROR_WANT_READ;
-+ }
-+#endif
- bio = SSL_get_rbio(s);
- if (BIO_should_read(bio))
- return SSL_ERROR_WANT_READ;
-@@ -3943,7 +3982,7 @@ EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
-
- const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
- {
-- if ((s->session != NULL) && (s->session->cipher != NULL))
-+ if (s->session != NULL)
- return s->session->cipher;
- return NULL;
- }
-diff --git a/deps/openssl/openssl/ssl/ssl_local.h b/deps/openssl/openssl/ssl/ssl_local.h
-index 8ddbde7729..016b253858 100644
---- a/deps/openssl/openssl/ssl/ssl_local.h
-+++ b/deps/openssl/openssl/ssl/ssl_local.h
-@@ -315,6 +315,13 @@
- /* Flag used on OpenSSL ciphersuite ids to indicate they are for SSLv3+ */
- # define SSL3_CK_CIPHERSUITE_FLAG 0x03000000
-
-+/* Check if an SSL structure is using QUIC (which uses TLSv1.3) */
-+# ifndef OPENSSL_NO_QUIC
-+# define SSL_IS_QUIC(s) (s->quic_method != NULL)
-+# else
-+# define SSL_IS_QUIC(s) 0
-+# endif
-+
- /* Check if an SSL structure is using DTLS */
- # define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
-
-@@ -715,6 +722,7 @@ typedef enum tlsext_index_en {
- TLSEXT_IDX_cryptopro_bug,
- TLSEXT_IDX_early_data,
- TLSEXT_IDX_certificate_authorities,
-+ TLSEXT_IDX_quic_transport_params,
- TLSEXT_IDX_padding,
- TLSEXT_IDX_psk,
- /* Dummy index - must always be the last entry */
-@@ -1064,7 +1072,24 @@ struct ssl_ctx_st {
-
- /* Do we advertise Post-handshake auth support? */
- int pha_enabled;
-+
-+#ifndef OPENSSL_NO_QUIC
-+ const SSL_QUIC_METHOD *quic_method;
-+#endif
-+};
-+
-+typedef struct cert_pkey_st CERT_PKEY;
-+
-+#ifndef OPENSSL_NO_QUIC
-+struct quic_data_st {
-+ struct quic_data_st *next;
-+ OSSL_ENCRYPTION_LEVEL level;
-+ size_t offset;
-+ size_t length;
- };
-+typedef struct quic_data_st QUIC_DATA;
-+int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level);
-+#endif
-
- struct ssl_st {
- /*
-@@ -1153,6 +1178,11 @@ struct ssl_st {
- unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE];
- unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
- unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
-+# ifndef OPENSSL_NO_QUIC
-+ unsigned char client_hand_traffic_secret[EVP_MAX_MD_SIZE];
-+ unsigned char server_hand_traffic_secret[EVP_MAX_MD_SIZE];
-+ unsigned char client_early_traffic_secret[EVP_MAX_MD_SIZE];
-+# endif
- unsigned char exporter_master_secret[EVP_MAX_MD_SIZE];
- unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE];
- EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
-@@ -1365,8 +1395,22 @@ struct ssl_st {
- * selected.
- */
- int tick_identity;
-+
-+#ifndef OPENSSL_NO_QUIC
-+ uint8_t *quic_transport_params;
-+ size_t quic_transport_params_len;
-+ uint8_t *peer_quic_transport_params;
-+ size_t peer_quic_transport_params_len;
-+#endif
- } ext;
-
-+#ifndef OPENSSL_NO_QUIC
-+ OSSL_ENCRYPTION_LEVEL quic_read_level;
-+ OSSL_ENCRYPTION_LEVEL quic_write_level;
-+ QUIC_DATA *quic_input_data_head;
-+ QUIC_DATA *quic_input_data_tail;
-+ const SSL_QUIC_METHOD *quic_method;
-+#endif
- /*
- * Parsed form of the ClientHello, kept around across client_hello_cb
- * calls.
-diff --git a/deps/openssl/openssl/ssl/ssl_quic.c b/deps/openssl/openssl/ssl/ssl_quic.c
-new file mode 100644
-index 0000000000..2d8accbdd1
---- /dev/null
-+++ b/deps/openssl/openssl/ssl/ssl_quic.c
-@@ -0,0 +1,285 @@
-+/*
-+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
-+ *
-+ * Licensed under the Apache License 2.0 (the "License"). You may not use
-+ * this file except in compliance with the License. You can obtain a copy
-+ * in the file LICENSE in the source distribution or at
-+ * https://www.openssl.org/source/license.html
-+ */
-+
-+#include "ssl_local.h"
-+#include "internal/cryptlib.h"
-+#include "internal/refcount.h"
-+
-+#ifdef OPENSSL_NO_QUIC
-+NON_EMPTY_TRANSLATION_UNIT
-+#else
-+
-+int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
-+ size_t params_len)
-+{
-+ uint8_t *tmp;
-+
-+ if (params == NULL || params_len == 0) {
-+ tmp = NULL;
-+ params_len = 0;
-+ } else {
-+ tmp = OPENSSL_memdup(params, params_len);
-+ if (tmp == NULL)
-+ return 0;
-+ }
-+
-+ OPENSSL_free(ssl->ext.quic_transport_params);
-+ ssl->ext.quic_transport_params = tmp;
-+ ssl->ext.quic_transport_params_len = params_len;
-+ return 1;
-+}
-+
-+void SSL_get_peer_quic_transport_params(const SSL *ssl,
-+ const uint8_t **out_params,
-+ size_t *out_params_len)
-+{
-+ *out_params = ssl->ext.peer_quic_transport_params;
-+ *out_params_len = ssl->ext.peer_quic_transport_params_len;
-+}
-+
-+size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, OSSL_ENCRYPTION_LEVEL level)
-+{
-+ /*
-+ * Limits flights to 16K by default when there are no large
-+ * (certificate-carrying) messages.
-+ */
-+ static const size_t DEFAULT_FLIGHT_LIMIT = 16384;
-+
-+ switch (level) {
-+ case ssl_encryption_initial:
-+ return DEFAULT_FLIGHT_LIMIT;
-+ case ssl_encryption_early_data:
-+ /* QUIC does not send EndOfEarlyData. */
-+ return 0;
-+ case ssl_encryption_handshake:
-+ if (ssl->server) {
-+ /*
-+ * Servers may receive Certificate message if configured to request
-+ * client certificates.
-+ */
-+ if ((ssl->verify_mode & SSL_VERIFY_PEER)
-+ && ssl->max_cert_list > DEFAULT_FLIGHT_LIMIT)
-+ return ssl->max_cert_list;
-+ } else {
-+ /*
-+ * Clients may receive both Certificate message and a CertificateRequest
-+ * message.
-+ */
-+ if (2*ssl->max_cert_list > DEFAULT_FLIGHT_LIMIT)
-+ return 2 * ssl->max_cert_list;
-+ }
-+ return DEFAULT_FLIGHT_LIMIT;
-+ case ssl_encryption_application:
-+ return DEFAULT_FLIGHT_LIMIT;
-+ }
-+
-+ return 0;
-+}
-+
-+OSSL_ENCRYPTION_LEVEL SSL_quic_read_level(const SSL *ssl)
-+{
-+ return ssl->quic_read_level;
-+}
-+
-+OSSL_ENCRYPTION_LEVEL SSL_quic_write_level(const SSL *ssl)
-+{
-+ return ssl->quic_write_level;
-+}
-+
-+int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len)
-+{
-+ size_t l;
-+
-+ if (!SSL_IS_QUIC(ssl)) {
-+ SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-+ return 0;
-+ }
-+
-+ /* Level can be different than the current read, but not less */
-+ if (level < ssl->quic_read_level
-+ || (ssl->quic_input_data_tail != NULL && level < ssl->quic_input_data_tail->level)) {
-+ SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED);
-+ return 0;
-+ }
-+
-+ /* Split the QUIC messages up, if necessary */
-+ while (len > 0) {
-+ QUIC_DATA *qd;
-+ const uint8_t *p = data + 1;
-+
-+ /* Check for an incomplete block */
-+ qd = ssl->quic_input_data_tail;
-+ if (qd != NULL) {
-+ l = qd->length - qd->offset;
-+ if (l != 0) {
-+ /* we still need to copy `l` bytes into the last data block */
-+ if (l > len)
-+ l = len;
-+ memcpy((char*)(qd+1) + qd->offset, data, l);
-+ qd->offset += l;
-+ len -= l;
-+ data += l;
-+ continue;
-+ }
-+ }
-+
-+ n2l3(p, l);
-+ l += SSL3_HM_HEADER_LENGTH;
-+
-+ qd = OPENSSL_zalloc(sizeof(QUIC_DATA) + l);
-+ if (qd == NULL) {
-+ SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+
-+ qd->next = NULL;
-+ qd->length = l;
-+ qd->level = level;
-+ /* partial data received? */
-+ if (l > len)
-+ l = len;
-+ qd->offset = l;
-+
-+ memcpy((void*)(qd + 1), data, l);
-+ if (ssl->quic_input_data_tail != NULL)
-+ ssl->quic_input_data_tail->next = qd;
-+ else
-+ ssl->quic_input_data_head = qd;
-+ ssl->quic_input_data_tail = qd;
-+
-+ data += l;
-+ len -= l;
-+ }
-+
-+ return 1;
-+}
-+
-+int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method)
-+{
-+ switch (ctx->method->version) {
-+ case DTLS1_VERSION:
-+ case DTLS1_2_VERSION:
-+ case DTLS_ANY_VERSION:
-+ case DTLS1_BAD_VER:
-+ return 0;
-+ default:
-+ break;
-+ }
-+ ctx->quic_method = quic_method;
-+ ctx->options &= ~SSL_OP_ENABLE_MIDDLEBOX_COMPAT;
-+ return 1;
-+}
-+
-+int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method)
-+{
-+ switch (ssl->method->version) {
-+ case DTLS1_VERSION:
-+ case DTLS1_2_VERSION:
-+ case DTLS_ANY_VERSION:
-+ case DTLS1_BAD_VER:
-+ return 0;
-+ default:
-+ break;
-+ }
-+ ssl->quic_method = quic_method;
-+ ssl->options &= ~SSL_OP_ENABLE_MIDDLEBOX_COMPAT;
-+ return 1;
-+}
-+
-+int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level)
-+{
-+ uint8_t *c2s_secret = NULL;
-+ uint8_t *s2c_secret = NULL;
-+ size_t len;
-+ const EVP_MD *md;
-+
-+ if (!SSL_IS_QUIC(ssl))
-+ return 1;
-+
-+ /* secrets from the POV of the client */
-+ switch (level) {
-+ case ssl_encryption_early_data:
-+ c2s_secret = ssl->client_early_traffic_secret;
-+ break;
-+ case ssl_encryption_handshake:
-+ c2s_secret = ssl->client_hand_traffic_secret;
-+ s2c_secret = ssl->server_hand_traffic_secret;
-+ break;
-+ case ssl_encryption_application:
-+ c2s_secret = ssl->client_app_traffic_secret;
-+ s2c_secret = ssl->server_app_traffic_secret;
-+ break;
-+ default:
-+ return 1;
-+ }
-+
-+ md = ssl_handshake_md(ssl);
-+ if (md == NULL) {
-+ /* May not have selected cipher, yet */
-+ const SSL_CIPHER *c = NULL;
-+
-+ if (ssl->session != NULL)
-+ c = SSL_SESSION_get0_cipher(ssl->session);
-+ else if (ssl->psksession != NULL)
-+ c = SSL_SESSION_get0_cipher(ssl->psksession);
-+
-+ if (c != NULL)
-+ md = SSL_CIPHER_get_handshake_digest(c);
-+ }
-+
-+ if ((len = EVP_MD_size(md)) <= 0) {
-+ SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
-+ ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+
-+ if (ssl->server) {
-+ if (!ssl->quic_method->set_encryption_secrets(ssl, level, c2s_secret,
-+ s2c_secret, len)) {
-+ SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
-+ ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ } else {
-+ if (!ssl->quic_method->set_encryption_secrets(ssl, level, s2c_secret,
-+ c2s_secret, len)) {
-+ SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_SET_ENCRYPTION_SECRETS,
-+ ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+int SSL_process_quic_post_handshake(SSL *ssl)
-+{
-+ int ret;
-+
-+ if (SSL_in_init(ssl) || !SSL_IS_QUIC(ssl)) {
-+ SSLerr(SSL_F_SSL_PROCESS_QUIC_POST_HANDSHAKE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-+ return 0;
-+ }
-+
-+ ossl_statem_set_in_init(ssl, 1);
-+ ret = ssl->handshake_func(ssl);
-+ ossl_statem_set_in_init(ssl, 0);
-+
-+ if (ret <= 0)
-+ return 0;
-+ return 1;
-+}
-+
-+int SSL_is_quic(SSL* ssl)
-+{
-+ return SSL_IS_QUIC(ssl);
-+}
-+
-+#endif
-diff --git a/deps/openssl/openssl/ssl/statem/extensions.c b/deps/openssl/openssl/ssl/statem/extensions.c
-index 4ef8b417b8..be09afbe71 100644
---- a/deps/openssl/openssl/ssl/statem/extensions.c
-+++ b/deps/openssl/openssl/ssl/statem/extensions.c
-@@ -56,6 +56,10 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent);
- static int final_early_data(SSL *s, unsigned int context, int sent);
- static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
- static int init_post_handshake_auth(SSL *s, unsigned int context);
-+#ifndef OPENSSL_NO_QUIC
-+static int init_quic_transport_params(SSL *s, unsigned int context);
-+static int final_quic_transport_params(SSL *s, unsigned int context, int sent);
-+#endif
-
- /* Structure to define a built-in extension */
- typedef struct extensions_definition_st {
-@@ -373,6 +377,19 @@ static const EXTENSION_DEFINITION ext_defs[] = {
- tls_construct_certificate_authorities,
- tls_construct_certificate_authorities, NULL,
- },
-+#ifndef OPENSSL_NO_QUIC
-+ {
-+ TLSEXT_TYPE_quic_transport_parameters,
-+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
-+ | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
-+ init_quic_transport_params,
-+ tls_parse_ctos_quic_transport_params, tls_parse_stoc_quic_transport_params,
-+ tls_construct_stoc_quic_transport_params, tls_construct_ctos_quic_transport_params,
-+ final_quic_transport_params,
-+ },
-+#else
-+ INVALID_EXTENSION,
-+#endif
- {
- /* Must be immediately before pre_shared_key */
- TLSEXT_TYPE_padding,
-@@ -1701,3 +1718,15 @@ static int init_post_handshake_auth(SSL *s, unsigned int context)
-
- return 1;
- }
-+
-+#ifndef OPENSSL_NO_QUIC
-+static int init_quic_transport_params(SSL *s, unsigned int context)
-+{
-+ return 1;
-+}
-+
-+static int final_quic_transport_params(SSL *s, unsigned int context, int sent)
-+{
-+ return 1;
-+}
-+#endif
-diff --git a/deps/openssl/openssl/ssl/statem/extensions_clnt.c b/deps/openssl/openssl/ssl/statem/extensions_clnt.c
-index bcce0f1d95..a9f73f07dc 100644
---- a/deps/openssl/openssl/ssl/statem/extensions_clnt.c
-+++ b/deps/openssl/openssl/ssl/statem/extensions_clnt.c
-@@ -1214,7 +1214,28 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
- #endif
- }
-
-+#ifndef OPENSSL_NO_QUIC
-+/* SAME AS tls_construct_stoc_quic_transport_params() */
-+EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt,
-+ unsigned int context, X509 *x,
-+ size_t chainidx)
-+{
-+ if (s->ext.quic_transport_params == NULL
-+ || s->ext.quic_transport_params_len == 0) {
-+ return EXT_RETURN_NOT_SENT;
-+ }
-+
-+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters)
-+ || !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params,
-+ s->ext.quic_transport_params_len)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-+ SSL_F_TLS_CONSTRUCT_CTOS_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
-+ return EXT_RETURN_FAIL;
-+ }
-
-+ return EXT_RETURN_SENT;
-+}
-+#endif
- /*
- * Parse the server's renegotiation binding and abort if it's not right
- */
-@@ -1912,6 +1933,18 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
- return 0;
- }
-
-+#ifndef OPENSSL_NO_QUIC
-+ /*
-+ * QUIC server must send 0xFFFFFFFF or it's a PROTOCOL_VIOLATION
-+ * per draft-ietf-quic-tls-24 S4.5
-+ */
-+ if (s->quic_method != NULL && max_early_data != 0xFFFFFFFF) {
-+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
-+ SSL_R_INVALID_MAX_EARLY_DATA);
-+ return 0;
-+ }
-+#endif
-+
- s->session->ext.max_early_data = max_early_data;
-
- return 1;
-@@ -1999,3 +2032,22 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-
- return 1;
- }
-+#ifndef OPENSSL_NO_QUIC
-+/* SAME AS tls_parse_ctos_quic_transport_params() */
-+int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
-+ X509 *x, size_t chainidx)
-+{
-+ OPENSSL_free(s->ext.peer_quic_transport_params);
-+ s->ext.peer_quic_transport_params = NULL;
-+ s->ext.peer_quic_transport_params_len = 0;
-+
-+ if (!PACKET_memdup(pkt,
-+ &s->ext.peer_quic_transport_params,
-+ &s->ext.peer_quic_transport_params_len)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-+ SSL_F_TLS_PARSE_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ return 1;
-+}
-+#endif
-diff --git a/deps/openssl/openssl/ssl/statem/extensions_srvr.c b/deps/openssl/openssl/ssl/statem/extensions_srvr.c
-index 3b07c6b940..602c9da314 100644
---- a/deps/openssl/openssl/ssl/statem/extensions_srvr.c
-+++ b/deps/openssl/openssl/ssl/statem/extensions_srvr.c
-@@ -1303,6 +1303,26 @@ int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context
- return 1;
- }
-
-+#ifndef OPENSSL_NO_QUIC
-+/* SAME AS tls_parse_stoc_quic_transport_params() */
-+int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
-+ X509 *x, size_t chainidx)
-+{
-+ OPENSSL_free(s->ext.peer_quic_transport_params);
-+ s->ext.peer_quic_transport_params = NULL;
-+ s->ext.peer_quic_transport_params_len = 0;
-+
-+ if (!PACKET_memdup(pkt,
-+ &s->ext.peer_quic_transport_params,
-+ &s->ext.peer_quic_transport_params_len)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-+ SSL_F_TLS_PARSE_CTOS_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ return 1;
-+}
-+#endif
-+
- /*
- * Add the server's renegotiation binding
- */
-@@ -1926,12 +1946,20 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
- size_t chainidx)
- {
- if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
-- if (s->max_early_data == 0)
-+ uint32_t max_early_data = s->max_early_data;
-+
-+ if (max_early_data == 0)
- return EXT_RETURN_NOT_SENT;
-
-+#ifndef OPENSSL_NO_QUIC
-+ /* QUIC server must always send 0xFFFFFFFF, per draft-ietf-quic-tls-24 S4.5 */
-+ if (s->quic_method != NULL)
-+ max_early_data = 0xFFFFFFFF;
-+#endif
-+
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
- || !WPACKET_start_sub_packet_u16(pkt)
-- || !WPACKET_put_bytes_u32(pkt, s->max_early_data)
-+ || !WPACKET_put_bytes_u32(pkt, max_early_data)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
-@@ -1972,3 +2000,26 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
-
- return EXT_RETURN_SENT;
- }
-+
-+#ifndef OPENSSL_NO_QUIC
-+/* SAME AS tls_construct_ctos_quic_transport_params() */
-+EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt,
-+ unsigned int context, X509 *x,
-+ size_t chainidx)
-+{
-+ if (s->ext.quic_transport_params == NULL
-+ || s->ext.quic_transport_params_len == 0) {
-+ return EXT_RETURN_NOT_SENT;
-+ }
-+
-+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_quic_transport_parameters)
-+ || !WPACKET_sub_memcpy_u16(pkt, s->ext.quic_transport_params,
-+ s->ext.quic_transport_params_len)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-+ SSL_F_TLS_CONSTRUCT_STOC_QUIC_TRANSPORT_PARAMS, ERR_R_INTERNAL_ERROR);
-+ return EXT_RETURN_FAIL;
-+ }
-+
-+ return EXT_RETURN_SENT;
-+}
-+#endif
-diff --git a/deps/openssl/openssl/ssl/statem/statem.c b/deps/openssl/openssl/ssl/statem/statem.c
-index 20f5bd584e..0a8acedebf 100644
---- a/deps/openssl/openssl/ssl/statem/statem.c
-+++ b/deps/openssl/openssl/ssl/statem/statem.c
-@@ -575,6 +575,10 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
- * In DTLS we get the whole message in one go - header and body
- */
- ret = dtls_get_message(s, &mt, &len);
-+#ifndef OPENSSL_NO_QUIC
-+ } else if (SSL_IS_QUIC(s)) {
-+ ret = quic_get_message(s, &mt, &len);
-+#endif
- } else {
- ret = tls_get_message_header(s, &mt);
- }
-@@ -604,8 +608,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
- return SUB_STATE_ERROR;
- }
-
-- /* dtls_get_message already did this */
-- if (!SSL_IS_DTLS(s)
-+ /* dtls_get_message/quic_get_message already did this */
-+ if (!SSL_IS_DTLS(s) && !SSL_IS_QUIC(s)
- && s->s3->tmp.message_size > 0
- && !grow_init_buf(s, s->s3->tmp.message_size
- + SSL3_HM_HEADER_LENGTH)) {
-@@ -618,8 +622,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
- /* Fall through */
-
- case READ_STATE_BODY:
-- if (!SSL_IS_DTLS(s)) {
-- /* We already got this above for DTLS */
-+ if (!SSL_IS_DTLS(s) && !SSL_IS_QUIC(s)) {
-+ /* We already got this above for DTLS & QUIC */
- ret = tls_get_message_body(s, &len);
- if (ret == 0) {
- /* Could be non-blocking IO */
-@@ -900,6 +904,15 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
- int statem_flush(SSL *s)
- {
- s->rwstate = SSL_WRITING;
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s)) {
-+ if (!s->quic_method->flush_flight(s)) {
-+ /* NOTE: BIO_flush() does not generate an error */
-+ SSLerr(SSL_F_STATEM_FLUSH, ERR_R_INTERNAL_ERROR);
-+ return 0;
-+ }
-+ } else
-+#endif
- if (BIO_flush(s->wbio) <= 0) {
- return 0;
- }
-diff --git a/deps/openssl/openssl/ssl/statem/statem_clnt.c b/deps/openssl/openssl/ssl/statem/statem_clnt.c
-index 64e392cfbf..aa2f5ad3f4 100644
---- a/deps/openssl/openssl/ssl/statem/statem_clnt.c
-+++ b/deps/openssl/openssl/ssl/statem/statem_clnt.c
-@@ -909,6 +909,14 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
- break;
-
- case TLS_ST_CW_END_OF_EARLY_DATA:
-+#ifndef OPENSSL_NO_QUIC
-+ /* QUIC does not send EndOfEarlyData, draft-ietf-quic-tls-24 S8.3 */
-+ if (s->quic_method != NULL) {
-+ *confunc = NULL;
-+ *mt = SSL3_MT_DUMMY;
-+ break;
-+ }
-+#endif
- *confunc = tls_construct_end_of_early_data;
- *mt = SSL3_MT_END_OF_EARLY_DATA;
- break;
-diff --git a/deps/openssl/openssl/ssl/statem/statem_lib.c b/deps/openssl/openssl/ssl/statem/statem_lib.c
-index 43d6fd5de9..09e7575832 100644
---- a/deps/openssl/openssl/ssl/statem/statem_lib.c
-+++ b/deps/openssl/openssl/ssl/statem/statem_lib.c
-@@ -42,9 +42,23 @@ int ssl3_do_write(SSL *s, int type)
- {
- int ret;
- size_t written = 0;
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s) && type == SSL3_RT_HANDSHAKE) {
-+ ret = s->quic_method->add_handshake_data(s, s->quic_write_level,
-+ (const uint8_t*)&s->init_buf->data[s->init_off],
-+ s->init_num);
-+ if (!ret) {
-+ ret = -1;
-+ /* QUIC can't sent anything out sice the above failed */
-+ SSLerr(SSL_F_SSL3_DO_WRITE, SSL_R_INTERNAL_ERROR);
-+ } else {
-+ written = s->init_num;
-+ }
-+ } else
-+#endif
-+ ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
-+ s->init_num, &written);
-
-- ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
-- s->init_num, &written);
- if (ret < 0)
- return -1;
- if (type == SSL3_RT_HANDSHAKE)
-@@ -1157,6 +1171,7 @@ int tls_get_message_header(SSL *s, int *mt)
-
- do {
- while (s->init_num < SSL3_HM_HEADER_LENGTH) {
-+ /* QUIC: either create a special ssl_read_bytes... or if/else this */
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
- &p[s->init_num],
- SSL3_HM_HEADER_LENGTH - s->init_num,
-diff --git a/deps/openssl/openssl/ssl/statem/statem_local.h b/deps/openssl/openssl/ssl/statem/statem_local.h
-index e27c0c13a2..1551dac952 100644
---- a/deps/openssl/openssl/ssl/statem/statem_local.h
-+++ b/deps/openssl/openssl/ssl/statem/statem_local.h
-@@ -93,6 +93,7 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
- __owur int tls_get_message_header(SSL *s, int *mt);
- __owur int tls_get_message_body(SSL *s, size_t *len);
- __owur int dtls_get_message(SSL *s, int *mt, size_t *len);
-+__owur int quic_get_message(SSL *s, int *mt, size_t *len);
-
- /* Message construction and processing functions */
- __owur int tls_process_initial_server_flight(SSL *s);
-@@ -236,6 +237,10 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx);
- int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
-+#ifndef OPENSSL_NO_QUIC
-+int tls_parse_ctos_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
-+ X509 *x, size_t chainidx);
-+#endif
-
- EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
-@@ -298,6 +303,11 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
- size_t chainidx);
- EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
-+#ifndef OPENSSL_NO_QUIC
-+EXT_RETURN tls_construct_stoc_quic_transport_params(SSL *s, WPACKET *pkt,
-+ unsigned int context, X509 *x,
-+ size_t chainidx);
-+#endif
-
- /* Client Extension processing */
- EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
-@@ -368,6 +378,11 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
- EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
-+#ifndef OPENSSL_NO_QUIC
-+EXT_RETURN tls_construct_ctos_quic_transport_params(SSL *s, WPACKET *pkt,
-+ unsigned int context, X509 *x,
-+ size_t chainidx);
-+#endif
-
- int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
-@@ -413,6 +428,10 @@ int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx);
- int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx);
-+#ifndef OPENSSL_NO_QUIC
-+int tls_parse_stoc_quic_transport_params(SSL *s, PACKET *pkt, unsigned int context,
-+ X509 *x, size_t chainidx);
-+#endif
-
- int tls_handle_alpn(SSL *s);
-
-diff --git a/deps/openssl/openssl/ssl/statem/statem_quic.c b/deps/openssl/openssl/ssl/statem/statem_quic.c
-new file mode 100644
-index 0000000000..eb1a76ec9d
---- /dev/null
-+++ b/deps/openssl/openssl/ssl/statem/statem_quic.c
-@@ -0,0 +1,109 @@
-+/*
-+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
-+ *
-+ * Licensed under the Apache License 2.0 (the "License"). You may not use
-+ * this file except in compliance with the License. You can obtain a copy
-+ * in the file LICENSE in the source distribution or at
-+ * https://www.openssl.org/source/license.html
-+ */
-+
-+#include "../ssl_local.h"
-+#include "statem_local.h"
-+#include "internal/cryptlib.h"
-+
-+#ifdef OPENSSL_NO_QUIC
-+NON_EMPTY_TRANSLATION_UNIT
-+#else
-+
-+int quic_get_message(SSL *s, int *mt, size_t *len)
-+{
-+ size_t l;
-+ QUIC_DATA *qd = s->quic_input_data_head;
-+ uint8_t *p;
-+
-+ if (qd == NULL || (qd->length - qd->offset) != 0) {
-+ s->rwstate = SSL_READING;
-+ *len = 0;
-+ return 0;
-+ }
-+
-+ /* This is where we check for the proper level, not when data is given */
-+ if (qd->level != s->quic_read_level) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE,
-+ SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED);
-+ *len = 0;
-+ return 0;
-+ }
-+
-+ if (!BUF_MEM_grow_clean(s->init_buf, (int)qd->length)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_GET_MESSAGE,
-+ ERR_R_BUF_LIB);
-+ *len = 0;
-+ return 0;
-+ }
-+
-+ /* Copy buffered data */
-+ memcpy(s->init_buf->data, (void*)(qd + 1), qd->length);
-+ s->init_buf->length = qd->length;
-+ s->quic_input_data_head = qd->next;
-+ if (s->quic_input_data_head == NULL)
-+ s->quic_input_data_tail = NULL;
-+ OPENSSL_free(qd);
-+
-+ s->s3->tmp.message_type = *mt = *(s->init_buf->data);
-+ p = (uint8_t*)s->init_buf->data + 1;
-+ n2l3(p, l);
-+ s->init_num = s->s3->tmp.message_size = *len = l;
-+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
-+
-+ /* No CCS in QUIC/TLSv1.3? */
-+ if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
-+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
-+ SSL_F_QUIC_GET_MESSAGE,
-+ SSL_R_CCS_RECEIVED_EARLY);
-+ *len = 0;
-+ return 0;
-+ }
-+
-+ /*
-+ * If receiving Finished, record MAC of prior handshake messages for
-+ * Finished verification.
-+ */
-+ if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
-+ /* SSLfatal() already called */
-+ *len = 0;
-+ return 0;
-+ }
-+
-+ /*
-+ * We defer feeding in the HRR until later. We'll do it as part of
-+ * processing the message
-+ * The TLsv1.3 handshake transcript stops at the ClientFinished
-+ * message.
-+ */
-+#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
-+ /* KeyUpdate and NewSessionTicket do not need to be added */
-+ if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
-+ && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
-+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
-+ || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
-+ || memcmp(hrrrandom,
-+ s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
-+ SSL3_RANDOM_SIZE) != 0) {
-+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
-+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
-+ /* SSLfatal() already called */
-+ *len = 0;
-+ return 0;
-+ }
-+ }
-+ }
-+ if (s->msg_callback)
-+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
-+ (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
-+ s->msg_callback_arg);
-+
-+ return 1;
-+}
-+
-+#endif
-diff --git a/deps/openssl/openssl/ssl/statem/statem_srvr.c b/deps/openssl/openssl/ssl/statem/statem_srvr.c
-index 14cb27e6db..ffa89d3b54 100644
---- a/deps/openssl/openssl/ssl/statem/statem_srvr.c
-+++ b/deps/openssl/openssl/ssl/statem/statem_srvr.c
-@@ -72,7 +72,8 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt)
- return 1;
- }
- break;
-- } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
-+ } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
-+ && !SSL_IS_QUIC(s)) {
- if (mt == SSL3_MT_END_OF_EARLY_DATA) {
- st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
- return 1;
-diff --git a/deps/openssl/openssl/ssl/tls13_enc.c b/deps/openssl/openssl/ssl/tls13_enc.c
-index 86754dc967..a05401bfdc 100644
---- a/deps/openssl/openssl/ssl/tls13_enc.c
-+++ b/deps/openssl/openssl/ssl/tls13_enc.c
-@@ -427,27 +427,140 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
- return 0;
- }
-
--int tls13_change_cipher_state(SSL *s, int which)
--{
- #ifdef CHARSET_EBCDIC
-- static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-- static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-- static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-- static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-- static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-- static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
-- static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
-- static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
-+static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-+static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-+static const unsigned char client_application_traffic[] = {0x63, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-+static const unsigned char server_handshake_traffic[] = {0x73, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-+static const unsigned char server_application_traffic[] = {0x73, 0x20, 0x61, 0x70, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
-+static const unsigned char exporter_master_secret[] = {0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
-+static const unsigned char resumption_master_secret[] = {0x72, 0x65, 0x73, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
-+static const unsigned char early_exporter_master_secret[] = {0x65, 0x20, 0x65, 0x78, 0x70, 0x20, /* master*/ 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00};
- #else
-- static const unsigned char client_early_traffic[] = "c e traffic";
-- static const unsigned char client_handshake_traffic[] = "c hs traffic";
-- static const unsigned char client_application_traffic[] = "c ap traffic";
-- static const unsigned char server_handshake_traffic[] = "s hs traffic";
-- static const unsigned char server_application_traffic[] = "s ap traffic";
-- static const unsigned char exporter_master_secret[] = "exp master";
-- static const unsigned char resumption_master_secret[] = "res master";
-- static const unsigned char early_exporter_master_secret[] = "e exp master";
-+static const unsigned char client_early_traffic[] = "c e traffic";
-+static const unsigned char client_handshake_traffic[] = "c hs traffic";
-+static const unsigned char client_application_traffic[] = "c ap traffic";
-+static const unsigned char server_handshake_traffic[] = "s hs traffic";
-+static const unsigned char server_application_traffic[] = "s ap traffic";
-+static const unsigned char exporter_master_secret[] = "exp master";
-+static const unsigned char resumption_master_secret[] = "res master";
-+static const unsigned char early_exporter_master_secret[] = "e exp master";
- #endif
-+#ifndef OPENSSL_NO_QUIC
-+static int quic_change_cipher_state(SSL *s, int which)
-+{
-+ unsigned char hash[EVP_MAX_MD_SIZE];
-+ size_t hashlen = 0;
-+ int hashleni;
-+ int ret = 0;
-+ const EVP_MD *md = NULL;
-+ OSSL_ENCRYPTION_LEVEL level = ssl_encryption_initial;
-+ int is_handshake = ((which & SSL3_CC_HANDSHAKE) == SSL3_CC_HANDSHAKE);
-+ int is_client_read = ((which & SSL3_CHANGE_CIPHER_CLIENT_READ) == SSL3_CHANGE_CIPHER_CLIENT_READ);
-+ int is_server_write = ((which & SSL3_CHANGE_CIPHER_SERVER_WRITE) == SSL3_CHANGE_CIPHER_SERVER_WRITE);
-+ int is_early = (which & SSL3_CC_EARLY);
-+
-+ md = ssl_handshake_md(s);
-+ if (!ssl3_digest_cached_records(s, 1)
-+ || !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
-+ /* SSLfatal() already called */;
-+ goto err;
-+ }
-+
-+ /* Ensure cast to size_t is safe */
-+ hashleni = EVP_MD_size(md);
-+ if (!ossl_assert(hashleni >= 0)) {
-+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_CHANGE_CIPHER_STATE,
-+ ERR_R_EVP_LIB);
-+ goto err;
-+ }
-+ hashlen = (size_t)hashleni;
-+
-+ if (is_client_read || is_server_write) {
-+ if (is_handshake) {
-+ level = ssl_encryption_handshake;
-+
-+ if (!tls13_hkdf_expand(s, md, s->handshake_secret, client_handshake_traffic,
-+ sizeof(client_handshake_traffic)-1, hash, hashlen,
-+ s->client_hand_traffic_secret, hashlen, 1)
-+ || !ssl_log_secret(s, CLIENT_HANDSHAKE_LABEL, s->client_hand_traffic_secret, hashlen)
-+ || !tls13_derive_finishedkey(s, md, s->client_hand_traffic_secret,
-+ s->client_finished_secret, hashlen)
-+ || !tls13_hkdf_expand(s, md, s->handshake_secret, server_handshake_traffic,
-+ sizeof(server_handshake_traffic)-1, hash, hashlen,
-+ s->server_hand_traffic_secret, hashlen, 1)
-+ || !ssl_log_secret(s, SERVER_HANDSHAKE_LABEL, s->server_hand_traffic_secret, hashlen)
-+ || !tls13_derive_finishedkey(s, md, s->server_hand_traffic_secret,
-+ s->server_finished_secret, hashlen)) {
-+ /* SSLfatal() already called */
-+ goto err;
-+ }
-+ } else {
-+ level = ssl_encryption_application;
-+
-+ if (!tls13_hkdf_expand(s, md, s->master_secret, client_application_traffic,
-+ sizeof(client_application_traffic)-1, hash, hashlen,
-+ s->client_app_traffic_secret, hashlen, 1)
-+ || !ssl_log_secret(s, CLIENT_APPLICATION_LABEL, s->client_app_traffic_secret, hashlen)
-+ || !tls13_hkdf_expand(s, md, s->master_secret, server_application_traffic,
-+ sizeof(server_application_traffic)-1, hash, hashlen,
-+ s->server_app_traffic_secret, hashlen, 1)
-+ || !ssl_log_secret(s, SERVER_APPLICATION_LABEL, s->server_app_traffic_secret, hashlen)) {
-+ /* SSLfatal() already called */
-+ goto err;
-+ }
-+ }
-+ if (!quic_set_encryption_secrets(s, level)) {
-+ /* SSLfatal() already called */
-+ goto err;
-+ }
-+ if (s->server)
-+ s->quic_write_level = level;
-+ else
-+ s->quic_read_level = level;
-+ } else {
-+ /* is_client_write || is_server_read */
-+
-+ if (is_early) {
-+ level = ssl_encryption_early_data;
-+
-+ if (!tls13_hkdf_expand(s, md, s->early_secret, client_early_traffic,
-+ sizeof(client_early_traffic)-1, hash, hashlen,
-+ s->client_early_traffic_secret, hashlen, 1)
-+ || !ssl_log_secret(s, CLIENT_EARLY_LABEL, s->client_early_traffic_secret, hashlen)
-+ || !quic_set_encryption_secrets(s, level)) {
-+ /* SSLfatal() already called */
-+ goto err;
-+ }
-+ } else if (is_handshake) {
-+ level = ssl_encryption_handshake;
-+ } else {
-+ level = ssl_encryption_application;
-+ /*
-+ * We also create the resumption master secret, but this time use the
-+ * hash for the whole handshake including the Client Finished
-+ */
-+ if (!tls13_hkdf_expand(s, md, s->master_secret, resumption_master_secret,
-+ sizeof(resumption_master_secret)-1, hash, hashlen,
-+ s->resumption_master_secret, hashlen, 1)) {
-+ /* SSLfatal() already called */
-+ goto err;
-+ }
-+ }
-+
-+ if (s->server)
-+ s->quic_read_level = level;
-+ else
-+ s->quic_write_level = level;
-+ }
-+
-+ ret = 1;
-+ err:
-+ return ret;
-+}
-+#endif /* OPENSSL_NO_QUIC */
-+int tls13_change_cipher_state(SSL *s, int which)
-+{
- unsigned char *iv;
- unsigned char secret[EVP_MAX_MD_SIZE];
- unsigned char hashval[EVP_MAX_MD_SIZE];
-@@ -463,6 +576,11 @@ int tls13_change_cipher_state(SSL *s, int which)
- const EVP_MD *md = NULL;
- const EVP_CIPHER *cipher = NULL;
-
-+#ifndef OPENSSL_NO_QUIC
-+ if (SSL_IS_QUIC(s))
-+ return quic_change_cipher_state(s, which);
-+#endif
-+
- if (which & SSL3_CC_READ) {
- if (s->enc_read_ctx != NULL) {
- EVP_CIPHER_CTX_reset(s->enc_read_ctx);
-@@ -707,6 +825,7 @@ int tls13_change_cipher_state(SSL *s, int which)
- s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
- else
- s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
-+
- ret = 1;
- err:
- OPENSSL_cleanse(secret, sizeof(secret));
-diff --git a/deps/openssl/openssl/test/sslapitest.c b/deps/openssl/openssl/test/sslapitest.c
-index 5c118108ef..fc06e4faa0 100644
---- a/deps/openssl/openssl/test/sslapitest.c
-+++ b/deps/openssl/openssl/test/sslapitest.c
-@@ -6471,6 +6471,135 @@ static int test_servername(int tst)
- return testresult;
- }
-
-+#ifndef OPENSSL_NO_QUIC
-+
-+static int test_quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *read_secret,
-+ const uint8_t *write_secret, size_t secret_len)
-+{
-+ test_printf_stderr("quic_set_encryption_secrets() %s, lvl=%d, len=%zd\n",
-+ ssl->server ? "server" : "client", level, secret_len);
-+ return 1;
-+}
-+static int test_quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level,
-+ const uint8_t *data, size_t len)
-+{
-+ SSL *peer = (SSL*)SSL_get_app_data(ssl);
-+
-+ test_printf_stderr("quic_add_handshake_data() %s, lvl=%d, *data=0x%02X, len=%zd\n",
-+ ssl->server ? "server" : "client", level, (int)*data, len);
-+ if (!TEST_ptr(peer))
-+ return 0;
-+
-+ if (!TEST_true(SSL_provide_quic_data(peer, level, data, len))) {
-+ ERR_print_errors_fp(stderr);
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+static int test_quic_flush_flight(SSL *ssl)
-+{
-+ test_printf_stderr("quic_flush_flight() %s\n", ssl->server ? "server" : "client");
-+ return 1;
-+}
-+static int test_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert)
-+{
-+ test_printf_stderr("quic_send_alert() %s, lvl=%d, alert=%d\n",
-+ ssl->server ? "server" : "client", level, alert);
-+ return 1;
-+}
-+
-+static SSL_QUIC_METHOD quic_method = {
-+ test_quic_set_encryption_secrets,
-+ test_quic_add_handshake_data,
-+ test_quic_flush_flight,
-+ test_quic_send_alert,
-+};
-+static int test_quic_api(void)
-+{
-+ SSL_CTX *cctx = NULL, *sctx = NULL;
-+ SSL *clientssl = NULL, *serverssl = NULL;
-+ int testresult = 0;
-+ static const char *server_str = "SERVER";
-+ static const char *client_str = "CLIENT";
-+ const uint8_t *peer_str;
-+ size_t peer_str_len;
-+
-+ /* Clean up logging space */
-+ memset(client_log_buffer, 0, sizeof(client_log_buffer));
-+ memset(server_log_buffer, 0, sizeof(server_log_buffer));
-+ client_log_buffer_index = 0;
-+ server_log_buffer_index = 0;
-+ error_writing_log = 0;
-+
-+
-+ if (!TEST_ptr(sctx = SSL_CTX_new(TLS_server_method()))
-+ || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method))
-+ || !TEST_ptr(sctx->quic_method)
-+ || !TEST_ptr(serverssl = SSL_new(sctx))
-+ || !TEST_true(SSL_IS_QUIC(serverssl))
-+ || !TEST_true(SSL_set_quic_method(serverssl, NULL))
-+ || !TEST_false(SSL_IS_QUIC(serverssl))
-+ || !TEST_true(SSL_set_quic_method(serverssl, &quic_method))
-+ || !TEST_true(SSL_IS_QUIC(serverssl)))
-+ goto end;
-+
-+ SSL_CTX_free(sctx);
-+ sctx = NULL;
-+ SSL_free(serverssl);
-+ serverssl = NULL;
-+
-+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
-+ TLS_client_method(),
-+ TLS1_3_VERSION, 0,
-+ &sctx, &cctx, cert, privkey))
-+ || !TEST_true(SSL_CTX_set_quic_method(sctx, &quic_method))
-+ || !TEST_true(SSL_CTX_set_quic_method(cctx, &quic_method))
-+ || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
-+ &clientssl, NULL, NULL))
-+ || !TEST_true(SSL_set_quic_transport_params(serverssl,
-+ (unsigned char*)server_str,
-+ sizeof(server_str)))
-+ || !TEST_true(SSL_set_quic_transport_params(clientssl,
-+ (unsigned char*)client_str,
-+ sizeof(client_str)))
-+ || !TEST_true(SSL_set_app_data(serverssl, clientssl))
-+ || !TEST_true(SSL_set_app_data(clientssl, serverssl))
-+ || !TEST_true(create_ssl_connection(serverssl, clientssl,
-+ SSL_ERROR_NONE))
-+ || !TEST_true(SSL_version(serverssl) == TLS1_3_VERSION)
-+ || !TEST_true(SSL_version(clientssl) == TLS1_3_VERSION)
-+ || !(TEST_int_eq(SSL_quic_read_level(clientssl), ssl_encryption_application))
-+ || !(TEST_int_eq(SSL_quic_read_level(serverssl), ssl_encryption_application))
-+ || !(TEST_int_eq(SSL_quic_write_level(clientssl), ssl_encryption_application))
-+ || !(TEST_int_eq(SSL_quic_write_level(serverssl), ssl_encryption_application)))
-+ goto end;
-+
-+ SSL_get_peer_quic_transport_params(serverssl, &peer_str, &peer_str_len);
-+ if (!TEST_mem_eq(peer_str, peer_str_len, client_str, sizeof(client_str)))
-+ goto end;
-+ SSL_get_peer_quic_transport_params(clientssl, &peer_str, &peer_str_len);
-+ if (!TEST_mem_eq(peer_str, peer_str_len, server_str, sizeof(server_str)))
-+ goto end;
-+
-+ /* Deal with two NewSessionTickets */
-+ if (!TEST_true(SSL_process_quic_post_handshake(clientssl))
-+ || !TEST_true(SSL_process_quic_post_handshake(clientssl)))
-+ goto end;
-+
-+ testresult = 1;
-+
-+end:
-+ SSL_free(serverssl);
-+ SSL_free(clientssl);
-+ SSL_CTX_free(sctx);
-+ SSL_CTX_free(cctx);
-+
-+ return testresult;
-+}
-+#endif
-+
- int setup_tests(void)
- {
- if (!TEST_ptr(certsdir = test_get_argument(0))
-@@ -6590,6 +6719,9 @@ int setup_tests(void)
- ADD_ALL_TESTS(test_client_cert_cb, 2);
- ADD_ALL_TESTS(test_ca_names, 3);
- ADD_ALL_TESTS(test_servername, 10);
-+#ifndef OPENSSL_NO_QUIC
-+ ADD_TEST(test_quic_api);
-+#endif
- return 1;
- }
-
-diff --git a/deps/openssl/openssl/test/ssltestlib.c b/deps/openssl/openssl/test/ssltestlib.c
-index 456afdf471..5f61e63390 100644
---- a/deps/openssl/openssl/test/ssltestlib.c
-+++ b/deps/openssl/openssl/test/ssltestlib.c
-@@ -917,6 +917,11 @@ int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
- if (!create_bare_ssl_connection(serverssl, clientssl, want, 1))
- return 0;
-
-+#ifndef OPENSSL_NO_QUIC
-+ /* QUIC does not support SSL_read_ex */
-+ if (SSL_is_quic(clientssl))
-+ return 1;
-+#endif
- /*
- * We attempt to read some data on the client side which we expect to fail.
- * This will ensure we have received the NewSessionTicket in TLSv1.3 where
-diff --git a/deps/openssl/openssl/test/tls13secretstest.c b/deps/openssl/openssl/test/tls13secretstest.c
-index 52fc2b6673..970c2f4aae 100644
---- a/deps/openssl/openssl/test/tls13secretstest.c
-+++ b/deps/openssl/openssl/test/tls13secretstest.c
-@@ -216,6 +216,13 @@ int ossl_statem_export_early_allowed(SSL *s)
- return 1;
- }
-
-+#ifndef OPENSSL_NO_QUIC
-+int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL level)
-+{
-+ return 1;
-+}
-+#endif
-+
- /* End of mocked out code */
-
- static int test_secret(SSL *s, unsigned char *prk,
-diff --git a/deps/openssl/openssl/util/libssl.num b/deps/openssl/openssl/util/libssl.num
-index 297522c363..15785fe10d 100644
---- a/deps/openssl/openssl/util/libssl.num
-+++ b/deps/openssl/openssl/util/libssl.num
-@@ -498,3 +498,14 @@ SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION:
- SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION:
- SSL_CTX_set_post_handshake_auth 500 1_1_1 EXIST::FUNCTION:
- SSL_get_signature_type_nid 501 1_1_1a EXIST::FUNCTION:
-+SSL_quic_read_level 10094 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_set_quic_transport_params 10095 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_CIPHER_get_prf_nid 10096 1_1_1d EXIST::FUNCTION:
-+SSL_is_quic 10097 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_get_peer_quic_transport_params 10098 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_quic_write_level 10099 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_CTX_set_quic_method 10100 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_set_quic_method 10101 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_quic_max_handshake_flight_len 10102 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_process_quic_post_handshake 10103 1_1_1d EXIST::FUNCTION:QUIC
-+SSL_provide_quic_data 10104 1_1_1d EXIST::FUNCTION:QUIC
-diff --git a/deps/openssl/openssl/util/private.num b/deps/openssl/openssl/util/private.num
-index bc7d967b5d..eb3d409f6e 100644
---- a/deps/openssl/openssl/util/private.num
-+++ b/deps/openssl/openssl/util/private.num
-@@ -91,6 +91,8 @@ custom_ext_free_cb datatype
- custom_ext_parse_cb datatype
- pem_password_cb datatype
- ssl_ct_validation_cb datatype
-+OSSL_ENCRYPTION_LEVEL datatype
-+SSL_QUIC_METHOD datatype
- #
- BIO_append_filename define
- BIO_destroy_bio_pair define
---
-2.26.0.windows.1
-
diff --git a/doc/api/errors.md b/doc/api/errors.md
index d0e0b8794f..6f7b0188d8 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1899,37 +1899,6 @@ Accessing `Object.prototype.__proto__` has been forbidden using
[`Object.setPrototypeOf`][] should be used to get and set the prototype of an
object.
-<a id="ERR_QUIC_FAILED_TO_CREATE_SESSION"></a>
-### `ERR_QUIC_FAILED_TO_CREATE_SESSION`
-
-> Stability: 1 - Experimental
-
-An unspecified failure occured trying to initialize a new `QuicClientSession`.
-
-<a id="ERR_QUIC_INVALID_REMOTE_TRANSPORT_PARAMS"></a>
-### `ERR_QUIC_INVALID_REMOTE_TRANSPORT_PARAMS`
-
-> Stability: 1 - Experimental
-
-An attempt to resume a `QuicClientSession` using remembered remote transport
-parameters failed because the transport parameters were invalid.
-
-<a id="ERR_QUIC_INVALID_TLS_SESSION_TICKET"></a>
-### `ERR_QUIC_INVALID_TLS_SESSION_TICKET`
-
-> Stability: 1 - Experimental
-
-An attempt resume a `QuicClientSession` using a remembered TLS session ticket
-failed because the session ticket was invalid.
-
-<a id="ERR_QUIC_VERSION_NEGOTIATION"></a>
-### `ERR_QUIC_VERSION_NEGOTIATION`
-
-> Stability: 1 - Experimental
-
-A `QuicClientSession` received a version negotiation request from the
-server and was shutdown accordingly.
-
<a id="ERR_REQUIRE_ESM"></a>
### `ERR_REQUIRE_ESM`
diff --git a/doc/api/index.md b/doc/api/index.md
index 391873c161..734d7f1cf0 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -47,7 +47,6 @@
* [Process](process.md)
* [Punycode](punycode.md)
* [Query strings](querystring.md)
-* [QUIC](quic.md)
* [Readline](readline.md)
* [REPL](repl.md)
* [Report](report.md)
diff --git a/doc/api/net.md b/doc/api/net.md
index d489070e24..fd7de2512c 100644
--- a/doc/api/net.md
+++ b/doc/api/net.md
@@ -1237,14 +1237,6 @@ immediately initiates connection with
[`socket.connect(port[, host][, connectListener])`][`socket.connect(port)`],
then returns the `net.Socket` that starts the connection.
-## `net.createQuicSocket([options])`
-<!-- YAML
-added: v15.0.0
--->
-
-Creates and returns a new `QuicSocket`. Please refer to the [QUIC documentation][]
-for details.
-
## `net.createServer([options][, connectionListener])`
<!-- YAML
added: v0.5.0
@@ -1352,7 +1344,6 @@ Returns `true` if input is a version 6 IP address, otherwise returns `false`.
[IPC]: #net_ipc_support
[Identifying paths for IPC connections]: #net_identifying_paths_for_ipc_connections
-[QUIC documentation]: quic.md
[Readable Stream]: stream.md#stream_class_stream_readable
[`'close'`]: #net_event_close
[`'connect'`]: #net_event_connect
diff --git a/doc/api/quic.md b/doc/api/quic.md
deleted file mode 100644
index 78428f7c24..0000000000
--- a/doc/api/quic.md
+++ /dev/null
@@ -1,2518 +0,0 @@
-# QUIC
-
-<!--introduced_in=v15.0.0-->
-
-> Stability: 1 - Experimental
-
-The `net` module provides an implementation of the QUIC protocol. To
-access it, the Node.js binary must be compiled using the
-`--experimental-quic` configuration flag.
-
-```js
-const { createQuicSocket } = require('net');
-```
-
-## Example
-
-```js
-'use strict';
-
-const key = getTLSKeySomehow();
-const cert = getTLSCertSomehow();
-
-const { createQuicSocket } = require('net');
-
-// Create the QUIC UDP IPv4 socket bound to local IP port 1234
-const socket = createQuicSocket({ endpoint: { port: 1234 } });
-
-socket.on('session', async (session) => {
- // A new server side session has been created!
-
- // The peer opened a new stream!
- session.on('stream', (stream) => {
- // Let's say hello
- stream.end('Hello World');
-
- // Let's see what the peer has to say...
- stream.setEncoding('utf8');
- stream.on('data', console.log);
- stream.on('end', () => console.log('stream ended'));
- });
-
- const uni = await session.openStream({ halfOpen: true });
- uni.write('hi ');
- uni.end('from the server!');
-});
-
-// Tell the socket to operate as a server using the given
-// key and certificate to secure new connections, using
-// the fictional 'hello' application protocol.
-(async function() {
- await socket.listen({ key, cert, alpn: 'hello' });
- console.log('The socket is listening for sessions!');
-})();
-
-```
-
-## QUIC basics
-
-QUIC is a UDP-based network transport protocol that includes built-in security
-via TLS 1.3, flow control, error correction, connection migration,
-multiplexing, and more.
-
-Within the Node.js implementation of the QUIC protocol, there are three main
-components: the `QuicSocket`, the `QuicSession` and the `QuicStream`.
-
-### QuicSocket
-
-A `QuicSocket` encapsulates a binding to one or more local UDP ports. It is
-used to send data to, and receive data from, remote endpoints. Once created,
-a `QuicSocket` is associated with a local network address and IP port and can
-act as both a QUIC client and server simultaneously. User code at the
-JavaScript level interacts with the `QuicSocket` object to:
-
-* Query or modified the properties of the local UDP binding;
-* Create client `QuicSession` instances;
-* Wait for server `QuicSession` instances; or
-* Query activity statistics
-
-Unlike the `net.Socket` and `tls.TLSSocket`, a `QuicSocket` instance cannot be
-directly used by user code at the JavaScript level to send or receive data over
-the network.
-
-### Client and server QuicSessions
-
-A `QuicSession` represents a logical connection between two QUIC endpoints (a
-client and a server). In the JavaScript API, each is represented by the
-`QuicClientSession` and `QuicServerSession` specializations.
-
-At any given time, a `QuicSession` exists is one of four possible states:
-
-* `Initial` - Entered as soon as the `QuicSession` is created.
-* `Handshake` - Entered as soon as the TLS 1.3 handshake between the client and
- server begins. The handshake is always initiated by the client.
-* `Ready` - Entered as soon as the TLS 1.3 handshake completes. Once the
- `QuicSession` enters the `Ready` state, it may be used to exchange
- application data using `QuicStream` instances.
-* `Closed` - Entered as soon as the `QuicSession` connection has been
- terminated.
-
-New instances of `QuicClientSession` are created using the `connect()`
-function on a `QuicSocket` as in the example below:
-
-```js
-const { createQuicSocket } = require('net');
-
-// Create a QuicSocket associated with localhost and port 1234
-const socket = createQuicSocket({ endpoint: { port: 1234 } });
-
-(async function() {
- const client = await socket.connect({
- address: 'example.com',
- port: 4567,
- alpn: 'foo'
- });
-})();
-```
-
-As soon as the `QuicClientSession` is created, the `address` provided in
-the connect options will be resolved to an IP address (if necessary), and
-the TLS 1.3 handshake will begin. The `QuicClientSession` cannot be used
-to exchange application data until after the `'secure'` event has been
-emitted by the `QuicClientSession` object, signaling the completion of
-the TLS 1.3 handshake.
-
-```js
-client.on('secure', () => {
- // The QuicClientSession can now be used for application data
-});
-```
-
-New instances of `QuicServerSession` are created internally by the
-`QuicSocket` if it has been configured to listen for new connections
-using the `listen()` method.
-
-```js
-const { createQuicSocket } = require('net');
-
-const key = getTLSKeySomehow();
-const cert = getTLSCertSomehow();
-
-const socket = createQuicSocket();
-
-socket.on('session', (session) => {
- session.on('secure', () => {
- // The QuicServerSession can now be used for application data
- });
-});
-
-(async function() {
- await socket.listen({ key, cert, alpn: 'foo' });
-})();
-```
-
-As with client `QuicSession` instances, the `QuicServerSession` cannot be
-used to exchange application data until the `'secure'` event has been emitted.
-
-### QuicSession and ALPN
-
-QUIC uses the TLS 1.3 [ALPN][] ("Application-Layer Protocol Negotiation")
-extension to identify the application level protocol that is using the QUIC
-connection. Every `QuicSession` instance has an ALPN identifier that *must* be
-specified in either the `connect()` or `listen()` options. ALPN identifiers that
-are known to Node.js (such as the ALPN identifier for HTTP/3) will alter how the
-`QuicSession` and `QuicStream` objects operate internally, but the QUIC
-implementation for Node.js has been designed to allow any ALPN to be specified
-and used.
-
-### QuicStream
-
-Once a `QuicSession` transitions to the `Ready` state, `QuicStream` instances
-may be created and used to exchange application data. On a general level, all
-`QuicStream` instances are simply Node.js Duplex Streams that allow
-bidirectional data flow between the QUIC client and server. However, the
-application protocol negotiated for the `QuicSession` may alter the semantics
-and operation of a `QuicStream` associated with the session. Specifically,
-some features of the `QuicStream` (e.g. headers) are enabled only if the
-application protocol selected is known by Node.js to support those features.
-
-Once the `QuicSession` is ready, a `QuicStream` may be created by either the
-client or server, and may be unidirectional or bidirectional.
-
-The `openStream()` method is used to create a new `QuicStream`:
-
-```js
-// Create a new bidirectional stream
-async function createStreams(session) {
- const stream1 = await session.openStream();
-
- // Create a new unidirectional stream
- const stream2 = await session.openStream({ halfOpen: true });
-}
-```
-
-As suggested by the names, a bidirectional stream allows data to be sent on
-a stream in both directions, by both client and server, regardless of which
-peer opened the stream. A unidirectional stream can be written to only by the
-QuicSession that opened it.
-
-The `'stream'` event is emitted by the `QuicSession` when a new `QuicStream`
-has been initiated by the connected peer:
-
-```js
-session.on('stream', (stream) => {
- if (stream.bidirectional) {
- stream.write('Hello World');
- stream.end();
- }
- stream.on('data', console.log);
- stream.on('end', () => {});
-});
-```
-
-#### QuicStream headers
-
-Some QUIC application protocols (like HTTP/3) use headers.
-
-There are four kinds of headers that the Node.js QUIC implementation
-is capable of handling dependent entirely on known application protocol
-support:
-
-* Informational Headers
-* Initial Headers
-* Trailing Headers
-* Push Headers
-
-These categories correlate exactly with the equivalent HTTP
-concepts:
-
-* Informational Headers: Any response headers transmitted within
- a block of headers using a `1xx` status code.
-* Initial Headers: HTTP request or response headers
-* Trailing Headers: A block of headers that follow the body of a
- request or response.
-* Push Promise Headers: A block of headers included in a promised
- push stream.
-
-If headers are supported by the application protocol in use for
-a given `QuicSession`, the `'initialHeaders'`, `'informationalHeaders'`,
-and `'trailingHeaders'` events will be emitted by the `QuicStream`
-object when headers are received; and the `submitInformationalHeaders()`,
-`submitInitialHeaders()`, and `submitTrailingHeaders()` methods can be
-used to send headers.
-
-## QUIC and HTTP/3
-
-HTTP/3 is an application layer protocol that uses QUIC as the transport.
-
-TBD
-
-## QUIC JavaScript API
-
-### `net.createQuicSocket([options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `options` {Object}
- * `client` {Object} A default configuration for QUIC client sessions created
- using `quicsocket.connect()`.
- * `disableStatelessReset` {boolean} When `true` the `QuicSocket` will not
- send stateless resets. **Default**: `false`.
- * `endpoint` {Object} An object describing the local address to bind to.
- * `address` {string} The local address to bind to. This may be an IPv4 or
- IPv6 address or a host name. If a host name is given, it will be resolved
- to an IP address.
- * `port` {number} The local port to bind to.
- * `type` {string} Can be one of `'udp4'`, `'upd6'`, or `'udp6-only'` to
- use IPv4, IPv6, or IPv6 with dual-stack mode disabled.
- **Default**: `'udp4'`.
- * `lookup` {Function} A [custom DNS lookup function][].
- **Default**: undefined.
- * `maxConnections` {number} The maximum number of total active inbound
- connections.
- * `maxConnectionsPerHost` {number} The maximum number of inbound connections
- allowed per remote host. Default: `100`.
- * `maxStatelessResetsPerHost` {number} The maximum number of stateless
- resets that the `QuicSocket` is permitted to send per remote host.
- Default: `10`.
- * `qlog` {boolean} Whether to enable ['qlog'][] for incoming sessions.
- (For outgoing client sessions, set `client.qlog`.) Default: `false`.
- * `retryTokenTimeout` {number} The maximum number of *seconds* for retry token
- validation. Default: `10` seconds.
- * `server` {Object} A default configuration for QUIC server sessions.
- * `statelessResetSecret` {Buffer|Uint8Array} A 16-byte `Buffer` or
- `Uint8Array` providing the secret to use when generating stateless reset
- tokens. If not specified, a random secret will be generated for the
- `QuicSocket`. **Default**: `undefined`.
- * `validateAddress` {boolean} When `true`, the `QuicSocket` will use explicit
- address validation using a QUIC `RETRY` frame when listening for new server
- sessions. Default: `false`.
-
-The `net.createQuicSocket()` function is used to create new `QuicSocket`
-instances associated with a local UDP address.
-
-### Class: `QuicEndpoint`
-<!-- YAML
-added: v15.0.0
--->
-
-The `QuicEndpoint` wraps a local UDP binding used by a `QuicSocket` to send
-and receive data. A single `QuicSocket` may be bound to multiple
-`QuicEndpoint` instances at any given time.
-
-Users will not create instances of `QuicEndpoint` directly.
-
-#### `quicendpoint.addMembership(address, iface)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `address` {string}
-* `iface` {string}
-
-Tells the kernel to join a multicast group at the given `multicastAddress` and
-`multicastInterface` using the `IP_ADD_MEMBERSHIP` socket option. If the
-`multicastInterface` argument is not specified, the operating system will
-choose one interface and will add membership to it. To add membership to every
-available interface, call `addMembership()` multiple times, once per
-interface.
-
-#### `quicendpoint.address`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: Address
-
-An object containing the address information for a bound `QuicEndpoint`.
-
-The object will contain the properties:
-
-* `address` {string} The local IPv4 or IPv6 address to which the `QuicEndpoint` is
- bound.
-* `family` {string} Either `'IPv4'` or `'IPv6'`.
-* `port` {number} The local IP port to which the `QuicEndpoint` is bound.
-
-If the `QuicEndpoint` is not bound, `quicendpoint.address` is an empty object.
-
-#### `quicendpoint.bind([options])`
-<!-- YAML
-added: v15.0.0
--->
-
-Binds the `QuicEndpoint` if it has not already been bound. User code will
-not typically be responsible for binding a `QuicEndpoint` as the owning
-`QuicSocket` will do that automatically.
-
-* `options` {Object}
- * `signal` {AbortSignal} Optionally allows the `bind()` to be canceled
- using an `AbortController`.
-* Returns: {Promise}
-
-The `quicendpoint.bind()` function returns `Promise` that will be resolved
-with the address once the bind operation is successful.
-
-If the `QuicEndpoint` has been destroyed, or is destroyed while the `Promise`
-is pending, the `Promise` will be rejected with an `ERR_INVALID_STATE` error.
-
-If an `AbortSignal` is specified in the `options` and it is triggered while
-the `Promise` is pending, the `Promise` will be rejected with an `AbortError`.
-
-If `quicendpoint.bind()` is called again while a previously returned `Promise`
-is still pending or has already successfully resolved, the previously returned
-pending `Promise` will be returned. If the additional call to
-`quicendpoint.bind()` contains an `AbortSignal`, the `signal` will be ignored.
-
-#### `quicendpoint.bound`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicEndpoint` is bound to the local UDP port.
-
-#### `quicendpoint.close()`
-<!-- YAML
-added: v15.0.0
--->
-
-Closes and destroys the `QuicEndpoint`. Returns a `Promise` that is resolved
-once the `QuicEndpoint` has been destroyed, or rejects if the `QuicEndpoint`
-is destroyed with an error.
-
-* Returns: {Promise}
-
-The `Promise` cannot be canceled. Once `quicendpoint.close()` is called, the
-`QuicEndpoint` will be destroyed.
-
-#### `quicendpoint.closing`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicEndpoint` is in the process of closing.
-
-#### `quicendpoint.destroy([error])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `error` {Object} An `Error` object.
-
-Closes and destroys the `QuicEndpoint` instance making it unusable.
-
-#### `quicendpoint.destroyed`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicEndpoint` has been destroyed.
-
-#### `quicendpoint.dropMembership(address, iface)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `address` {string}
-* `iface` {string}
-
-Instructs the kernel to leave a multicast group at `multicastAddress` using the
-`IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the
-kernel when the socket is closed or the process terminates, so most apps will
-never have reason to call this.
-
-If `multicastInterface` is not specified, the operating system will attempt to
-drop membership on all valid interfaces.
-
-#### `quicendpoint.fd`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {integer}
-
-The system file descriptor the `QuicEndpoint` is bound to. This property
-is not set on Windows.
-
-#### `quicendpoint.pending`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicEndpoint` is in the process of binding to
-the local UDP port.
-
-#### `quicendpoint.ref()`
-<!-- YAML
-added: v15.0.0
--->
-
-#### `quicendpoint.setBroadcast([on])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `on` {boolean}
-
-Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP
-packets may be sent to a local interface's broadcast address.
-
-#### `quicendpoint.setMulticastInterface(iface)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `iface` {string}
-
-All references to scope in this section are referring to IPv6 Zone Indices,
-which are defined by [RFC 4007][]. In string form, an IP with a scope index
-is written as `'IP%scope'` where scope is an interface name or interface
-number.
-
-Sets the default outgoing multicast interface of the socket to a chosen
-interface or back to system interface selection. The multicastInterface must
-be a valid string representation of an IP from the socket's family.
-
-For IPv4 sockets, this should be the IP configured for the desired physical
-interface. All packets sent to multicast on the socket will be sent on the
-interface determined by the most recent successful use of this call.
-
-For IPv6 sockets, multicastInterface should include a scope to indicate the
-interface as in the examples that follow. In IPv6, individual send calls can
-also use explicit scope in addresses, so only packets sent to a multicast
-address without specifying an explicit scope are affected by the most recent
-successful use of this call.
-
-##### Examples: IPv6 outgoing multicast interface
-<!-- YAML
-added: v15.0.0
--->
-On most systems, where scope format uses the interface name:
-
-```js
-const { createQuicSocket } = require('net');
-const socket = createQuicSocket({ endpoint: { type: 'udp6', port: 1234 } });
-
-socket.on('ready', () => {
- socket.endpoints[0].setMulticastInterface('::%eth1');
-});
-```
-
-On Windows, where scope format uses an interface number:
-
-```js
-const { createQuicSocket } = require('net');
-const socket = createQuicSocket({ endpoint: { type: 'udp6', port: 1234 } });
-
-socket.on('ready', () => {
- socket.endpoints[0].setMulticastInterface('::%2');
-});
-```
-
-##### Example: IPv4 outgoing multicast interface
-<!-- YAML
-added: v15.0.0
--->
-All systems use an IP of the host on the desired physical interface:
-
-```js
-const { createQuicSocket } = require('net');
-const socket = createQuicSocket({ endpoint: { type: 'udp4', port: 1234 } });
-
-socket.on('ready', () => {
- socket.endpoints[0].setMulticastInterface('10.0.0.2');
-});
-```
-
-##### Call results
-
-A call on a socket that is not ready to send or no longer open may throw a
-Not running Error.
-
-If multicastInterface can not be parsed into an IP then an `EINVAL` System
-Error is thrown.
-
-On IPv4, if `multicastInterface` is a valid address but does not match any
-interface, or if the address does not match the family then a System Error
-such as `EADDRNOTAVAIL` or `EPROTONOSUP` is thrown.
-
-On IPv6, most errors with specifying or omitting scope will result in the
-socket continuing to use (or returning to) the system's default interface
-selection.
-
-A socket's address family's ANY address (IPv4 `'0.0.0.0'` or IPv6 `'::'`)
-can be used to return control of the sockets default outgoing interface to
-the system for future multicast packets.
-
-#### `quicendpoint.setMulticastLoopback([on])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `on` {boolean}
-
-Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`,
-multicast packets will also be received on the local interface.
-
-#### `quicendpoint.setMulticastTTL(ttl)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `ttl` {number}
-
-Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for
-"Time to Live", in this context it specifies the number of IP hops that a
-packet is allowed to travel through, specifically for multicast traffic. Each
-router or gateway that forwards a packet decrements the TTL. If the TTL is
-decremented to `0` by a router, it will not be forwarded.
-
-The argument passed to `setMulticastTTL()` is a number of hops between
-`0` and `255`. The default on most systems is `1` but can vary.
-
-#### `quicendpoint.setTTL(ttl)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `ttl` {number}
-
-Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live",
-in this context it specifies the number of IP hops that a packet is allowed to
-travel through. Each router or gateway that forwards a packet decrements the
-TTL. If the TTL is decremented to `0` by a router, it will not be forwarded.
-Changing TTL values is typically done for network probes or when multicasting.
-
-The argument to `setTTL()` is a number of hops between `1` and `255`.
-The default on most systems is `64` but can vary.
-
-#### `quicendpoint.unref()`
-<!-- YAML
-added: v15.0.0
--->
-
-### Class: `QuicSession extends EventEmitter`
-<!-- YAML
-added: v15.0.0
--->
-* Extends: {EventEmitter}
-
-The `QuicSession` is an abstract base class that defines events, methods, and
-properties that are shared by both `QuicClientSession` and `QuicServerSession`.
-
-Users will not create instances of `QuicSession` directly.
-
-#### Event: `'close'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted after the `QuicSession` has been destroyed and is no longer usable.
-
-The `'close'` event will not be emitted more than once.
-
-#### Event: `'error'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted immediately before the `'close'` event if the `QuicSession` was
-destroyed with an error.
-
-The callback will be invoked with a single argument:
-
-* `error` {Object} An `Error` object.
-
-The `'error'` event will not be emitted more than once.
-
-#### Event: `'keylog'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when key material is generated or received by a `QuicSession`
-(typically during or immediately following the handshake process). This keying
-material can be stored for debugging, as it allows captured TLS traffic to be
-decrypted. It may be emitted multiple times per `QuicSession` instance.
-
-The callback will be invoked with a single argument:
-
-* `line` {Buffer} Line of ASCII text, in NSS SSLKEYLOGFILE format.
-
-A typical use case is to append received lines to a common text file, which is
-later used by software (such as Wireshark) to decrypt the traffic:
-
-```js
-const log = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
-// ...
-session.on('keylog', (line) => log.write(line));
-```
-
-The `'keylog'` event will be emitted multiple times.
-
-#### Event: `'pathValidation'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when a path validation result has been determined. This event
-is strictly informational. When path validation is successful, the
-`QuicSession` will automatically update to use the new validated path.
-
-The callback will be invoked with three arguments:
-
-* `result` {string} Either `'failure'` or `'success'`, denoting the status
- of the path challenge.
-* `local` {Object} The local address component of the tested path.
-* `remote` {Object} The remote address component of the tested path.
-
-The `'pathValidation'` event will be emitted multiple times.
-
-#### Event: `'secure'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted after the TLS handshake has been completed.
-
-The callback will be invoked with two arguments:
-
-* `servername` {string} The SNI servername requested by the client.
-* `alpnProtocol` {string} The negotiated ALPN protocol.
-* `cipher` {Object} Information about the selected cipher algorithm.
- * `name` {string} The cipher algorithm name.
- * `version` {string} The TLS version (currently always `'TLSv1.3'`).
-
-These will also be available using the `quicsession.servername`,
-`quicsession.alpnProtocol`, and `quicsession.cipher` properties.
-
-The `'secure'` event will not be emitted more than once.
-
-#### Event: `'stream'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when a new `QuicStream` has been initiated by the connected peer.
-
-The `'stream'` event may be emitted multiple times.
-
-#### `quicsession.ackDelayRetransmitCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of retransmissions caused by delayed acknowledgments.
-
-#### `quicsession.address`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {Object}
- * `address` {string} The local IPv4 or IPv6 address to which the `QuicSession`
- is bound.
- * `family` {string} Either `'IPv4'` or `'IPv6'`.
- * `port` {number} The local IP port to which the `QuicSocket` is bound.
-
-An object containing the local address information for the `QuicSocket` to which
-the `QuicSession` is currently associated.
-
-#### `quicsession.alpnProtocol`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {string}
-
-The ALPN protocol identifier negotiated for this session.
-
-#### `quicsession.authenticated`
-<!--YAML
-added: v15.0.0
--->
-* Type: {boolean}
-
-True if the certificate provided by the peer during the TLS 1.3
-handshake has been verified.
-
-#### `quicsession.authenticationError`
-
-* Type: {Object} An error object
-
-If `quicsession.authenticated` is false, returns an `Error` object
-representing the reason the peer certificate verification failed.
-
-#### `quicsession.bidiStreamCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bidirectional streams created for this `QuicSession`.
-
-#### `quicsession.blockCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of times the `QuicSession` has been blocked from sending
-stream data due to flow control.
-
-Such blocks indicate that transmitted stream data is not being consumed
-quickly enough by the connected peer.
-
-#### `quicsession.bytesInFlight`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of unacknowledged bytes this QUIC endpoint has transmitted
-to the connected peer.
-
-#### `quicsession.bytesReceived`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes received from the peer.
-
-#### `quicsession.bytesSent`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes sent to the peer.
-
-#### `quicsession.cipher`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {Object}
- * `name` {string} The cipher algorithm name.
- * `type` {string} The TLS version (currently always `'TLSv1.3'`).
-
-Information about the cipher algorithm selected for the session.
-
-#### `quicsession.close()`
-<!-- YAML
-added: v15.0.0
--->
-
-Begins a graceful close of the `QuicSession`. Existing `QuicStream` instances
-will be permitted to close naturally. New `QuicStream` instances will not be
-permitted. Once all `QuicStream` instances have closed, the `QuicSession`
-instance will be destroyed. Returns a `Promise` that is resolved once the
-`QuicSession` instance is destroyed.
-
-#### `quicsession.closeCode`
-<!-- YAML
-added: v15.0.0
--->
-* Type: {Object}
- * `code` {number} The error code reported when the `QuicSession` closed.
- * `family` {number} The type of error code reported (`0` indicates a QUIC
- protocol level error, `1` indicates a TLS error, `2` represents an
- application level error.)
-
-#### `quicsession.closing`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicSession` is in the process of a graceful shutdown.
-
-#### `quicsession.destroy([error])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `error` {any}
-
-Destroys the `QuicSession` immediately causing the `close` event to be emitted.
-If `error` is not `undefined`, the `error` event will be emitted immediately
-before the `close` event.
-
-Any `QuicStream` instances that are still opened will be abruptly closed.
-
-#### `quicsession.destroyed`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicSession` has been destroyed.
-
-#### `quicsession.duration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time the `QuicSession` was active.
-
-#### `quicsession.getCertificate()`
-<!-- YAML
-added: v15.0.0
--->
-
-* Returns: {Object} A [Certificate Object][].
-
-Returns an object representing the *local* certificate. The returned object has
-some properties corresponding to the fields of the certificate.
-
-If there is no local certificate, or if the `QuicSession` has been destroyed,
-an empty object will be returned.
-
-#### `quicsession.getPeerCertificate([detailed])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `detailed` {boolean} Include the full certificate chain if `true`, otherwise
- include just the peer's certificate. **Default**: `false`.
-* Returns: {Object} A [Certificate Object][].
-
-Returns an object representing the peer's certificate. If the peer does not
-provide a certificate, or if the `QuicSession` has been destroyed, an empty
-object will be returned.
-
-If the full certificate chain was requested (`details` equals `true`), each
-certificate will include an `issuerCertificate` property containing an object
-representing the issuer's certificate.
-
-#### `quicsession.handshakeAckHistogram`
-<!-- YAML
-added: v15.0.0
--->
-
-TBD
-
-#### `quicsession.handshakeContinuationHistogram`
-<!-- YAML
-added: v15.0.0
--->
-
-TBD
-
-#### `quicsession.handshakeComplete`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the TLS handshake has completed.
-
-#### `quicsession.handshakeConfirmed`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` when the TLS handshake completion has been confirmed.
-
-#### `quicsession.handshakeDuration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time taken to complete the TLS handshake.
-
-#### `quicsession.idleTimeout`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicSession` was closed due to an idle timeout.
-
-#### `quicsession.keyUpdateCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of key update operations that have occurred.
-
-#### `quicsession.latestRTT`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The most recently recorded RTT for this `QuicSession`.
-
-#### `quicsession.lossRetransmitCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of lost-packet retransmissions that have been performed on
-this `QuicSession`.
-
-#### `quicsession.maxDataLeft`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes the `QuicSession` is *currently* allowed to
-send to the connected peer.
-
-#### `quicsession.maxInFlightBytes`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The maximum number of in-flight bytes recorded for this `QuicSession`.
-
-#### `quicsession.maxStreams`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {Object}
- * `uni` {number} The maximum number of unidirectional streams.
- * `bidi` {number} The maximum number of bidirectional streams.
-
-The highest cumulative number of bidirectional and unidirectional streams
-that can currently be opened. The values are set initially by configuration
-parameters when the `QuicSession` is created, then updated over the lifespan
-of the `QuicSession` as the connected peer allows new streams to be created.
-
-#### `quicsession.minRTT`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The minimum RTT recorded so far for this `QuicSession`.
-
-#### `quicsession.openStream([options])`
-<!-- YAML
-added: v15.0.0
--->
-* `options` {Object}
- * `halfOpen` {boolean} Set to `true` to open a unidirectional stream, `false`
- to open a bidirectional stream. **Default**: `true`.
- * `highWaterMark` {number} Total number of bytes that the `QuicStream` may
- buffer internally before the `quicstream.write()` function starts returning
- `false`. Default: `16384`.
- * `defaultEncoding` {string} The default encoding that is used when no
- encoding is specified as an argument to `quicstream.write()`. Default:
- `'utf8'`.
-* Returns: {Promise} containing {QuicStream}
-
-Returns a `Promise` that resolves a new `QuicStream`.
-
-The `Promise` will be rejected if the `QuicSession` has been destroyed, is in
-the process of a graceful shutdown, or the `QuicSession` is otherwise blocked
-from opening a new stream.
-
-#### `quicsession.ping()`
-<!--YAML
-added: v15.0.0
--->
-
-The `ping()` method will trigger the underlying QUIC connection to serialize
-any frames currently pending in the outbound queue if it is able to do so.
-This has the effect of keeping the connection with the peer active and resets
-the idle and retransmission timers. The `ping()` method is a best-effort
-that ignores any errors that may occur during the serialization and send
-operations. There is no return value and there is no way to monitor the status
-of the `ping()` operation.
-
-#### `quicsession.peerInitiatedStreamCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of `QuicStreams` initiated by the connected peer.
-
-#### `quicsession.qlog`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {stream.Readable}
-
-If `qlog` support is enabled for `QuicSession`, the `quicsession.qlog` property
-provides a [`stream.Readable`][] that may be used to access the `qlog` event
-data according to the [qlog standard][]. For client `QuicSessions`, the
-`quicsession.qlog` property will be `undefined` until the `'qlog'` event
-is emitted.
-
-#### `quicsession.remoteAddress`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {Object}
- * `address` {string} The local IPv4 or IPv6 address to which the `QuicSession`
- is connected.
- * `family` {string} Either `'IPv4'` or `'IPv6'`.
- * `port` {number} The local IP port to which the `QuicSocket` is bound.
-
-An object containing the remote address information for the connected peer.
-
-#### `quicsession.selfInitiatedStreamCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of `QuicStream` instances initiated by this `QuicSession`.
-
-#### `quicsession.servername`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {string}
-
-The SNI servername requested for this session by the client.
-
-#### `quicsession.smoothedRTT`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The modified RTT calculated for this `QuicSession`.
-
-#### `quicsession.socket`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {QuicSocket}
-
-The `QuicSocket` the `QuicSession` is associated with.
-
-#### `quicsession.statelessReset`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-True if the `QuicSession` was closed due to QUIC stateless reset.
-
-#### `quicsession.uniStreamCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of unidirectional streams created on this `QuicSession`.
-
-#### `quicsession.updateKey()`
-<!-- YAML
-added: v15.0.0
--->
-
-* Returns: {boolean} `true` if the key update operation is successfully
- initiated.
-
-Initiates QuicSession key update.
-
-An error will be thrown if called before `quicsession.handshakeConfirmed`
-is equal to `true`.
-
-#### `quicsession.usingEarlyData`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-On server `QuicSession` instances, set to `true` on completion of the TLS
-handshake if early data is enabled. On client `QuicSession` instances,
-set to true on handshake completion if early data is enabled *and* was
-accepted by the server.
-
-### Class: `QuicClientSession extends QuicSession`
-<!-- YAML
-added: v15.0.0
--->
-
-* Extends: {QuicSession}
-
-The `QuicClientSession` class implements the client side of a QUIC connection.
-Instances are created using the `quicsocket.connect()` method.
-
-#### Event: `'sessionTicket'`
-<!-- YAML
-added: v15.0.0
--->
-
-The `'sessionTicket'` event is emitted when a new TLS session ticket has been
-generated for the current `QuicClientSession`. The callback is invoked with
-two arguments:
-
-* `sessionTicket` {Buffer} The serialized session ticket.
-* `remoteTransportParams` {Buffer} The serialized remote transport parameters
- provided by the QUIC server.
-
-The `sessionTicket` and `remoteTransportParams` are useful when creating a new
-`QuicClientSession` to more quickly resume an existing session.
-
-The `'sessionTicket'` event may be emitted multiple times.
-
-#### Event: `'qlog'`
-<!-- YAML
-added: v15.0.0
--->
-
-The `'qlog'` event is emitted when the `QuicClientSession` is ready to begin
-providing `qlog` event data. The callback is invoked with a single argument:
-
-* `qlog` {stream.Readable} A [`stream.Readable`][] that is also available using
- the `quicsession.qlog` property.
-
-#### Event: `'usePreferredAddress'`
-<!-- YAML
-added: v15.0.0
--->
-
-The `'usePreferredAddress'` event is emitted when the client `QuicSession`
-is updated to use the server-advertised preferred address. The callback is
-invoked with a single `address` argument:
-
-* `address` {Object}
- * `address` {string} The preferred host name
- * `port` {number} The preferred IP port
- * `type` {string} Either `'udp4'` or `'udp6'`.
-
-This event is purely informational and will be emitted only when
-`preferredAddressPolicy` is set to `'accept'`.
-
-The `'usePreferredAddress'` event will not be emitted more than once.
-
-#### `quicclientsession.ephemeralKeyInfo`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {Object}
-
-An object representing the type, name, and size of parameter of an ephemeral
-key exchange in Perfect Forward Secrecy on a client connection. It is an
-empty object when the key exchange is not ephemeral. The supported types are
-`'DH'` and `'ECDH'`. The `name` property is available only when type is
-`'ECDH'`.
-
-For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`.
-
-#### `quicclientsession.setSocket(socket[, natRebinding])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `socket` {QuicSocket} A `QuicSocket` instance to move this session to.
-* `natRebinding` {boolean} When `true`, indicates that the local address is to
- be changed without triggering address validation. This will be rare and will
- typically be used only to test resiliency in NAT rebind scenarios.
- **Default**: `false`.
-* Returns: {Promise}
-
-Migrates the `QuicClientSession` to the given `QuicSocket` instance. If the new
-`QuicSocket` has not yet been bound to a local UDP port, it will be bound prior
-to attempting the migration.
-
-### Class: `QuicServerSession extends QuicSession`
-<!-- YAML
-added: v15.0.0
--->
-
-* Extends: {QuicSession}
-
-The `QuicServerSession` class implements the server side of a QUIC connection.
-Instances are created internally and are emitted using the `QuicSocket`
-`'session'` event.
-
-### Class: `QuicSocket`
-<!-- YAML
-added: v15.0.0
--->
-
-New instances of `QuicSocket` are created using the `net.createQuicSocket()`
-method, and can be used as both a client and a server.
-
-#### Event: `'busy'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the server busy state has been toggled using
-`quicSocket.serverBusy = true | false`. The callback is invoked with no
-arguments. Use the `quicsocket.serverBusy` property to determine the
-current status. This event is strictly informational.
-
-```js
-const { createQuicSocket } = require('net');
-
-const socket = createQuicSocket();
-
-socket.on('busy', () => {
- if (socket.serverBusy)
- console.log('Server is busy');
- else
- console.log('Server is not busy');
-});
-
-socket.serverBusy = true;
-socket.serverBusy = false;
-```
-
-This `'busy'` event may be emitted multiple times.
-
-#### Event: `'close'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted after the `QuicSocket` has been destroyed and is no longer usable.
-
-The `'close'` event will only ever be emitted once.
-
-#### Event: `'endpointClose'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted after a `QuicEndpoint` associated with the `QuicSocket` closes and
-has been destroyed. The handler will be invoked with two arguments:
-
-* `endpoint` {QuicEndpoint} The `QuicEndpoint` that has been destroyed.
-* `error` {Error} An `Error` object if the `QuicEndpoint` was destroyed because
- of an error.
-
-When all of the `QuicEndpoint` instances associated with a `QuicSocket` have
-closed, the `QuicEndpoint` will also automatically close.
-
-#### Event: `'error'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted before the `'close'` event if the `QuicSocket` was destroyed with an
-`error`.
-
-The `'error'` event will only ever be emitted once.
-
-#### Event: `'listening'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted after `quicsocket.listen()` is called and the `QuicSocket` has started
-listening for incoming `QuicServerSession`s. The callback is invoked with
-no arguments.
-
-The `'listening'` event will only ever be emitted once.
-
-#### Event: `'ready'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted once the `QuicSocket` has been bound to a local UDP port.
-
-The `'ready'` event will only ever be emitted once.
-
-#### Event: `'session'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when a new `QuicServerSession` has been created. The callback is
-invoked with a single argument providing the newly created `QuicServerSession`
-object.
-
-```js
-const { createQuicSocket } = require('net');
-
-const options = getOptionsSomehow();
-const server = createQuicSocket({ server: options });
-
-server.on('session', (session) => {
- // Attach session event listeners.
-});
-
-server.listen();
-```
-
-The `'session'` event will be emitted multiple times.
-
-The `'session'` event handler can be an async function.
-
-If the `'session'` event handler throws an error, or if it returns a `Promise`
-that is rejected, the error will be handled by destroying the `QuicServerSession`
-automatically and emitting a `'sessionError'` event on the `QuicSocket`.
-
-#### Event: `'sessionError'`
-<!--YAML
-added: v15.0.0
--->
-
-Emitted when an error occurs processing an event related to a specific
-`QuicSession` instance. The callback is invoked with two arguments:
-
-* `error` {Error} The error that was either thrown or rejected.
-* `session` {QuicSession} The `QuicSession` instance that was destroyed.
-
-The `QuicSession` instance will have been destroyed by the time the
-`'sessionError'` event is emitted.
-
-```js
-const { createQuicSocket } = require('net');
-
-const options = getOptionsSomehow();
-const server = createQuicSocket({ server: options });
-server.listen();
-
-server.on('session', (session) => {
- throw new Error('boom');
-});
-
-server.on('sessionError', (error, session) => {
- console.log('error:', error.message);
-});
-```
-
-#### `quicsocket.addEndpoint(options)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `options`: {Object} An object describing the local address to bind to.
- * `address` {string} The local address to bind to. This may be an IPv4 or
- IPv6 address or a host name. If a host name is given, it will be resolved
- to an IP address.
- * `port` {number} The local port to bind to.
- * `type` {string} Can be one of `'udp4'`, `'upd6'`, or `'udp6-only'` to
- use IPv4, IPv6, or IPv6 with dual-stack mode disabled.
- **Default**: `'udp4'`.
- * `lookup` {Function} A [custom DNS lookup function][].
- **Default**: undefined.
-* Returns: {QuicEndpoint}
-
-Creates and adds a new `QuicEndpoint` to the `QuicSocket` instance. An
-error will be thrown if `quicsocket.addEndpoint()` is called either after
-the `QuicSocket` has already started binding to the local ports, or after
-the `QuicSocket` has been destroyed.
-
-#### `quicsocket.blockList`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {net.BlockList}
-
-A {net.BlockList} instance used to define rules for remote IPv4 or IPv6
-addresses that this `QuicSocket` is not permitted to interact with. The
-rules can be specified as either specific individual addresses, ranges
-of addresses, or CIDR subnet ranges.
-
-When listening as a server, if a packet is received from a blocked address,
-the packet will be ignored.
-
-When connecting as a client, if the remote IP address is blocked, the
-connection attempt will be rejected.
-
-#### `quicsocket.bound`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Will be `true` if the `QuicSocket` has been successfully bound to a local UDP
-port. Initially the value is `false`.
-
-`QuicSocket` instances are not bound to a local UDP port until the first time
-either `quicsocket.listen()` or `quicsocket.connect()` is called. The `'ready'`
-event will be emitted once the `QuicSocket` has been bound and the value of
-`quicsocket.bound` will become `true`.
-
-Read-only.
-
-#### `quicsocket.boundDuration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time this `QuicSocket` has been bound to a local port.
-
-Read-only.
-
-#### `quicsocket.bytesReceived`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of bytes received by this `QuicSocket`.
-
-Read-only.
-
-#### `quicsocket.bytesSent`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of bytes sent by this `QuicSocket`.
-
-Read-only.
-
-#### `quicsocket.clientSessions`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of client `QuicSession` instances that have been associated
-with this `QuicSocket`.
-
-Read-only.
-
-#### `quicsocket.close()`
-<!-- YAML
-added: v15.0.0
--->
-
-* Returns: {Promise}
-
-Gracefully closes the `QuicSocket`. Existing `QuicSession` instances will be
-permitted to close naturally. New `QuicClientSession` and `QuicServerSession`
-instances will not be allowed. The returns `Promise` will be resolved once
-the `QuicSocket` is destroyed.
-
-#### `quicsocket.connect([options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `options` {Object}
- * `address` {string} The domain name or IP address of the QUIC server
- endpoint.
- * `alpn` {string} An ALPN protocol identifier.
- * `ca` {string|string[]|Buffer|Buffer[]} Optionally override the trusted CA
- certificates. Default is to trust the well-known CAs curated by Mozilla.
- Mozilla's CAs are completely replaced when CAs are explicitly specified
- using this option. The value can be a string or `Buffer`, or an `Array` of
- strings and/or `Buffer`s. Any string or `Buffer` can contain multiple PEM
- CAs concatenated together. The peer's certificate must be chainable to a CA
- trusted by the server for the connection to be authenticated. When using
- certificates that are not chainable to a well-known CA, the certificate's CA
- must be explicitly specified as a trusted or the connection will fail to
- authenticate.
- If the peer uses a certificate that doesn't match or chain to one of the
- default CAs, use the `ca` option to provide a CA certificate that the peer's
- certificate can match or chain to.
- For self-signed certificates, the certificate is its own CA, and must be
- provided.
- For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE",
- "X509 CERTIFICATE", and "CERTIFICATE".
- * `cert` {string|string[]|Buffer|Buffer[]} Cert chains in PEM format. One cert
- chain should be provided per private key. Each cert chain should consist of
- the PEM formatted certificate for a provided private `key`, followed by the
- PEM formatted intermediate certificates (if any), in order, and not
- including the root CA (the root CA must be pre-known to the peer, see `ca`).
- When providing multiple cert chains, they do not have to be in the same
- order as their private keys in `key`. If the intermediate certificates are
- not provided, the peer will not be able to validate the certificate, and the
- handshake will fail.
- * `ciphers` {string} Cipher suite specification, replacing the default. For
- more information, see [modifying the default cipher suite][]. Permitted
- ciphers can be obtained via [`tls.getCiphers()`][]. Cipher names must be
- uppercased in order for OpenSSL to accept them.
- * `clientCertEngine` {string} Name of an OpenSSL engine which can provide the
- client certificate.
- * `crl` {string|string[]|Buffer|Buffer[]} PEM formatted CRLs (Certificate
- Revocation Lists).
- * `defaultEncoding` {string} The default encoding that is used when no
- encoding is specified as an argument to `quicstream.write()`. Default:
- `'utf8'`.
- * `dhparam` {string|Buffer} Diffie Hellman parameters, required for
- [Perfect Forward Secrecy][]. Use `openssl dhparam` to create the parameters.
- The key length must be greater than or equal to 1024 bits, otherwise an
- error will be thrown. It is strongly recommended to use 2048 bits or larger
- for stronger security. If omitted or invalid, the parameters are silently
- discarded and DHE ciphers will not be available.
- * `ecdhCurve` {string} A string describing a named curve or a colon separated
- list of curve NIDs or names, for example `P-521:P-384:P-256`, to use for
- ECDH key agreement. Set to `auto` to select the
- curve automatically. Use [`crypto.getCurves()`][] to obtain a list of
- available curve names. On recent releases, `openssl ecparam -list_curves`
- will also display the name and description of each available elliptic curve.
- **Default:** [`tls.DEFAULT_ECDH_CURVE`][].
- * `highWaterMark` {number} Total number of bytes that the `QuicStream` may
- buffer internally before the `quicstream.write()` function starts returning
- `false`. Default: `16384`.
- * `honorCipherOrder` {boolean} Attempt to use the server's cipher suite
- preferences instead of the client's. When `true`, causes
- `SSL_OP_CIPHER_SERVER_PREFERENCE` to be set in `secureOptions`, see
- [OpenSSL Options][] for more information.
- * `idleTimeout` {number}
- * `key` {string|string[]|Buffer|Buffer[]|Object[]} Private keys in PEM format.
- PEM allows the option of private keys being encrypted. Encrypted keys will
- be decrypted with `options.passphrase`. Multiple keys using different
- algorithms can be provided either as an array of unencrypted key strings or
- buffers, or an array of objects in the form `{pem: <string|buffer>[,
- passphrase: <string>]}`. The object form can only occur in an array.
- `object.passphrase` is optional. Encrypted keys will be decrypted with
- `object.passphrase` if provided, or `options.passphrase` if it is not.
- * `lookup` {Function} A [custom DNS lookup function][].
- **Default**: undefined.
- * `activeConnectionIdLimit` {number} Must be a value between `2` and `8`
- (inclusive). Default: `2`.
- * `congestionAlgorithm` {string} Must be either `'reno'` or `'cubic'`.
- **Default**: `'reno'`.
- * `maxAckDelay` {number}
- * `maxData` {number}
- * `maxUdpPayloadSize` {number}
- * `maxStreamDataBidiLocal` {number}
- * `maxStreamDataBidiRemote` {number}
- * `maxStreamDataUni` {number}
- * `maxStreamsBidi` {number}
- * `maxStreamsUni` {number}
- * `h3` {Object} HTTP/3 Specific Configuration Options
- * `qpackMaxTableCapacity` {number}
- * `qpackBlockedStreams` {number}
- * `maxHeaderListSize` {number}
- * `maxPushes` {number}
- * `ocspHandler` {Function} A function for handling [OCSP responses][].
- * `passphrase` {string} Shared passphrase used for a single private key and/or
- a PFX.
- * `pfx` {string|string[]|Buffer|Buffer[]|Object[]} PFX or PKCS12 encoded
- private key and certificate chain. `pfx` is an alternative to providing
- `key` and `cert` individually. PFX is usually encrypted, if it is,
- `passphrase` will be used to decrypt it. Multiple PFX can be provided either
- as an array of unencrypted PFX buffers, or an array of objects in the form
- `{buf: <string|buffer>[, passphrase: <string>]}`. The object form can only
- occur in an array. `object.passphrase` is optional. Encrypted PFX will be
- decrypted with `object.passphrase` if provided, or `options.passphrase` if
- it is not.
- * `port` {number} The IP port of the remote QUIC server.
- * `preferredAddressPolicy` {string} `'accept'` or `'reject'`. When `'accept'`,
- indicates that the client will automatically use the preferred address
- advertised by the server.
- * `remoteTransportParams` {Buffer|TypedArray|DataView} The serialized remote
- transport parameters from a previously established session. These would
- have been provided as part of the `'sessionTicket'` event on a previous
- `QuicClientSession` object.
- * `qlog` {boolean} Whether to enable ['qlog'][] for this session.
- Default: `false`.
- * `secureOptions` {number} Optionally affect the OpenSSL protocol behavior,
- which is not usually necessary. This should be used carefully if at all!
- Value is a numeric bitmask of the `SSL_OP_*` options from
- [OpenSSL Options][].
- * `servername` {string} The SNI servername.
- * `sessionTicket`: {Buffer|TypedArray|DataView} The serialized TLS Session
- Ticket from a previously established session. These would have been
- provided as part of the `'sessionTicket`' event on a previous
- `QuicClientSession` object.
- * `type`: {string} Identifies the type of UDP socket. The value must either
- be `'udp4'`, indicating UDP over IPv4, or `'udp6'`, indicating UDP over
- IPv6. **Default**: `'udp4'`.
-* Returns: {Promise}
-
-Returns a `Promise` that resolves a new `QuicClientSession`.
-
-#### `quicsocket.destroy([error])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `error` {any}
-
-Destroys the `QuicSocket` then emits the `'close'` event when done. The `'error'`
-event will be emitted after `'close'` if the `error` is not `undefined`.
-
-#### `quicsocket.destroyed`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Will be `true` if the `QuicSocket` has been destroyed.
-
-Read-only.
-
-#### `quicsocket.duration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time this `QuicSocket` has been active,
-
-Read-only.
-
-#### `quicsocket.endpoints`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {QuicEndpoint[]}
-
-An array of `QuicEndpoint` instances associated with the `QuicSocket`.
-
-Read-only.
-
-#### `quicsocket.listen([options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `options` {Object}
- * `alpn` {string} A required ALPN protocol identifier.
- * `ca` {string|string[]|Buffer|Buffer[]} Optionally override the trusted CA
- certificates. Default is to trust the well-known CAs curated by Mozilla.
- Mozilla's CAs are completely replaced when CAs are explicitly specified
- using this option. The value can be a string or `Buffer`, or an `Array` of
- strings and/or `Buffer`s. Any string or `Buffer` can contain multiple PEM
- CAs concatenated together. The peer's certificate must be chainable to a CA
- trusted by the server for the connection to be authenticated. When using
- certificates that are not chainable to a well-known CA, the certificate's CA
- must be explicitly specified as a trusted or the connection will fail to
- authenticate.
- If the peer uses a certificate that doesn't match or chain to one of the
- default CAs, use the `ca` option to provide a CA certificate that the peer's
- certificate can match or chain to.
- For self-signed certificates, the certificate is its own CA, and must be
- provided.
- For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE",
- "X509 CERTIFICATE", and "CERTIFICATE".
- * `cert` {string|string[]|Buffer|Buffer[]} Cert chains in PEM format. One cert
- chain should be provided per private key. Each cert chain should consist of
- the PEM formatted certificate for a provided private `key`, followed by the
- PEM formatted intermediate certificates (if any), in order, and not
- including the root CA (the root CA must be pre-known to the peer, see `ca`).
- When providing multiple cert chains, they do not have to be in the same
- order as their private keys in `key`. If the intermediate certificates are
- not provided, the peer will not be able to validate the certificate, and the
- handshake will fail.
- * `ciphers` {string} Cipher suite specification, replacing the default. For
- more information, see [modifying the default cipher suite][]. Permitted
- ciphers can be obtained via [`tls.getCiphers()`][]. Cipher names must be
- uppercased in order for OpenSSL to accept them.
- * `clientCertEngine` {string} Name of an OpenSSL engine which can provide the
- client certificate.
- * `clientHelloHandler` {Function} An async function that may be used to
- set a {tls.SecureContext} for the given server name at the start of the
- TLS handshake. See [Handling client hello][] for details.
- * `crl` {string|string[]|Buffer|Buffer[]} PEM formatted CRLs (Certificate
- Revocation Lists).
- * `defaultEncoding` {string} The default encoding that is used when no
- encoding is specified as an argument to `quicstream.write()`. Default:
- `'utf8'`.
- * `dhparam` {string|Buffer} Diffie Hellman parameters, required for
- [Perfect Forward Secrecy][]. Use `openssl dhparam` to create the parameters.
- The key length must be greater than or equal to 1024 bits, otherwise an
- error will be thrown. It is strongly recommended to use 2048 bits or larger
- for stronger security. If omitted or invalid, the parameters are silently
- discarded and DHE ciphers will not be available.
- * `earlyData` {boolean} Set to `false` to disable 0RTT early data.
- Default: `true`.
- * `ecdhCurve` {string} A string describing a named curve or a colon separated
- list of curve NIDs or names, for example `P-521:P-384:P-256`, to use for
- ECDH key agreement. Set to `auto` to select the
- curve automatically. Use [`crypto.getCurves()`][] to obtain a list of
- available curve names. On recent releases, `openssl ecparam -list_curves`
- will also display the name and description of each available elliptic curve.
- **Default:** [`tls.DEFAULT_ECDH_CURVE`][].
- * `highWaterMark` {number} Total number of bytes that `QuicStream` instances
- may buffer internally before the `quicstream.write()` function starts
- returning `false`. Default: `16384`.
- * `honorCipherOrder` {boolean} Attempt to use the server's cipher suite
- references instead of the client's. When `true`, causes
- `SSL_OP_CIPHER_SERVER_PREFERENCE` to be set in `secureOptions`, see
- [OpenSSL Options][] for more information.
- * `idleTimeout` {number}
- * `key` {string|string[]|Buffer|Buffer[]|Object[]} Private keys in PEM format.
- PEM allows the option of private keys being encrypted. Encrypted keys will
- be decrypted with `options.passphrase`. Multiple keys using different
- algorithms can be provided either as an array of unencrypted key strings or
- buffers, or an array of objects in the form `{pem: <string|buffer>[,
- passphrase: <string>]}`. The object form can only occur in an array.
- `object.passphrase` is optional. Encrypted keys will be decrypted with
- `object.passphrase` if provided, or `options.passphrase` if it is not.
- * `lookup` {Function} A [custom DNS lookup function][].
- **Default**: undefined.
- * `activeConnectionIdLimit` {number}
- * `congestionAlgorithm` {string} Must be either `'reno'` or `'cubic'`.
- **Default**: `'reno'`.
- * `maxAckDelay` {number}
- * `maxData` {number}
- * `maxUdpPayloadSize` {number}
- * `maxStreamsBidi` {number}
- * `maxStreamsUni` {number}
- * `maxStreamDataBidiLocal` {number}
- * `maxStreamDataBidiRemote` {number}
- * `maxStreamDataUni` {number}
- * `ocspHandler` {Function} A function for handling [OCSP requests][].
- * `passphrase` {string} Shared passphrase used for a single private key
- and/or a PFX.
- * `pfx` {string|string[]|Buffer|Buffer[]|Object[]} PFX or PKCS12 encoded
- private key and certificate chain. `pfx` is an alternative to providing
- `key` and `cert` individually. PFX is usually encrypted, if it is,
- `passphrase` will be used to decrypt it. Multiple PFX can be provided either
- as an array of unencrypted PFX buffers, or an array of objects in the form
- `{buf: <string|buffer>[, passphrase: <string>]}`. The object form can only
- occur in an array. `object.passphrase` is optional. Encrypted PFX will be
- decrypted with `object.passphrase` if provided, or `options.passphrase` if
- it is not.
- * `preferredAddress` {Object}
- * `address` {string}
- * `port` {number}
- * `type` {string} `'udp4'` or `'udp6'`.
- * `requestCert` {boolean} Request a certificate used to authenticate the
- client.
- * `rejectUnauthorized` {boolean} If not `false` the server will reject any
- connection which is not authorized with the list of supplied CAs. This
- option only has an effect if `requestCert` is `true`. Default: `true`.
- * `secureOptions` {number} Optionally affect the OpenSSL protocol behavior,
- which is not usually necessary. This should be used carefully if at all!
- Value is a numeric bitmask of the `SSL_OP_*` options from
- [OpenSSL Options][].
- * `sessionIdContext` {string} Opaque identifier used by servers to ensure
- session state is not shared between applications. Unused by clients.
-* Returns: {Promise}
-
-Listen for new peer-initiated sessions. Returns a `Promise` that is resolved
-once the `QuicSocket` is actively listening.
-
-#### `quicsocket.listenDuration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time this `QuicSocket` has been listening for connections.
-
-Read-only
-
-#### `quicsocket.listening`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the `QuicSocket` is listening for new connections.
-
-Read-only.
-
-#### `quicsocket.packetsIgnored`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of packets received by this `QuicSocket` that have been ignored.
-
-Read-only.
-
-#### `quicsocket.packetsReceived`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of packets successfully received by this `QuicSocket`.
-
-Read-only
-
-#### `quicsocket.packetsSent`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of packets sent by this `QuicSocket`.
-
-Read-only
-
-#### `quicsocket.pending`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Set to `true` if the socket is not yet bound to the local UDP port.
-
-Read-only.
-
-#### `quicsocket.ref()`
-<!-- YAML
-added: v15.0.0
--->
-
-#### `quicsocket.serverBusy`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean} When `true`, the `QuicSocket` will reject new connections.
-
-Setting `quicsocket.serverBusy` to `true` will tell the `QuicSocket`
-to reject all new incoming connection requests using the `SERVER_BUSY` QUIC
-error code. To begin receiving connections again, disable busy mode by setting
-`quicsocket.serverBusy = false`.
-
-#### `quicsocket.serverBusyCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of `QuicSession` instances rejected due to server busy status.
-
-Read-only.
-
-#### `quicsocket.serverSessions`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of server `QuicSession` instances that have been associated with
-this `QuicSocket`.
-
-Read-only.
-
-#### `quicsocket.setDiagnosticPacketLoss(options)`
-<!-- YAML
-added: v15.0.0
--->
-
-* `options` {Object}
- * `rx` {number} A value in the range `0.0` to `1.0` that specifies the
- probability of received packet loss.
- * `tx` {number} A value in the range `0.0` to `1.0` that specifies the
- probability of transmitted packet loss.
-
-The `quicsocket.setDiagnosticPacketLoss()` method is a diagnostic only tool
-that can be used to *simulate* packet loss conditions for this `QuicSocket`
-by artificially dropping received or transmitted packets.
-
-This method is *not* to be used in production applications.
-
-#### `quicsocket.statelessReset`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean} `true` if stateless reset processing is enabled; `false`
- if disabled.
-
-By default, a listening `QuicSocket` will generate stateless reset tokens when
-appropriate. The `disableStatelessReset` option may be set when the
-`QuicSocket` is created to disable generation of stateless resets. The
-`quicsocket.statelessReset` property allows stateless reset to be turned on and
-off dynamically through the lifetime of the `QuicSocket`.
-
-#### `quicsocket.statelessResetCount`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The number of stateless resets that have been sent.
-
-Read-only.
-
-#### `quicsocket.unref();`
-<!-- YAML
-added: v15.0.0
--->
-
-### Class: `QuicStream extends stream.Duplex`
-<!-- YAML
-added: v15.0.0
--->
-
-* Extends: {stream.Duplex}
-
-#### Event: `'blocked'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the `QuicStream` has been prevented from sending queued data for
-the `QuicStream` due to congestion control.
-
-#### Event: `'close'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the `QuicStream` has is completely closed and the underlying
-resources have been freed.
-
-#### Event: `'data'`
-<!-- YAML
-added: v15.0.0
--->
-
-#### Event: `'end'`
-<!-- YAML
-added: v15.0.0
--->
-
-#### Event: `'error'`
-<!-- YAML
-added: v15.0.0
--->
-
-#### Event: `'informationalHeaders'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the `QuicStream` has received a block of informational headers.
-
-Support for headers depends entirely on the QUIC Application used as identified
-by the `alpn` configuration option. In QUIC Applications that support headers,
-informational header blocks typically come before initial headers.
-
-The event handler is invoked with a single argument representing the block of
-Headers as an object.
-
-```js
-stream('informationalHeaders', (headers) => {
- // Use headers
-});
-```
-
-#### Event: `'initialHeaders'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the `QuicStream` has received a block of initial headers.
-
-Support for headers depends entirely on the QUIC Application used as identified
-by the `alpn` configuration option. HTTP/3, for instance, supports two kinds of
-initial headers: request headers for HTTP request messages and response headers
-for HTTP response messages. For HTTP/3 QUIC streams, request and response
-headers are each emitted using the `'initialHeaders'` event.
-
-The event handler is invoked with a single argument representing the block of
-Headers as an object.
-
-```js
-stream('initialHeaders', (headers) => {
- // Use headers
-});
-```
-
-#### Event: `'trailingHeaders'`
-<!-- YAML
-added: v15.0.0
--->
-
-Emitted when the `QuicStream` has received a block of trailing headers.
-
-Support for headers depends entirely on the QUIC Application used as identified
-by the `alpn` configuration option. Trailing headers typically follow any data
-transmitted on the `QuicStream`, and therefore typically emit sometime after the
-last `'data'` event but before the `'close'` event. The precise timing may
-vary from one QUIC application to another.
-
-The event handler is invoked with a single argument representing the block of
-Headers as an object.
-
-```js
-stream('trailingHeaders', (headers) => {
- // Use headers
-});
-```
-
-#### Event: `'readable'`
-<!-- YAML
-added: v15.0.0
--->
-
-#### `quicstream.bidirectional`
-<!--YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-When `true`, the `QuicStream` is bidirectional. Both the readable and
-writable sides of the `QuicStream` `Duplex` are open.
-
-Read-only.
-
-#### `quicstream.bytesReceived`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes received for this `QuicStream`.
-
-Read-only.
-
-#### `quicstream.bytesSent`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes sent by this `QuicStream`.
-
-Read-only.
-
-#### `quicstream.clientInitiated`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Will be `true` if the `QuicStream` was initiated by a `QuicClientSession`
-instance.
-
-Read-only.
-
-#### `quicstream.close()`
-<!-- YAML
-added: v15.0.0
--->
-
-* Returns: {Promise}
-
-Closes the `QuicStream` by ending both sides of the `QuicStream` `Duplex`.
-Returns a `Promise` that is resolved once the `QuicStream` has been destroyed.
-
-#### `quicstream.dataAckHistogram`
-<!-- YAML
-added: v15.0.0
--->
-
-TBD
-
-#### `quicstream.dataRateHistogram`
-<!-- YAML
-added: v15.0.0
--->
-
-TBD
-
-#### `quicstream.dataSizeHistogram`
-<!-- YAML
-added: v15.0.0
--->
-TBD
-
-#### `quicstream.duration`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The length of time the `QuicStream` has been active.
-
-Read-only.
-
-#### `quicstream.finalSize`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The total number of bytes successfully received by the `QuicStream`.
-
-Read-only.
-
-#### `quicstream.id`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The numeric identifier of the `QuicStream`.
-
-Read-only.
-
-#### `quicstream.maxAcknowledgedOffset`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The highest acknowledged data offset received for this `QuicStream`.
-
-Read-only.
-
-#### `quicstream.maxExtendedOffset`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The maximum extended data offset that has been reported to the connected peer.
-
-Read-only.
-
-#### `quicstream.maxReceivedOffset`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {number}
-
-The maximum received offset for this `QuicStream`.
-
-Read-only.
-
-#### `quicstream.pushStream(headers[, options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `headers` {Object} An object representing a block of headers to be
- transmitted with the push promise.
-* `options` {Object}
- * `highWaterMark` {number} Total number of bytes that the `QuicStream` may
- buffer internally before the `quicstream.write()` function starts returning
- `false`. Default: `16384`.
- * `defaultEncoding` {string} The default encoding that is used when no
- encoding is specified as an argument to `quicstream.write()`. Default:
- `'utf8'`.
-
-* Returns: {QuicStream}
-
-If the selected QUIC application protocol supports push streams, then the
-`pushStream()` method will initiate a new push promise and create a new
-unidirectional `QuicStream` object used to fulfill that push.
-
-Currently only HTTP/3 supports the use of `pushStream()`.
-
-If the selected QUIC application protocol does not support push streams, an
-error will be thrown.
-
-#### `quicstream.serverInitiated`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Will be `true` if the `QuicStream` was initiated by a `QuicServerSession`
-instance.
-
-Read-only.
-
-#### `quicstream.session`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {QuicSession}
-
-The `QuicServerSession` or `QuicClientSession` to which the
-`QuicStream` belongs.
-
-Read-only.
-
-#### `quicstream.sendFD(fd[, options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `fd` {number|FileHandle} A readable file descriptor.
-* `options` {Object}
- * `offset` {number} The offset position at which to begin reading.
- Default: `-1`.
- * `length` {number} The amount of data from the fd to send.
- Default: `-1`.
-
-Instead of using a `QuicStream` as a writable stream, send data from a given
-file descriptor.
-
-If `offset` is set to a non-negative number, reading starts from that position
-and the file offset will not be advanced.
-If `length` is set to a non-negative number, it gives the maximum number of
-bytes that are read from the file.
-
-The file descriptor or `FileHandle` is not closed when the stream is closed,
-so it will need to be closed manually once it is no longer needed.
-Using the same file descriptor concurrently for multiple streams
-is not supported and may result in data loss. Re-using a file descriptor
-after a stream has finished is supported.
-
-#### `quicstream.sendFile(path[, options])`
-<!-- YAML
-added: v15.0.0
--->
-
-* `path` {string|Buffer|URL}
-* `options` {Object}
- * `onError` {Function} Callback function invoked in the case of an
- error before send.
- * `offset` {number} The offset position at which to begin reading.
- Default: `-1`.
- * `length` {number} The amount of data from the fd to send.
- Default: `-1`.
-
-Instead of using a `QuicStream` as a writable stream, send data from a given
-file path.
-
-The `options.onError` callback will be called if the file could not be opened.
-If `offset` is set to a non-negative number, reading starts from that position.
-If `length` is set to a non-negative number, it gives the maximum number of
-bytes that are read from the file.
-
-#### `quicstream.submitInformationalHeaders(headers)`
-<!-- YAML
-added: v15.0.0
--->
-* `headers` {Object}
-
-TBD
-
-#### `quicstream.submitInitialHeaders(headers)`
-<!-- YAML
-added: v15.0.0
--->
-* `headers` {Object}
-
-TBD
-
-#### `quicstream.submitTrailingHeaders(headers)`
-<!-- YAML
-added: v15.0.0
--->
-* `headers` {Object}
-
-TBD
-
-#### `quicstream.unidirectional`
-<!-- YAML
-added: v15.0.0
--->
-
-* Type: {boolean}
-
-Will be `true` if the `QuicStream` is unidirectional. Whether the `QuicStream`
-will be readable or writable depends on whether the `quicstream.session` is
-a `QuicClientSession` or `QuicServerSession`, and whether the `QuicStream`
-was initiated locally or remotely.
-
-| `quicstream.session` | `quicstream.serverInitiated` | Readable | Writable |
-| -------------------- | ---------------------------- | -------- | -------- |
-| `QuicClientSession` | `true` | Y | N |
-| `QuicServerSession` | `true` | N | Y |
-| `QuicClientSession` | `false` | N | Y |
-| `QuicServerSession` | `false` | Y | N |
-
-| `quicstream.session` | `quicstream.clientInitiated` | Readable | Writable |
-| -------------------- | ---------------------------- | -------- | -------- |
-| `QuicClientSession` | `true` | N | Y |
-| `QuicServerSession` | `true` | Y | N |
-| `QuicClientSession` | `false` | Y | N |
-| `QuicServerSession` | `false` | N | Y |
-
-Read-only.
-
-## Additional notes
-
-### Custom DNS lookup functions
-
-By default, the QUIC implementation uses the `dns` module's
-[promisified version of `lookup()`][] to resolve domains names
-into IP addresses. For most typical use cases, this will be
-sufficient. However, it is possible to pass a custom `lookup`
-function as an option in several places throughout the QUIC API:
-
-* `net.createQuicSocket()`
-* `quicsocket.addEndpoint()`
-* `quicsocket.connect()`
-* `quicsocket.listen()`
-
-The custom `lookup` function must return a `Promise` that is
-resolved once the lookup is complete. It will be invoked with
-two arguments:
-
-* `address` {string|undefined} The host name to resolve, or
- `undefined` if no host name was provided.
-* `family` {number} One of `4` or `6`, identifying either
- IPv4 or IPv6.
-
-```js
-async function myCustomLookup(address, type) {
- // TODO(@jasnell): Make this example more useful
- return resolveTheAddressSomehow(address, type);
-}
-```
-
-### Online Certificate Status Protocol (OCSP)
-
-The QUIC implementation supports use of OCSP during the TLS 1.3 handshake
-of a new QUIC session.
-
-#### Requests
-
-A `QuicServerSession` can receive and process OCSP requests by setting the
-`ocspHandler` option in the `quicsocket.listen()` function. The value of
-the `ocspHandler` is an async function that must return an object with the
-OCSP response and, optionally, a new {tls.SecureContext} to use during the
-handshake.
-
-The handler function will be invoked with two arguments:
-
-* `type`: {string} Will always be `request` for `QuicServerSession`.
-* `options`: {Object}
- * `servername` {string} The SNI server name.
- * `context` {tls.SecureContext} The `SecureContext` currently used.
-
-```js
-async function ocspServerHandler(type, { servername, context }) {
- // Process the request...
- return { data: Buffer.from('The OCSP response') };
-}
-
-sock.listen({ ocspHandler: ocspServerHandler });
-```
-
-#### Responses
-
-A `QuicClientSession` can receive and process OCSP responses by setting the
-`ocspHandler` option in the `quicsocket.connect()` function. The value of
-the `ocspHandler` is an async function with no expected return value.
-
-The handler function will be invoked with two arguments:
-
-* `type`: {string} Will always be `response` for `QuicClientSession`.
-* `options`: {Object}
- * `data`: {Buffer} The OCSP response provided by the server
-
-```js
-async function ocspClientHandler(type, { data }) {
- console.log(data.toString());
-}
-
-sock.connect({ ocspHandler: ocspClientHandler });
-```
-
-### Handling client hello
-
-When `quicsocket.listen()` is called, a {tls.SecureContext} is created and used
-by default for all new `QuicServerSession` instances. There are times, however,
-when the {tls.SecureContext} to be used for a `QuicSession` can only be
-determined once the client initiates a connection. This is accomplished using
-the `clientHelloHandler` option when calling `quicsocket.listen()`.
-
-The value of `clientHelloHandler` is an async function that is called at the
-start of a new `QuicServerSession`. It is invoked with three arguments:
-
-* `alpn` {string} The ALPN protocol identifier specified by the client.
-* `servername` {string} The SNI server name specified by the client.
-* `ciphers` {string[]} The array of TLS 1.3 ciphers specified by the client.
-
-The `clientHelloHandler` can return a new {tls.SecureContext} object that will
-be used to continue the TLS handshake. If the function returns `undefined`, the
-default {tls.SecureContext} will be used. Returning any other value will cause
-an error to be thrown that will destroy the `QuicServerSession` instance.
-
-```js
-const server = createQuicSocket();
-
-server.listen({
- async clientHelloHandler(alpn, servername, ciphers) {
- console.log(alpn);
- console.log(servername);
- console.log(ciphers);
- }
-});
-```
-
-[ALPN]: https://tools.ietf.org/html/rfc7301
-[Certificate Object]: https://nodejs.org/dist/latest-v12.x/docs/api/tls.html#tls_certificate_object
-[Handling client hello]: #quic_handling_client_hello
-[OCSP requests]: #quic_online_certificate_status_protocol_ocsp
-[OCSP responses]: #quic_online_certificate_status_protocol_ocsp
-[OpenSSL Options]: crypto.md#crypto_openssl_options
-[Perfect Forward Secrecy]: #tls_perfect_forward_secrecy
-[RFC 4007]: https://tools.ietf.org/html/rfc4007
-[`crypto.getCurves()`]: crypto.md#crypto_crypto_getcurves
-[`stream.Readable`]: #stream_class_stream_readable
-[`tls.DEFAULT_ECDH_CURVE`]: #tls_tls_default_ecdh_curve
-[`tls.getCiphers()`]: tls.md#tls_tls_getciphers
-[custom DNS lookup function]: #quic_custom_dns_lookup_functions
-[modifying the default cipher suite]: tls.md#tls_modifying_the_default_tls_cipher_suite
-[promisified version of `lookup()`]: dns.md#dns_dnspromises_lookup_hostname_options
-['qlog']: #quic_quicsession_qlog
-[qlog standard]: https://tools.ietf.org/id/draft-marx-qlog-event-definitions-quic-h3-00.html
diff --git a/doc/guides/maintaining-ngtcp2-nghttp3.md b/doc/guides/maintaining-ngtcp2-nghttp3.md
deleted file mode 100644
index 1fa065f6df..0000000000
--- a/doc/guides/maintaining-ngtcp2-nghttp3.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Maintaining ngtcp2 and nghttp3
-
-The ngtcp2 and nghttp3 libraries form the foundation of the QUIC
-implementation. They are acquired from the [ngtcp2/ngtcp2][] and
-[ngtcp2/nghttp3][] repositories on GitHub.
-
-ngtcp2 and nghttp3 are tightly related. They will typically be
-updated together.
-
-## Updating ngtcp2
-
-Update ngtcp2:
-```bash
-git clone https://github.com/ngtcp2/ngtcp2
-cd ngtcp2
-autoreconf -i
-./configure --enable-lib-only
-cd ..
-cp -R ngtcp2/crypto node/deps/ngtcp2
-cp -R ngtcp2/lib node/deps/ngtcp2
-```
-
-The `autoreconf -i` and `./configure --enable-lib-only` commands
-ensure that the necessary template files (such as version.h.in
-located in lib/includes/ngtcp2/ are processed appropriately.
-
-Check that Node.js still builds and tests.
-
-## Updating nghttp3
-
-Update nghttp3:
-```bash
-git clone https://github.com/ngtcp2/nghttp3
-cd nghttp3
-autoreconf -i
-./configure --enable-lib-only
-cd ..
-cp -R nghttp3/lib node/deps/nghttp3
-```
-
-The `autoreconf -i` and `./configure --enable-lib-only` commands
-ensure that the necessary template files (such as version.h.in
-located in lib/includes/ngtcp2/ are processed appropriately.
-
-Check that Node.js still builds and tests.
-
-## Commiting ngtcp2 and nghttp3
-
-Use: `git add --all deps/ngtcp2` and `git add --all deps/nghttp3`
-
-Commit the changes with a message like
-```text
-deps: update ngtcp2 and nghttp3
-
-Updated as described in doc/guides/maintaining-ngtcp2-nghttp3.md.
-```
-
-[ngtcp2/nghttp3]: https://github.com/ngtcp2/nghttp3
-[ngtcp2/ngtcp2]: https://github.com/ngtcp2/ngtcp2
diff --git a/doc/guides/maintaining-openssl.md b/doc/guides/maintaining-openssl.md
index d4ac9ad429..0d5ed34490 100644
--- a/doc/guides/maintaining-openssl.md
+++ b/doc/guides/maintaining-openssl.md
@@ -6,11 +6,10 @@ If you need to provide updates across all active release lines you will
currently need to generate three PRs as follows:
* a PR for master which is generated following the instructions
- below which include the QUIC patch.
+ below.
* a PR for 14.x following the instruction below based on the
- 14,x branch but skipping the step to apply the QUICK patch.
- This PR should cherry pick back to the active release lines
- except for the 10.x line.
+ 14,x branch. This PR should cherry pick back to the active release
+ lines except for the 10.x line.
* a PR which uses the same commit from the second PR to apply the
updates to the openssl source code, with a new commit generated
by following steps 2 onwards on the 10.x line. This is
@@ -68,28 +67,6 @@ This updates all sources in deps/openssl/openssl by:
$ git commit openssl
```
-#### Updating the QUIC APIs
-
-The APIs to support the QUIC implementation are a port of the BoringSSL
-implementation that has not yet landed in OpenSSL. They must be re-applied
-separately after updating the openssl source as described above. The
-current patch implementation can be found in the `deps/openssl/patches`
-directory in the file `0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch`.
-
-```console
-% git am deps/openssl/patches 0001-deps-add-support-for-BoringSSL-QUIC-APIs.patch
-```
-
-The patch file itself is generated by squashing commits from the
-`OpenSSL_1_1_1d-quic` fork of the Akamai OpenSSL fork located
-[here](https://github.com/akamai/openssl), starting with
-[this commit](https://github.com/akamai/openssl/commit/f910151a5b60eb7b90d274332368226cc67479df),
-then applying additional edits to update the implementation to
-openssl-1.1.1e. As OpenSSL updates are made, additional updates
-to the patch may be necessary to keep the patch in sync.
-
-The patch is currently supported only for openssl-1.1.1e.
-
## 2. Execute `make` in `deps/openssl/config` directory
Use `make` to regenerate all platform dependent files in
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 35b091c185..631f312913 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1341,19 +1341,6 @@ E('ERR_PACKAGE_PATH_NOT_EXPORTED', (pkgPath, subpath, base = undefined) => {
return `Package subpath '${subpath}' is not defined by "exports" in ${
pkgPath}package.json${base ? ` imported from ${base}` : ''}`;
}, Error);
-E('ERR_QUIC_FAILED_TO_CREATE_SESSION', 'Failed to create QuicSession', Error);
-E('ERR_QUIC_INVALID_REMOTE_TRANSPORT_PARAMS',
- 'Invalid remote transport params', Error);
-E('ERR_QUIC_INVALID_TLS_SESSION_TICKET',
- 'Invalid TLS session ticket', Error);
-E('ERR_QUIC_VERSION_NEGOTIATION',
- (version, requestedVersions, supportedVersions) => {
- const requestedVersionsString = ArrayPrototypeJoin(requestedVersions, ', ');
- return 'QUIC session received version negotiation from server. ' +
- `Version: ${version}. Requested: ${requestedVersionsString} ` +
- `Supported: ${ArrayPrototypeJoin(supportedVersions, ', ')}`;
- },
- Error);
E('ERR_REQUIRE_ESM',
(filename, parentPath = null, packageJsonPath = null) => {
let msg = `Must use import to load ES Module: ${filename}`;
diff --git a/lib/internal/quic/core.js b/lib/internal/quic/core.js
deleted file mode 100644
index 0c326872a7..0000000000
--- a/lib/internal/quic/core.js
+++ /dev/null
@@ -1,3326 +0,0 @@
-'use strict';
-
-/* eslint-disable no-use-before-define */
-
-const {
- assertCrypto,
- customInspectSymbol: kInspect,
-} = require('internal/util');
-
-assertCrypto();
-
-const {
- ArrayFrom,
- ArrayPrototypePush,
- BigInt64Array,
- Boolean,
- Error,
- FunctionPrototypeBind,
- FunctionPrototypeCall,
- Map,
- Number,
- Promise,
- PromiseAll,
- PromisePrototypeThen,
- PromisePrototypeCatch,
- PromisePrototypeFinally,
- PromiseReject,
- PromiseResolve,
- ReflectApply,
- SafeSet,
- Symbol,
- SymbolFor,
-} = primordials;
-
-const { Buffer } = require('buffer');
-const { isArrayBufferView } = require('internal/util/types');
-const {
- customInspect,
- getAllowUnauthorized,
- getSocketType,
- setTransportParams,
- toggleListeners,
- validateNumber,
- validateTransportParams,
- validateQuicClientSessionOptions,
- validateQuicSocketOptions,
- validateQuicStreamOptions,
- validateQuicSocketListenOptions,
- validateQuicEndpointOptions,
- validateCreateSecureContextOptions,
- validateQuicSocketConnectOptions,
- QuicStreamSharedState,
- QuicSocketSharedState,
- QuicSessionSharedState,
- QLogStream,
-} = require('internal/quic/util');
-const assert = require('internal/assert');
-const { EventEmitter, once } = require('events');
-const fs = require('fs');
-const fsPromisesInternal = require('internal/fs/promises');
-const { Duplex } = require('stream');
-const {
- createSecureContext: _createSecureContext
-} = require('tls');
-const BlockList = require('internal/blocklist');
-const {
- translatePeerCertificate
-} = require('_tls_common');
-const {
- defaultTriggerAsyncIdScope,
- symbols: {
- async_id_symbol,
- owner_symbol,
- },
-} = require('internal/async_hooks');
-const dgram = require('dgram');
-const internalDgram = require('internal/dgram');
-const {
- assertValidPseudoHeader,
- assertValidPseudoHeaderResponse,
- assertValidPseudoHeaderTrailer,
- mapToHeaders,
-} = require('internal/http2/util');
-
-const {
- constants: {
- UV_UDP_IPV6ONLY,
- UV_UDP_REUSEADDR,
- }
-} = internalBinding('udp_wrap');
-
-const {
- writeGeneric,
- writevGeneric,
- onStreamRead,
- kAfterAsyncWrite,
- kMaybeDestroy,
- kUpdateTimer,
- kHandle,
- setStreamTimeout // eslint-disable-line no-unused-vars
-} = require('internal/stream_base_commons');
-
-const {
- ShutdownWrap,
- kReadBytesOrError,
- streamBaseState
-} = internalBinding('stream_wrap');
-
-const {
- codes: {
- ERR_INVALID_ARG_TYPE,
- ERR_INVALID_STATE,
- ERR_OPERATION_FAILED,
- ERR_QUIC_FAILED_TO_CREATE_SESSION,
- ERR_QUIC_INVALID_REMOTE_TRANSPORT_PARAMS,
- ERR_QUIC_INVALID_TLS_SESSION_TICKET,
- ERR_QUIC_VERSION_NEGOTIATION,
- ERR_TLS_DH_PARAM_SIZE,
- },
- hideStackFrames,
- errnoException,
- exceptionWithHostPort
-} = require('internal/errors');
-
-const { FileHandle } = internalBinding('fs');
-const { StreamPipe } = internalBinding('stream_pipe');
-const { UV_EOF } = internalBinding('uv');
-
-const {
- QuicSocket: QuicSocketHandle,
- QuicEndpoint: QuicEndpointHandle,
- initSecureContext,
- initSecureContextClient,
- createClientSession: _createClientSession,
- openBidirectionalStream: _openBidirectionalStream,
- openUnidirectionalStream: _openUnidirectionalStream,
- setCallbacks,
- constants: {
- AF_INET6,
- NGTCP2_DEFAULT_MAX_PKTLEN,
- IDX_QUIC_SESSION_STATS_CREATED_AT,
- IDX_QUIC_SESSION_STATS_DESTROYED_AT,
- IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT,
- IDX_QUIC_SESSION_STATS_BYTES_RECEIVED,
- IDX_QUIC_SESSION_STATS_BYTES_SENT,
- IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT,
- IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT,
- IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT,
- IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT,
- IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT,
- IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT,
- IDX_QUIC_SESSION_STATS_HANDSHAKE_COMPLETED_AT,
- IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT,
- IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT,
- IDX_QUIC_SESSION_STATS_BLOCK_COUNT,
- IDX_QUIC_SESSION_STATS_MIN_RTT,
- IDX_QUIC_SESSION_STATS_SMOOTHED_RTT,
- IDX_QUIC_SESSION_STATS_LATEST_RTT,
- IDX_QUIC_STREAM_STATS_CREATED_AT,
- IDX_QUIC_STREAM_STATS_DESTROYED_AT,
- IDX_QUIC_STREAM_STATS_BYTES_RECEIVED,
- IDX_QUIC_STREAM_STATS_BYTES_SENT,
- IDX_QUIC_STREAM_STATS_MAX_OFFSET,
- IDX_QUIC_STREAM_STATS_FINAL_SIZE,
- IDX_QUIC_STREAM_STATS_MAX_OFFSET_ACK,
- IDX_QUIC_STREAM_STATS_MAX_OFFSET_RECV,
- IDX_QUIC_SOCKET_STATS_CREATED_AT,
- IDX_QUIC_SOCKET_STATS_DESTROYED_AT,
- IDX_QUIC_SOCKET_STATS_BOUND_AT,
- IDX_QUIC_SOCKET_STATS_LISTEN_AT,
- IDX_QUIC_SOCKET_STATS_BYTES_RECEIVED,
- IDX_QUIC_SOCKET_STATS_BYTES_SENT,
- IDX_QUIC_SOCKET_STATS_PACKETS_RECEIVED,
- IDX_QUIC_SOCKET_STATS_PACKETS_IGNORED,
- IDX_QUIC_SOCKET_STATS_PACKETS_SENT,
- IDX_QUIC_SOCKET_STATS_SERVER_SESSIONS,
- IDX_QUIC_SOCKET_STATS_CLIENT_SESSIONS,
- IDX_QUIC_SOCKET_STATS_STATELESS_RESET_COUNT,
- IDX_QUIC_SOCKET_STATS_SERVER_BUSY_COUNT,
- ERR_FAILED_TO_CREATE_SESSION,
- ERR_INVALID_REMOTE_TRANSPORT_PARAMS,
- ERR_INVALID_TLS_SESSION_TICKET,
- NGTCP2_PATH_VALIDATION_RESULT_FAILURE,
- NGTCP2_NO_ERROR,
- QUIC_ERROR_APPLICATION,
- QUICSERVERSESSION_OPTION_REJECT_UNAUTHORIZED,
- QUICSERVERSESSION_OPTION_REQUEST_CERT,
- QUICCLIENTSESSION_OPTION_REQUEST_OCSP,
- QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY,
- QUICSOCKET_OPTIONS_VALIDATE_ADDRESS,
- QUICSTREAM_HEADERS_KIND_NONE,
- QUICSTREAM_HEADERS_KIND_INFORMATIONAL,
- QUICSTREAM_HEADERS_KIND_INITIAL,
- QUICSTREAM_HEADERS_KIND_TRAILING,
- QUICSTREAM_HEADERS_KIND_PUSH,
- QUICSTREAM_HEADER_FLAGS_NONE,
- QUICSTREAM_HEADER_FLAGS_TERMINAL,
- }
-} = internalBinding('quic');
-
-const {
- Histogram,
- kDestroy: kDestroyHistogram
-} = require('internal/histogram');
-
-const {
- validateAbortSignal,
- validateBoolean,
- validateInteger,
- validateObject,
-} = require('internal/validators');
-
-const emit = EventEmitter.prototype.emit;
-
-const kAddSession = Symbol('kAddSession');
-const kAddStream = Symbol('kAddStream');
-const kBind = Symbol('kBind');
-const kClose = Symbol('kClose');
-const kClientHello = Symbol('kClientHello');
-const kDestroy = Symbol('kDestroy');
-const kEndpointBound = Symbol('kEndpointBound');
-const kEndpointClose = Symbol('kEndpointClose');
-const kHandleOcsp = Symbol('kHandleOcsp');
-const kHandshake = Symbol('kHandshake');
-const kHandshakeComplete = Symbol('kHandshakeComplete');
-const kHandshakePost = Symbol('kHandshakePost');
-const kHeaders = Symbol('kHeaders');
-const kInternalState = Symbol('kInternalState');
-const kInternalClientState = Symbol('kInternalClientState');
-const kInternalServerState = Symbol('kInternalServerState');
-const kListen = Symbol('kListen');
-const kMaybeBind = Symbol('kMaybeBind');
-const kOnFileOpened = Symbol('kOnFileOpened');
-const kOnFileUnpipe = Symbol('kOnFileUnpipe');
-const kOnPipedFileHandleRead = Symbol('kOnPipedFileHandleRead');
-const kReady = Symbol('kReady');
-const kRemoveFromSocket = Symbol('kRemoveFromSocket');
-const kRemoveSession = Symbol('kRemove');
-const kRemoveStream = Symbol('kRemoveStream');
-const kServerBusy = Symbol('kServerBusy');
-const kSetHandle = Symbol('kSetHandle');
-const kSetQLogStream = Symbol('kSetQLogStream');
-const kSetSocket = Symbol('kSetSocket');
-const kStartFilePipe = Symbol('kStartFilePipe');
-const kStreamClose = Symbol('kStreamClose');
-const kStreamOptions = Symbol('kStreamOptions');
-const kStreamReset = Symbol('kStreamReset');
-const kTrackWriteState = Symbol('kTrackWriteState');
-const kUDPHandleForTesting = Symbol('kUDPHandleForTesting');
-const kUsePreferredAddress = Symbol('kUsePreferredAddress');
-const kVersionNegotiation = Symbol('kVersionNegotiation');
-const kWriteGeneric = Symbol('kWriteGeneric');
-
-const kRejections = SymbolFor('nodejs.rejection');
-
-const kSocketUnbound = 0;
-const kSocketPending = 1;
-const kSocketBound = 2;
-const kSocketDestroyed = 3;
-
-let diagnosticPacketLossWarned = false;
-let warnedVerifyHostnameIdentity = false;
-
-let DOMException;
-
-const lazyDOMException = hideStackFrames((message, name) => {
- if (DOMException === undefined)
- DOMException = internalBinding('messaging').DOMException;
- return new DOMException(message, name);
-});
-
-assert(process.versions.ngtcp2 !== undefined);
-
-// Called by the C++ internals when the QuicSocket is closed with
-// or without an error. The only thing left to do is destroy the
-// QuicSocket instance.
-function onSocketClose(err) {
- this[owner_symbol].destroy(err != null ? errnoException(err) : undefined);
-}
-
-// Called by the C++ internals when the server busy state of
-// the QuicSocket has been changed.
-function onSocketServerBusy() {
- this[owner_symbol][kServerBusy]();
-}
-
-// Called by the C++ internals when a new server QuicSession has been created.
-function onSessionReady(handle) {
- const socket = this[owner_symbol];
- const session =
- new QuicServerSession(
- socket,
- handle,
- socket[kStreamOptions]);
- try {
- socket.emit('session', session);
- } catch (error) {
- socket[kRejections](error, 'session', session);
- }
-}
-
-// Called when the C++ QuicSession::Close() method has been called.
-// Synchronously cleanup and destroy the JavaScript QuicSession.
-function onSessionClose(code, family, silent, statelessReset) {
- this[owner_symbol][kDestroy](code, family, silent, statelessReset);
-}
-
-// This callback is invoked at the start of the TLS handshake to provide
-// some basic information about the ALPN, SNI, and Ciphers that are
-// being requested. It is only called if the 'clientHelloHandler' option is
-// specified on listen().
-function onSessionClientHello(alpn, servername, ciphers) {
- PromisePrototypeThen(
- this[owner_symbol][kClientHello](alpn, servername, ciphers),
- (context) => {
- if (context !== undefined && !context?.context)
- throw new ERR_INVALID_ARG_TYPE('context', 'SecureContext', context);
- this.onClientHelloDone(context?.context);
- },
- (error) => this[owner_symbol].destroy(error)
- );
-}
-
-// This callback is only ever invoked for QuicServerSession instances,
-// and is used to trigger OCSP request processing when needed. The
-// user callback must invoke .onCertDone() in order for the
-// TLS handshake to continue.
-function onSessionCert(servername) {
- PromisePrototypeThen(
- this[owner_symbol][kHandleOcsp](servername),
- (data) => {
- if (data !== undefined) {
- if (typeof data === 'string')
- data = Buffer.from(data);
- if (!isArrayBufferView(data)) {
- throw new ERR_INVALID_ARG_TYPE(
- 'data',
- ['string', 'Buffer', 'TypedArray', 'DataView'],
- data);
- }
- }
- this.onCertDone(data);
- },
- (error) => this[owner_symbol].destroy(error)
- );
-}
-
-// This callback is only ever invoked for QuicClientSession instances,
-// and is used to deliver the OCSP response as provided by the server.
-// If the requestOCSP configuration option is false, this will never
-// be called.
-function onSessionStatus(data) {
- PromisePrototypeCatch(
- this[owner_symbol][kHandleOcsp](data),
- (error) => this[owner_symbol].destroy(error)
- );
-}
-
-// Called by the C++ internals when the TLS handshake is completed.
-function onSessionHandshake(
- servername,
- alpn,
- cipher,
- cipherVersion,
- maxPacketLength,
- verifyErrorReason,
- verifyErrorCode,
- earlyData) {
- this[owner_symbol][kHandshake](
- servername,
- alpn,
- cipher,
- cipherVersion,
- maxPacketLength,
- verifyErrorReason,
- verifyErrorCode,
- earlyData);
-}
-
-// Called by the C++ internals when TLS session ticket data is
-// available. This is generally most useful on the client side
-// where the session ticket needs to be persisted for session
-// resumption and 0RTT.
-function onSessionTicket(sessionTicket, transportParams) {
- if (this[owner_symbol]) {
- process.nextTick(FunctionPrototypeBind(
- emit,
- this[owner_symbol],
- 'sessionTicket',
- sessionTicket,
- transportParams
- ));
- }
-}
-
-// Called by the C++ internals when path validation is completed.
-// This is a purely informational event that is emitted only when
-// there is a listener present for the pathValidation event.
-function onSessionPathValidation(res, local, remote) {
- const session = this[owner_symbol];
- if (session) {
- process.nextTick(FunctionPrototypeBind(
- emit,
- session,
- 'pathValidation',
- res === NGTCP2_PATH_VALIDATION_RESULT_FAILURE ? 'failure' : 'success',
- local,
- remote
- ));
- }
-}
-
-function onSessionUsePreferredAddress(address, port, family) {
- const session = this[owner_symbol];
- session[kUsePreferredAddress]({
- address,
- port,
- type: family === AF_INET6 ? 'udp6' : 'udp4'
- });
-}
-
-// Called by the C++ internals to emit a QLog record. This can
-// be called before the QuicSession has been fully initialized,
-// in which case we store a reference and defer emitting the
-// qlog event until after we're initialized.
-function onSessionQlog(handle) {
- const session = this[owner_symbol];
- const stream = new QLogStream(handle);
- if (session)
- session[kSetQLogStream](stream);
- else
- this.qlogStream = stream;
-}
-
-// Called by the C++ internals when a client QuicSession receives
-// a version negotiation response from the server.
-function onSessionVersionNegotiation(
- version,
- requestedVersions,
- supportedVersions) {
- if (this[owner_symbol]) {
- this[owner_symbol][kVersionNegotiation](
- version,
- requestedVersions,
- supportedVersions);
- }
-}
-
-// Called by the C++ internals to emit keylogging details for a
-// QuicSession.
-function onSessionKeylog(line) {
- if (this[owner_symbol]) {
- this[owner_symbol].emit('keylog', line);
- }
-}
-
-// Called by the C++ internals when a new QuicStream has been created.
-function onStreamReady(streamHandle, id, push_id) {
- const session = this[owner_symbol];
-
- // onStreamReady should never be called if the stream is in a closing
- // state because new streams should not have been accepted at the C++
- // level.
- assert(!session.closing);
- const stream = new QuicStream({
- ...session[kStreamOptions],
- writable: !(id & 0b10),
- }, session, streamHandle, push_id);
- process.nextTick(() => {
- try {
- session.emit('stream', stream);
- } catch (error) {
- stream.destroy(error);
- }
- });
-}
-
-// Called by the C++ internals when a stream is closed and
-// needs to be destroyed on the JavaScript side.
-function onStreamClose(id, appErrorCode) {
- this[owner_symbol][kStreamClose](id, appErrorCode);
-}
-
-// Called by the C++ internals when a stream has been reset
-function onStreamReset(id, appErrorCode) {
- this[owner_symbol][kStreamReset](id, appErrorCode);
-}
-
-// Called when an error occurs in a QuicStream
-function onStreamError(streamHandle, error) {
- streamHandle[owner_symbol].destroy(error);
-}
-
-// Called when a block of headers has been fully
-// received for the stream. Not all QuicStreams
-// will support headers. The headers argument
-// here is an Array of name-value pairs.
-function onStreamHeaders(id, headers, kind, push_id) {
- this[owner_symbol][kHeaders](id, headers, kind, push_id);
-}
-
-// When a stream is flow control blocked, causes a blocked event
-// to be emitted. This is a purely informational event.
-function onStreamBlocked() {
- process.nextTick(FunctionPrototypeBind(emit, this[owner_symbol], 'blocked'));
-}
-
-// Register the callbacks with the QUIC internal binding.
-setCallbacks({
- onSocketClose,
- onSocketServerBusy,
- onSessionReady,
- onSessionCert,
- onSessionStatus,
- onSessionClientHello,
- onSessionClose,
- onSessionHandshake,
- onSessionKeylog,
- onSessionQlog,
- onSessionTicket,
- onSessionVersionNegotiation,
- onStreamReady,
- onStreamClose,
- onStreamError,
- onStreamReset,
- onSessionPathValidation,
- onSessionUsePreferredAddress,
- onStreamHeaders,
- onStreamBlocked,
-});
-
-// Creates the SecureContext used by QuicSocket instances that are listening
-// for new connections.
-function createSecureContext(options, init_cb) {
- const sc_options = validateCreateSecureContextOptions(options);
- const { groups, earlyData } = sc_options;
- const sc = _createSecureContext(sc_options);
- init_cb(sc.context, groups, earlyData);
- return sc;
-}
-
-function onNewListener(event) {
- toggleListeners(this[kInternalState].state, event, true);
-}
-
-function onRemoveListener(event) {
- toggleListeners(this[kInternalState].state, event, false);
-}
-
-function getStats(obj, idx) {
- const stats = obj[kHandle]?.stats || obj[kInternalState].stats;
- // If stats is undefined at this point, it's just a bug
- assert(stats);
- return stats[idx];
-}
-
-function addressOrLocalhost(address, type) {
- return address || (type === AF_INET6 ? '::' : '0.0.0.0');
-}
-
-function deferredClosePromise(state) {
- return state.closePromise = PromisePrototypeFinally(
- new Promise((resolve, reject) => {
- state.closePromiseResolve = resolve;
- state.closePromiseReject = reject;
- }),
- () => {
- state.closePromise = undefined;
- state.closePromiseResolve = undefined;
- state.closePromiseReject = undefined;
- }
- );
-}
-
-async function resolvePreferredAddress(lookup, preferredAddress) {
- if (preferredAddress === undefined)
- return {};
- const {
- address,
- port,
- type = 'udp4'
- } = { ...preferredAddress };
- const [typeVal] = getSocketType(type);
- const {
- address: ip
- } = await lookup(address, typeVal === AF_INET6 ? 6 : 4);
- return { ip, port, type };
-}
-
-// QuicEndpoint wraps a UDP socket and is owned
-// by a QuicSocket. It does not exist independently
-// of the QuicSocket.
-class QuicEndpoint {
- [kInternalState] = {
- state: kSocketUnbound,
- bindPromise: undefined,
- closePromise: undefined,
- closePromiseResolve: undefined,
- closePromiseReject: undefined,
- socket: undefined,
- udpSocket: undefined,
- address: undefined,
- ipv6Only: undefined,
- lookup: undefined,
- port: undefined,
- reuseAddr: undefined,
- type: undefined,
- fd: undefined
- };
-
- constructor(socket, options) {
- const {
- address,
- ipv6Only,
- lookup,
- port = 0,
- reuseAddr,
- type,
- preferred,
- } = validateQuicEndpointOptions(options);
- const state = this[kInternalState];
- state.socket = socket;
- state.address = addressOrLocalhost(address, type);
- state.lookup = lookup;
- state.ipv6Only = ipv6Only;
- state.port = port;
- state.reuseAddr = reuseAddr;
- state.type = type;
- state.udpSocket = dgram.createSocket(type === AF_INET6 ? 'udp6' : 'udp4');
-
- // kUDPHandleForTesting is only used in the Node.js test suite to
- // artificially test the endpoint. This code path should never be
- // used in user code.
- if (typeof options[kUDPHandleForTesting] === 'object') {
- state.udpSocket.bind(options[kUDPHandleForTesting]);
- state.state = kSocketBound;
- state.socket[kEndpointBound](this);
- }
- const udpHandle = state.udpSocket[internalDgram.kStateSymbol].handle;
- const handle = new QuicEndpointHandle(socket[kHandle], udpHandle);
- handle[owner_symbol] = this;
- this[kHandle] = handle;
- socket[kHandle].addEndpoint(handle, preferred);
- }
-
- [kInspect](depth, options) {
- return customInspect(this, {
- address: this.address,
- fd: this.fd,
- type: this[kInternalState].type === AF_INET6 ? 'udp6' : 'udp4',
- destroyed: this.destroyed,
- bound: this.bound,
- pending: this.pending,
- }, depth, options);
- }
-
- bind(options) {
- const state = this[kInternalState];
- if (state.bindPromise !== undefined)
- return state.bindPromise;
-
- return state.bindPromise = PromisePrototypeFinally(this[kBind](), () => {
- state.bindPromise = undefined;
- });
- }
-
- // Binds the QuicEndpoint to the local port. Returns a Promise
- // that is resolved once the QuicEndpoint binds, or rejects if
- // binding was not successful. Calling bind() multiple times
- // before the Promise is resolved will return the same Promise.
- // Calling bind() after the endpoint is already bound will
- // immediately return a resolved promise. Calling bind() after
- // the endpoint has been destroyed will cause the Promise to
- // be rejected.
- async [kBind](options) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
-
- if (state.state !== kSocketUnbound)
- return this.address;
-
- const { signal } = { ...options };
- validateAbortSignal(signal, 'options.signal');
-
- // If an AbortSignal was passed in, check to make sure it is not already
- // aborted before we continue on to do any work.
- if (signal && signal.aborted)
- throw new lazyDOMException('The operation was aborted', 'AbortError');
-
- state.state = kSocketPending;
-
- const {
- address: ip
- } = await state.lookup(state.address, state.type === AF_INET6 ? 6 : 4);
-
- // It's possible for the QuicEndpoint to have been destroyed while
- // we were waiting for the DNS lookup to complete. If so, reject
- // the Promise.
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint was destroyed');
-
- // If an AbortSignal was passed in, check to see if it was triggered
- // while we were waiting.
- if (signal && signal.aborted) {
- state.state = kSocketUnbound;
- throw new lazyDOMException('The operation was aborted', 'AbortError');
- }
-
- // From here on, any errors are fatal for the QuicEndpoint. Keep in
- // mind that this means that the Bind Promise will be rejected *and*
- // the QuicEndpoint will be destroyed with an error.
- try {
- const udpHandle = state.udpSocket[internalDgram.kStateSymbol].handle;
- if (udpHandle == null) {
- // It's not clear what cases trigger this but it is possible.
- throw new ERR_OPERATION_FAILED('Acquiring UDP socket handle failed');
- }
-
- const flags =
- (state.reuseAddr ? UV_UDP_REUSEADDR : 0) |
- (state.ipv6Only ? UV_UDP_IPV6ONLY : 0);
-
- const ret = udpHandle.bind(ip, state.port, flags);
- if (ret)
- throw exceptionWithHostPort(ret, 'bind', ip, state.port);
-
- // On Windows, the fd will be meaningless, but we always record it.
- state.fd = udpHandle.fd;
- state.state = kSocketBound;
-
- return this.address;
- } catch (error) {
- this.destroy(error);
- throw error;
- }
- }
-
- destroy(error) {
- if (this.destroyed)
- return;
-
- const state = this[kInternalState];
- state.state = kSocketDestroyed;
-
- const handle = this[kHandle];
- if (handle === undefined)
- return;
-
- this[kHandle] = undefined;
- handle[owner_symbol] = undefined;
- // Calling waitForPendingCallbacks starts the process of
- // closing down the QuicEndpoint. Once all pending writes
- // to the underlying libuv udp handle have completed, the
- // ondone callback will be invoked, triggering the UDP
- // socket to be closed. Once it is closed, we notify
- // the QuicSocket that this QuicEndpoint has been closed,
- // allowing it to be freed.
- handle.ondone = () => {
- state.udpSocket.close((err) => {
- if (err) error = err;
- if (error && typeof state.closePromiseReject === 'function')
- state.closePromiseReject(error);
- else if (typeof state.closePromiseResolve === 'function')
- state.closePromiseResolve();
- state.socket[kEndpointClose](this, error);
- });
- };
- handle.waitForPendingCallbacks();
- }
-
- // Closes the QuicEndpoint. Returns a Promise that is resolved
- // once the QuicEndpoint closes, or rejects if it closes with
- // an error. Calling close() multiple times before the Promise
- // is resolved will return the same Promise. Calling close()
- // after will return a rejected Promise.
- close() {
- return this[kInternalState].closePromise || this[kClose]();
- }
-
- [kClose]() {
- if (this.destroyed) {
- return PromiseReject(
- new ERR_INVALID_STATE('QuicEndpoint is already destroyed'));
- }
- const promise = deferredClosePromise(this[kInternalState]);
- this.destroy();
- return promise;
- }
-
- // If the QuicEndpoint is bound, returns an object detailing
- // the local IP address, port, and address type to which it
- // is bound. Otherwise, returns an empty object.
- get address() {
- const state = this[kInternalState];
- if (state.state !== kSocketDestroyed) {
- try {
- return state.udpSocket.address();
- } catch (err) {
- if (err.code === 'EBADF') {
- // If there is an EBADF error, the socket is not bound.
- // Return empty object. Else, rethrow the error because
- // something else bad happened.
- return {};
- }
- throw err;
- }
- }
- return {};
- }
-
- // On Windows, this always returns undefined.
- get fd() {
- return this[kInternalState].fd >= 0 ?
- this[kInternalState].fd : undefined;
- }
-
- // True if the QuicEndpoint has been destroyed and is
- // no longer usable.
- get destroyed() {
- return this[kInternalState].state === kSocketDestroyed;
- }
-
- // True if binding has been initiated and is in progress.
- get pending() {
- return this[kInternalState].state === kSocketPending;
- }
-
- // True if the QuicEndpoint has been bound to the localUDP port.
- get bound() {
- return this[kInternalState].state === kSocketBound;
- }
-
- setTTL(ttl) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.setTTL(ttl);
- return this;
- }
-
- setMulticastTTL(ttl) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.setMulticastTTL(ttl);
- return this;
- }
-
- setBroadcast(on = true) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.setBroadcast(on);
- return this;
- }
-
- setMulticastLoopback(on = true) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.setMulticastLoopback(on);
- return this;
- }
-
- setMulticastInterface(iface) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.setMulticastInterface(iface);
- return this;
- }
-
- addMembership(address, iface) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.addMembership(address, iface);
- return this;
- }
-
- dropMembership(address, iface) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.dropMembership(address, iface);
- return this;
- }
-
- ref() {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.ref();
- return this;
- }
-
- unref() {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicEndpoint is already destroyed');
- state.udpSocket.unref();
- return this;
- }
-}
-
-// QuicSocket wraps a UDP socket plus the associated TLS context and QUIC
-// Protocol state. There may be *multiple* QUIC connections (QuicSession)
-// associated with a single QuicSocket.
-class QuicSocket extends EventEmitter {
- [kInternalState] = {
- alpn: undefined,
- bindPromise: undefined,
- blockList: undefined,
- client: undefined,
- closePromise: undefined,
- closePromiseResolve: undefined,
- closePromiseReject: undefined,
- defaultEncoding: undefined,
- endpoints: new SafeSet(),
- highWaterMark: undefined,
- listenPending: false,
- listenPromise: undefined,
- lookup: undefined,
- ocspHandler: undefined,
- clientHelloHandler: undefined,
- server: undefined,
- serverSecureContext: undefined,
- sessions: new SafeSet(),
- state: kSocketUnbound,
- sharedState: undefined,
- stats: undefined,
- };
-
- constructor(options) {
- const {
- endpoint,
-
- // Default configuration for QuicClientSessions
- client,
-
- // The maximum number of connections
- maxConnections,
-
- // The maximum number of connections per host
- maxConnectionsPerHost,
-
- // The maximum number of stateless resets per host
- maxStatelessResetsPerHost,
-
- // The maximum number of seconds for retry token
- retryTokenTimeout,
-
- // The DNS lookup function
- lookup,
-
- // Default configuration for QuicServerSessions
- server,
-
- // True if address verification should be used.
- validateAddress,
-
- // Whether qlog should be enabled for sessions
- qlog,
-
- // Stateless reset token secret (16 byte buffer)
- statelessResetSecret,
-
- // When true, stateless resets will not be sent (default false)
- disableStatelessReset,
- } = validateQuicSocketOptions(options);
- super({ captureRejections: true });
-
- const state = this[kInternalState];
-
- state.client = client;
- state.server = server;
- state.lookup = lookup;
-
- let socketOptions = 0;
- if (validateAddress)
- socketOptions |= (1 << QUICSOCKET_OPTIONS_VALIDATE_ADDRESS);
-
- this[kSetHandle](
- new QuicSocketHandle(
- socketOptions,
- retryTokenTimeout,
- maxConnections,
- maxConnectionsPerHost,
- maxStatelessResetsPerHost,
- qlog,
- statelessResetSecret,
- disableStatelessReset));
-
- this.addEndpoint({ ...endpoint, preferred: true });
- }
-
- [kRejections](err, eventname, ...args) {
- switch (eventname) {
- case 'session':
- const session = args[0];
- session.destroy(err);
- process.nextTick(() => {
- this.emit('sessionError', err, session);
- });
- return;
- default:
- // Fall through
- }
- this.destroy(err);
- }
-
- get [kStreamOptions]() {
- const state = this[kInternalState];
- return {
- highWaterMark: state.highWaterMark,
- defaultEncoding: state.defaultEncoding,
- ocspHandler: state.ocspHandler,
- clientHelloHandler: state.clientHelloHandler,
- context: state.serverSecureContext,
- };
- }
-
- [kSetHandle](handle) {
- this[kHandle] = handle;
- if (handle !== undefined) {
- handle[owner_symbol] = this;
- this[async_id_symbol] = handle.getAsyncId();
- this[kInternalState].sharedState =
- new QuicSocketSharedState(handle.state);
- this[kInternalState].blockList = new BlockList(handle.blockList);
- } else {
- this[kInternalState].sharedState = undefined;
- this[kInternalState].blockList = undefined;
- }
- }
-
- [kInspect](depth, options) {
- const state = this[kInternalState];
- return customInspect(this, {
- endpoints: this.endpoints,
- sessions: ArrayFrom(state.sessions),
- bound: this.bound,
- pending: this.pending,
- closing: this.closing,
- destroyed: this.destroyed,
- listening: this.listening,
- serverBusy: this.serverBusy,
- statelessResetDisabled: this.statelessResetDisabled,
- }, depth, options);
- }
-
- [kAddSession](session) {
- this[kInternalState].sessions.add(session);
- }
-
- [kRemoveSession](session) {
- const state = this[kInternalState];
- state.sessions.delete(session);
- if (this.closing && state.sessions.size === 0)
- this.destroy();
- }
-
- [kMaybeBind](options) {
- const state = this[kInternalState];
- if (state.bindPromise !== undefined)
- return state.bindPromise;
-
- return state.bindPromise = PromisePrototypeFinally(
- this[kBind](options),
- () => {
- state.bindPromise = undefined;
- }
- );
- }
-
- async [kBind](options) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
-
- const state = this[kInternalState];
- if (state.state === kSocketBound)
- return;
-
- const { signal } = { ...options };
- validateAbortSignal(signal, 'options.signal');
-
- // If an AbotSignal was passed in, check to make sure it is not already
- // aborted before we continue on to do any work.
- if (signal && signal.aborted)
- throw new lazyDOMException('The operation was aborted', 'AbortError');
-
- state.state = kSocketPending;
-
- const binds = [];
- for (const endpoint of state.endpoints)
- ArrayPrototypePush(binds, endpoint.bind({ signal }));
-
- await PromiseAll(binds);
-
- // It it's possible that the QuicSocket was destroyed while we were
- // waiting. Check to make sure.
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
-
- // Any errors from this point on are fatal for the QuicSocket.
- try {
- // If an AbortSignal is used and it has been triggered, our
- // only recourse at this point is to destroy() the QuicSocket.
- // Some number of endpoints may have successfully bound, while
- // others have not
- if (signal && signal.aborted)
- throw lazyDOMException('The operation was aborted', 'AbortError');
-
- state.state = kSocketBound;
-
- process.nextTick(() => {
- // User code may have run before this so we need to check the
- // destroyed state. If it has been destroyed, do nothing.
- if (this.destroyed)
- return;
- try {
- this.emit('ready');
- } catch (error) {
- this.destroy(error);
- }
- });
- } catch (error) {
- this.destroy(error);
- throw error;
- }
- }
-
- // Currently only used for testing when the QuicEndpoint is bound immediately.
- [kEndpointBound](endpoint) {
- const state = this[kInternalState];
- if (state.state === kSocketBound)
- return;
- state.state = kSocketBound;
-
- // The ready event indicates that the QuicSocket is ready to be
- // used to either listen or connect. No QuicServerSession should
- // exist before this event, and all QuicClientSession will remain
- // in Initial states until ready is invoked.
- process.nextTick(() => {
- try {
- this.emit('ready');
- } catch (error) {
- this.destroy(error);
- }
- });
- }
-
- // Called by the C++ internals to notify when server busy status is toggled.
- [kServerBusy]() {
- const busy = this.serverBusy;
- process.nextTick(() => {
- try {
- this.emit('busy', busy);
- } catch (error) {
- this[kRejections](error, 'busy', busy);
- }
- });
- }
-
- // A QuicSocket will typically bind only to a single local port, but it is
- // possible to bind to multiple, even if those use different IP families
- // (e.g. IPv4 or IPv6). Calls to addEndpoint() must be made before the
- // QuicSocket is bound (e.g. before any calls to listen() or connect()).
- addEndpoint(options = {}) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- if (state.state !== kSocketUnbound)
- throw new ERR_INVALID_STATE('QuicSocket is already being bound');
-
- options = {
- lookup: state.lookup,
- ...options
- };
-
- const endpoint = new QuicEndpoint(this, options);
- state.endpoints.add(endpoint);
- return endpoint;
- }
-
- listen(options) {
- const state = this[kInternalState];
- if (state.listenPromise !== undefined)
- return state.listenPromise;
-
- return state.listenPromise = PromisePrototypeFinally(
- this[kListen](options),
- () => {
- state.listenPromise = undefined;
- }
- );
- }
-
- async [kListen](options) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
- if (this.listening)
- throw new ERR_INVALID_STATE('QuicSocket is already listening');
-
- options = {
- ...state.server,
- ...options,
- };
-
- // The ALPN protocol identifier is strictly required.
- const {
- alpn,
- lookup = state.lookup,
- defaultEncoding,
- highWaterMark,
- ocspHandler,
- clientHelloHandler,
- transportParams,
- } = validateQuicSocketListenOptions(options);
-
- state.serverSecureContext =
- createSecureContext({
- ...options,
- minVersion: 'TLSv1.3',
- maxVersion: 'TLSv1.3',
- }, initSecureContext);
- state.highWaterMark = highWaterMark;
- state.defaultEncoding = defaultEncoding;
- state.alpn = alpn;
- state.listenPending = true;
- state.ocspHandler = ocspHandler;
- state.clientHelloHandler = clientHelloHandler;
-
- await this[kMaybeBind]();
-
- // It's possible that the QuicSocket was destroyed or closed while
- // the bind was pending. Check for that and handle accordingly.
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- const {
- ip,
- port,
- type
- } = await resolvePreferredAddress(lookup, transportParams.preferredAddress);
-
- // It's possible that the QuicSocket was destroyed or closed while
- // the preferred address resolution was pending. Check for that and handle
- // accordingly.
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- const {
- rejectUnauthorized = !getAllowUnauthorized(),
- requestCert = false,
- } = transportParams;
-
- // Transport Parameters are passed to the C++ side using a shared array.
- // These are the transport parameters that will be used when a new
- // server QuicSession is established. They are transmitted to the client
- // as part of the server's initial TLS handshake. Once they are set, they
- // cannot be modified.
- setTransportParams(transportParams);
-
- // When the handle is told to listen, it will begin acting as a QUIC
- // server and will emit session events whenever a new QuicServerSession
- // is created.
- state.listenPending = false;
- this[kHandle].listen(
- state.serverSecureContext.context,
- ip, // Preferred address ip,
- type, // Preferred address type,
- port, // Preferred address port,
- state.alpn,
- (rejectUnauthorized ? QUICSERVERSESSION_OPTION_REJECT_UNAUTHORIZED : 0) |
- (requestCert ? QUICSERVERSESSION_OPTION_REQUEST_CERT : 0));
-
- process.nextTick(() => {
- // It's remotely possible the QuicSocket is be destroyed or closed
- // while the nextTick is pending. If that happens, do nothing.
- if (this.destroyed || this.closing)
- return;
- try {
- this.emit('listening');
- } catch (error) {
- this.destroy(error);
- }
- });
- }
-
- async connect(options) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- options = {
- ...state.client,
- ...options
- };
-
- const {
- type,
- address,
- lookup = state.lookup
- } = validateQuicSocketConnectOptions(options);
-
- await this[kMaybeBind]();
-
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- const {
- address: ip
- } = await lookup(addressOrLocalhost(address, type),
- type === AF_INET6 ? 6 : 4);
-
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- if (this.blockList.check(ip, type === AF_INET6 ? 'ipv6' : 'ipv4'))
- throw new ERR_OPERATION_FAILED(`${ip} failed BlockList check`);
-
- return new QuicClientSession(this, options, type, ip);
- }
-
- [kEndpointClose](endpoint, error) {
- const state = this[kInternalState];
- state.endpoints.delete(endpoint);
- process.nextTick(() => {
- try {
- this.emit('endpointClose', endpoint, error);
- } catch (error) {
- this.destroy(error);
- }
- });
-
- // If there aren't any more endpoints, the QuicSession
- // is no longer usable and needs to be destroyed.
- if (state.endpoints.size === 0) {
- if (!this.destroyed)
- return this.destroy(error);
- this[kDestroy](error);
- }
- }
-
- // Initiate a Graceful Close of the QuicSocket.
- // Existing QuicClientSession and QuicServerSession instances will be
- // permitted to close naturally and gracefully on their own.
- // The QuicSocket will be immediately closed and freed as soon as there
- // are no additional session instances remaining. If there are no
- // QuicClientSession or QuicServerSession instances, the QuicSocket
- // will be immediately closed.
- //
- // Returns a Promise that will be resolved once the QuicSocket is
- // destroyed.
- //
- // No additional QuicServerSession instances will be accepted from
- // remote peers, and calls to connect() to create QuicClientSession
- // instances will fail. The QuicSocket will be otherwise usable in
- // every other way.
- //
- // Once initiated, a graceful close cannot be canceled. The graceful
- // close can be interupted, however, by abruptly destroying the
- // QuicSocket using the destroy() method.
- //
- // If close() is called before the QuicSocket has been bound (before
- // either connect() or listen() have been called, or the QuicSocket
- // is still in the pending state, the QuicSocket is destroyed
- // immediately.
- close() {
- return this[kInternalState].closePromise || this[kClose]();
- }
-
- [kClose]() {
- if (this.destroyed) {
- return PromiseReject(
- new ERR_INVALID_STATE('QuicSocket is already destroyed'));
- }
- const state = this[kInternalState];
- const promise = deferredClosePromise(state);
-
- // Tell the underlying QuicSocket C++ object to stop
- // listening for new QuicServerSession connections.
- // New initial connection packets for currently unknown
- // DCID's will be ignored.
- if (this[kHandle])
- state.sharedState.serverListening = false;
-
- // If the QuicSocket is otherwise not bound to the local
- // port, or there are not active sessions, destroy the
- // QuicSocket immediately and we're done.
- if (state.state !== kSocketBound || state.sessions.size === 0) {
- this.destroy();
- return promise;
- }
-
- // Otherwise, loop through each of the known sessions and close them.
- const reqs = [promise];
- for (const session of state.sessions) {
- ArrayPrototypePush(reqs,
- PromisePrototypeCatch(session.close(),
- (error) => this.destroy(error)));
- }
- return PromiseAll(reqs);
- }
-
- // Initiate an abrupt close and destruction of the QuicSocket.
- // Existing QuicClientSession and QuicServerSession instances will be
- // immediately closed. If error is specified, it will be forwarded
- // to each of the session instances.
- //
- // When the session instances are closed, an attempt to send a final
- // CONNECTION_CLOSE will be made.
- //
- // The JavaScript QuicSocket object will be marked destroyed and will
- // become unusable. As soon as all pending outbound UDP packets are
- // flushed from the QuicSocket's queue, the QuicSocket C++ instance
- // will be destroyed and freed from memory.
- destroy(error) {
- const state = this[kInternalState];
- // If the QuicSocket is already destroyed, do nothing
- if (state.state === kSocketDestroyed)
- return;
-
- // Mark the QuicSocket as being destroyed.
- state.state = kSocketDestroyed;
- this[kHandle].stats[IDX_QUIC_SOCKET_STATS_DESTROYED_AT] =
- process.hrtime.bigint();
- state.stats = new BigInt64Array(this[kHandle].stats);
-
- // Immediately close any sessions that may be remaining.
- // If the udp socket is in a state where it is able to do so,
- // a final attempt to send CONNECTION_CLOSE frames for each
- // closed session will be made.
- for (const session of state.sessions)
- session.destroy(error);
-
- // If there aren't any QuicEndpoints to clean up, skip
- // directly to the end to emit the error and close events.
- if (state.endpoints.size === 0)
- return this[kDestroy](error);
-
- // Otherwise, the QuicSocket will be destroyed once all
- // QuicEndpoints are destroyed. See [kEndpointClose].
- for (const endpoint of state.endpoints)
- endpoint.destroy(error);
- }
-
- [kDestroy](error) {
- const state = this[kInternalState];
- if (error) {
- if (typeof state.closePromiseReject === 'function')
- state.closePromiseReject(error);
- process.nextTick(FunctionPrototypeBind(emit, this, 'error', error));
- } else if (typeof state.closePromiseResolve === 'function') {
- state.closePromiseResolve();
- }
- process.nextTick(FunctionPrototypeBind(emit, this, 'close'));
- }
-
- ref() {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- for (const endpoint of state.endpoints)
- endpoint.ref();
- return this;
- }
-
- unref() {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- for (const endpoint of state.endpoints)
- endpoint.unref();
- return this;
- }
-
- get blockList() {
- return this[kInternalState]?.blockList;
- }
-
- get endpoints() {
- return ArrayFrom(this[kInternalState].endpoints);
- }
-
- get serverSecureContext() {
- return this[kInternalState].serverSecureContext;
- }
-
- // True if at least one associated QuicEndpoint has been successfully
- // bound to a local UDP port.
- get bound() {
- return this[kInternalState].state === kSocketBound;
- }
-
- // True if graceful close has been initiated by calling close()
- get closing() {
- return this[kInternalState].closePromise !== undefined;
- }
-
- // True if the QuicSocket has been destroyed and is no longer usable
- get destroyed() {
- return this[kInternalState].state === kSocketDestroyed;
- }
-
- // True if listen() has been called successfully
- get listening() {
- return Boolean(this[kInternalState].sharedState?.serverListening);
- }
-
- // True if the QuicSocket is currently waiting on at least one
- // QuicEndpoint to succesfully bind.g
- get pending() {
- return this[kInternalState].state === kSocketPending;
- }
-
- // Marking a server as busy will cause all new
- // connection attempts to fail with a SERVER_BUSY CONNECTION_CLOSE.
- set serverBusy(on) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- validateBoolean(on, 'on');
- if (state.sharedState.serverBusy !== on) {
- state.sharedState.serverBusy = on;
- this[kServerBusy]();
- }
- }
-
- get serverBusy() {
- return Boolean(this[kInternalState].sharedState?.serverBusy);
- }
-
- set statelessResetDisabled(on) {
- const state = this[kInternalState];
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- validateBoolean(on, 'on');
- if (state.sharedState.statelessResetDisabled !== on)
- state.sharedState.statelessResetDisabled = on;
- }
-
- get statelessResetDisabled() {
- return Boolean(this[kInternalState].sharedState?.statelessResetDisabled);
- }
-
- get duration() {
- const end = getStats(this, IDX_QUIC_SOCKET_STATS_DESTROYED_AT) ||
- process.hrtime.bigint();
- return Number(end - getStats(this, IDX_QUIC_SOCKET_STATS_CREATED_AT));
- }
-
- get boundDuration() {
- const end = getStats(this, IDX_QUIC_SOCKET_STATS_DESTROYED_AT) ||
- process.hrtime.bigint();
- return Number(end - getStats(this, IDX_QUIC_SOCKET_STATS_BOUND_AT));
- }
-
- get listenDuration() {
- const end = getStats(this, IDX_QUIC_SOCKET_STATS_DESTROYED_AT) ||
- process.hrtime.bigint();
- return Number(end - getStats(this, IDX_QUIC_SOCKET_STATS_LISTEN_AT));
- }
-
- get bytesReceived() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_BYTES_RECEIVED));
- }
-
- get bytesSent() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_BYTES_SENT));
- }
-
- get packetsReceived() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_PACKETS_RECEIVED));
- }
-
- get packetsSent() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_PACKETS_SENT));
- }
-
- get packetsIgnored() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_PACKETS_IGNORED));
- }
-
- get serverSessions() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_SERVER_SESSIONS));
- }
-
- get clientSessions() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_CLIENT_SESSIONS));
- }
-
- get statelessResetCount() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_STATELESS_RESET_COUNT));
- }
-
- get serverBusyCount() {
- return Number(getStats(this, IDX_QUIC_SOCKET_STATS_SERVER_BUSY_COUNT));
- }
-
- // Diagnostic packet loss is a testing mechanism that allows simulating
- // pseudo-random packet loss for rx or tx. The value specified for each
- // option is a number between 0 and 1 that identifies the possibility of
- // packet loss in the given direction.
- setDiagnosticPacketLoss(options) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- const {
- rx = 0.0,
- tx = 0.0
- } = { ...options };
- validateNumber(
- rx,
- 'options.rx',
- /* min */ 0.0,
- /* max */ 1.0);
- validateNumber(
- tx,
- 'options.tx',
- /* min */ 0.0,
- /* max */ 1.0);
- if ((rx > 0.0 || tx > 0.0) && !diagnosticPacketLossWarned) {
- diagnosticPacketLossWarned = true;
- process.emitWarning(
- 'QuicSocket diagnostic packet loss is enabled. Received or ' +
- 'transmitted packets will be randomly ignored to simulate ' +
- 'network packet loss.');
- }
- this[kHandle].setDiagnosticPacketLoss(rx, tx);
- }
-}
-
-class QuicSession extends EventEmitter {
- [kInternalState] = {
- alpn: undefined,
- cipher: undefined,
- cipherVersion: undefined,
- clientHelloHandler: undefined,
- closeCode: NGTCP2_NO_ERROR,
- closeFamily: QUIC_ERROR_APPLICATION,
- closePromise: undefined,
- closePromiseResolve: undefined,
- closePromiseReject: undefined,
- destroyed: false,
- earlyData: false,
- handshakeComplete: false,
- handshakeCompletePromise: undefined,
- handshakeCompletePromiseResolve: undefined,
- handshakeCompletePromiseReject: undefined,
- idleTimeout: false,
- maxPacketLength: NGTCP2_DEFAULT_MAX_PKTLEN,
- ocspHandler: undefined,
- servername: undefined,
- socket: undefined,
- silentClose: false,
- statelessReset: false,
- stats: undefined,
- streams: new Map(),
- verifyErrorReason: undefined,
- verifyErrorCode: undefined,
- handshakeAckHistogram: undefined,
- handshakeContinuationHistogram: undefined,
- highWaterMark: undefined,
- defaultEncoding: undefined,
- state: undefined,
- qlogStream: undefined,
- };
-
- constructor(socket, options) {
- const {
- alpn,
- servername,
- highWaterMark,
- defaultEncoding,
- ocspHandler,
- clientHelloHandler,
- } = options;
- super({ captureRejections: true });
- this.on('newListener', onNewListener);
- this.on('removeListener', onRemoveListener);
- const state = this[kInternalState];
- state.socket = socket;
- state.servername = servername;
- state.alpn = alpn;
- state.highWaterMark = highWaterMark;
- state.defaultEncoding = defaultEncoding;
- state.ocspHandler = ocspHandler;
- state.clientHelloHandler = clientHelloHandler;
- socket[kAddSession](this);
- }
-
- [kRejections](err, eventname, ...args) {
- this.destroy(err);
- }
-
- // Used to get the configured options for peer initiated QuicStream
- // instances.
- get [kStreamOptions]() {
- const state = this[kInternalState];
- return {
- highWaterMark: state.highWaterMark,
- defaultEncoding: state.defaultEncoding,
- };
- }
-
- [kSetQLogStream](stream) {
- const state = this[kInternalState];
- state.qlogStream = stream;
- process.nextTick(() => {
- try {
- this.emit('qlog', state.qlogStream);
- } catch (error) {
- this.destroy(error);
- }
- });
- }
-
- [kHandshakeComplete]() {
- const state = this[kInternalState];
- if (state.handshakeComplete)
- return PromiseResolve();
-
- if (state.handshakeCompletePromise !== undefined)
- return state.handshakeCompletePromise;
-
- state.handshakeCompletePromise = PromisePrototypeFinally(
- new Promise((resolve, reject) => {
- state.handshakeCompletePromiseResolve = resolve;
- state.handshakeCompletePromiseReject = reject;
- }),
- () => {
- state.handshakeCompletePromise = undefined;
- state.handshakeCompletePromiseReject = undefined;
- state.handshakeCompletePromiseResolve = undefined;
- }
- );
-
- return state.handshakeCompletePromise;
- }
-
- // Sets the internal handle for the QuicSession instance. For
- // server QuicSessions, this is called immediately as the
- // handle is created before the QuicServerSession JS object.
- // For client QuicSession instances, the connect() method
- // must first perform DNS resolution on the provided address
- // before the underlying QuicSession handle can be created.
- [kSetHandle](handle) {
- const state = this[kInternalState];
- this[kHandle] = handle;
- if (handle !== undefined) {
- handle[owner_symbol] = this;
- state.state = new QuicSessionSharedState(handle.state);
- state.handshakeAckHistogram = new Histogram(handle.ack);
- state.handshakeContinuationHistogram = new Histogram(handle.rate);
- state.state.ocspEnabled = state.ocspHandler !== undefined;
- state.state.clientHelloEnabled = state.clientHelloHandler !== undefined;
- if (handle.qlogStream !== undefined) {
- this[kSetQLogStream](handle.qlogStream);
- handle.qlogStream = undefined;
- }
- } else {
- if (state.handshakeAckHistogram)
- state.handshakeAckHistogram[kDestroyHistogram]();
- if (state.handshakeContinuationHistogram)
- state.handshakeContinuationHistogram[kDestroyHistogram]();
- }
- }
-
- // Called when a client QuicSession instance receives a version
- // negotiation packet from the server peer. The client QuicSession
- // is destroyed immediately. This is not called at all for server
- // QuicSessions.
- [kVersionNegotiation](version, requestedVersions, supportedVersions) {
- const err =
- new ERR_QUIC_VERSION_NEGOTIATION(
- version,
- requestedVersions,
- supportedVersions);
- err.detail = {
- version,
- requestedVersions,
- supportedVersions,
- };
- this.destroy(err);
- }
-
- // Closes the specified stream with the given code. The
- // QuicStream object will be destroyed.
- [kStreamClose](id, code) {
- const stream = this[kInternalState].streams.get(id);
- if (stream === undefined)
- return;
- stream[kDestroy](code);
- }
-
- [kStreamReset](id, code) {
- const stream = this[kInternalState].streams.get(id);
- if (stream === undefined)
- return;
-
- stream[kStreamReset](code);
- }
-
- // Delivers a block of headers to the appropriate QuicStream
- // instance. This will only be called if the ALPN selected
- // is known to support headers.
- [kHeaders](id, headers, kind, push_id) {
- const stream = this[kInternalState].streams.get(id);
- if (stream === undefined)
- return;
-
- stream[kHeaders](headers, kind, push_id);
- }
-
- [kInspect](depth, options) {
- const state = this[kInternalState];
- return customInspect(this, {
- alpn: state.alpn,
- cipher: this.cipher,
- closing: this.closing,
- closeCode: this.closeCode,
- destroyed: this.destroyed,
- earlyData: state.earlyData,
- maxStreams: this.maxStreams,
- servername: this.servername,
- streams: state.streams.size,
- }, depth, options);
- }
-
- [kSetSocket](socket, natRebinding = false) {
- this[kInternalState].socket = socket;
- if (socket !== undefined)
- this[kHandle].setSocket(socket[kHandle], natRebinding);
- }
-
- // Called at the completion of the TLS handshake for the local peer
- [kHandshake](
- servername,
- alpn,
- cipher,
- cipherVersion,
- maxPacketLength,
- verifyErrorReason,
- verifyErrorCode,
- earlyData) {
- const state = this[kInternalState];
- state.handshakeComplete = true;
- state.servername = servername;
- state.alpn = alpn;
- state.cipher = cipher;
- state.cipherVersion = cipherVersion;
- state.maxPacketLength = maxPacketLength;
- state.verifyErrorReason = verifyErrorReason;
- state.verifyErrorCode = verifyErrorCode;
- state.earlyData = earlyData;
-
- if (!this[kHandshakePost]()) {
- if (typeof state.handshakeCompletePromiseReject === 'function') {
- state.handshakeCompletePromiseReject(
- new ERR_OPERATION_FAILED('Handshake failed'));
- }
- return;
- }
-
- if (typeof state.handshakeCompletePromiseResolve === 'function')
- state.handshakeCompletePromiseResolve();
-
- process.nextTick(() => {
- try {
- this.emit('secure', servername, alpn, this.cipher);
- } catch (error) {
- this.destroy(error);
- }
- });
- }
-
- // Non-op for the default case. QuicClientSession
- // overrides this with some client-side specific
- // checks
- [kHandshakePost]() {
- return true;
- }
-
- [kRemoveStream](stream) {
- this[kInternalState].streams.delete(stream.id);
- this[kMaybeDestroy]();
- }
-
- [kAddStream](id, stream) {
- this[kInternalState].streams.set(id, stream);
- }
-
- // Called when a client QuicSession has opted to use the
- // server provided preferred address. This is a purely
- // informationational notification. It is not called on
- // server QuicSession instances.
- [kUsePreferredAddress](address) {
- process.nextTick(() => {
- try {
- this.emit('usePreferredAddress', address);
- } catch (error) {
- this.destroy(error);
- }
- });
- }
-
- close() {
- return this[kInternalState].closePromise || this[kClose]();
- }
-
- [kClose]() {
- if (this.destroyed) {
- return PromiseReject(
- new ERR_INVALID_STATE('QuicSession is already destroyed'));
- }
- const promise = deferredClosePromise(this[kInternalState]);
- if (!this[kMaybeDestroy]()) {
- this[kHandle].gracefulClose();
- }
- return promise;
- }
-
- get closing() {
- return this[kInternalState].closePromise !== undefined;
- }
-
- // The QuicSession will be destroyed if close() has been
- // called and there are no remaining streams
- [kMaybeDestroy]() {
- const state = this[kInternalState];
- if (this.closing && state.streams.size === 0) {
- this.destroy();
- return true;
- }
- return false;
- }
-
- // Causes the QuicSession to be immediately destroyed, but with
- // additional metadata set.
- [kDestroy](code, family, silent, statelessReset) {
- const state = this[kInternalState];
- state.closeCode = code;
- state.closeFamily = family;
- state.silentClose = silent;
- state.statelessReset = statelessReset;
- this.destroy();
- }
-
- // Destroying synchronously shuts down and frees the
- // QuicSession immediately, even if there are still open
- // streams.
- //
- // Unless we're in the middle of a silent close, a
- // CONNECTION_CLOSE packet will be sent to the connected
- // peer and the session will be immediately destroyed.
- //
- // If destroy is called with an error argument, the
- // 'error' event is emitted on next tick.
- //
- // Once destroyed, and after the 'error' event (if any),
- // the 'close' event is emitted on next tick.
- destroy(error) {
- const state = this[kInternalState];
- // Destroy can only be called once. Multiple calls will be ignored
- if (state.destroyed)
- return;
- state.destroyed = true;
-
- state.idleTimeout = Boolean(this[kInternalState].state?.idleTimeout);
-
- // Destroy any remaining streams immediately.
- for (const stream of state.streams.values())
- stream.destroy(error);
-
- this.removeListener('newListener', onNewListener);
- this.removeListener('removeListener', onRemoveListener);
-
- const handle = this[kHandle];
- this[kHandle] = undefined;
- if (handle !== undefined) {
- // Copy the stats for use after destruction
- handle.stats[IDX_QUIC_SESSION_STATS_DESTROYED_AT] =
- process.hrtime.bigint();
- state.stats = new BigInt64Array(handle.stats);
-
- // Destroy the underlying QuicSession handle
- handle.destroy(state.closeCode, state.closeFamily);
- }
-
- // Remove the QuicSession JavaScript object from the
- // associated QuicSocket.
- state.socket[kRemoveSession](this);
- state.socket = undefined;
-
- // If we are destroying with an error, schedule the
- // error to be emitted on process.nextTick.
- if (error) {
- if (typeof state.closePromiseReject === 'function')
- state.closePromiseReject(error);
- process.nextTick(FunctionPrototypeBind(emit, this, 'error', error));
- } else if (typeof state.closePromiseResolve === 'function')
- state.closePromiseResolve();
-
- if (typeof state.handshakeCompletePromiseReject === 'function') {
- state.handshakeCompletePromiseReject(
- new ERR_OPERATION_FAILED('Handshake failed'));
- }
-
- process.nextTick(FunctionPrototypeBind(emit, this, 'close'));
- }
-
- // For server QuicSession instances, true if earlyData is
- // enabled. For client QuicSessions, true only if session
- // resumption is used and early data was accepted during
- // the TLS handshake. The value is set only after the
- // TLS handshake is completed (immeditely before the
- // secure event is emitted)
- get usingEarlyData() {
- return this[kInternalState].earlyData;
- }
-
- get maxStreams() {
- let bidi = 0;
- let uni = 0;
- if (this[kHandle]) {
- bidi = this[kInternalState].state.maxStreamsBidi;
- uni = this[kInternalState].state.maxStreamsUni;
- }
- return { bidi, uni };
- }
-
- get qlog() {
- return this[kInternalState].qlogStream;
- }
-
- get address() {
- return this[kInternalState].socket?.address || {};
- }
-
- get maxDataLeft() {
- return Number(this[kHandle] ? this[kInternalState].state.maxDataLeft : 0);
- }
-
- get bytesInFlight() {
- return Number(this[kHandle] ? this[kInternalState].state.bytesInFlight : 0);
- }
-
- get blockCount() {
- return Number(
- this[kHandle]?.stats[IDX_QUIC_SESSION_STATS_BLOCK_COUNT] || 0);
- }
-
- get authenticated() {
- // Specifically check for null. Undefined means the check has not
- // been performed yet, another other value other than null means
- // there was an error
- return this[kInternalState].verifyErrorReason == null;
- }
-
- get authenticationError() {
- if (this.authenticated)
- return undefined;
- const state = this[kInternalState];
- // eslint-disable-next-line no-restricted-syntax
- const err = new Error(state.verifyErrorReason);
- const code = 'ERR_QUIC_VERIFY_' + state.verifyErrorCode;
- err.name = `Error [${code}]`;
- err.code = code;
- return err;
- }
-
- get remoteAddress() {
- const out = {};
- if (this[kHandle])
- this[kHandle].getRemoteAddress(out);
- return out;
- }
-
- get handshakeComplete() {
- return this[kInternalState].handshakeComplete;
- }
-
- get handshakeConfirmed() {
- return this[kHandle] ?
- this[kInternalState].state.handshakeConfirmed :
- false;
- }
-
- get idleTimeout() {
- return this[kInternalState].idleTimeout;
- }
-
- get alpnProtocol() {
- return this[kInternalState].alpn;
- }
-
- get cipher() {
- if (!this.handshakeComplete)
- return {};
- const state = this[kInternalState];
- return {
- name: state.cipher,
- version: state.cipherVersion,
- };
- }
-
- getCertificate() {
- return this[kHandle] ?
- translatePeerCertificate(this[kHandle].getCertificate() || {}) : {};
- }
-
- getPeerCertificate(detailed = false) {
- return this[kHandle] ?
- translatePeerCertificate(
- this[kHandle].getPeerCertificate(detailed) || {}) : {};
- }
-
- ping() {
- if (this.destroyed) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is already destroyed`);
- }
- this[kHandle].ping();
- }
-
- get servername() {
- return this[kInternalState].servername;
- }
-
- get destroyed() {
- return this[kInternalState].destroyed;
- }
-
- get closeCode() {
- const state = this[kInternalState];
- return {
- code: state.closeCode,
- family: state.closeFamily,
- silent: state.silentClose,
- };
- }
-
- get socket() {
- return this[kInternalState].socket;
- }
-
- get statelessReset() {
- return this[kInternalState].statelessReset;
- }
-
- async openStream(options) {
- if (this.destroyed) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is already destroyed`);
- }
- if (this.closing) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is closing`);
- }
-
- const {
- halfOpen, // Unidirectional or Bidirectional
- highWaterMark,
- defaultEncoding,
- } = validateQuicStreamOptions(options);
-
- const stream = new QuicStream({
- highWaterMark,
- defaultEncoding,
- readable: !halfOpen
- }, this);
-
- await once(stream, kReady);
-
- return stream;
- }
-
- get duration() {
- const end = getStats(this, IDX_QUIC_SESSION_STATS_DESTROYED_AT) ||
- process.hrtime.bigint();
- return Number(end - getStats(this, IDX_QUIC_SESSION_STATS_CREATED_AT));
- }
-
- get handshakeDuration() {
- const end =
- this.handshakeComplete ?
- getStats(this, IDX_QUIC_SESSION_STATS_HANDSHAKE_COMPLETED_AT) :
- process.hrtime.bigint();
- return Number(
- end - getStats(this, IDX_QUIC_SESSION_STATS_HANDSHAKE_START_AT));
- }
-
- get bytesReceived() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_BYTES_RECEIVED));
- }
-
- get bytesSent() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_BYTES_SENT));
- }
-
- get bidiStreamCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_BIDI_STREAM_COUNT));
- }
-
- get uniStreamCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_UNI_STREAM_COUNT));
- }
-
- get maxInFlightBytes() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_MAX_BYTES_IN_FLIGHT));
- }
-
- get lossRetransmitCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_LOSS_RETRANSMIT_COUNT));
- }
-
- get ackDelayRetransmitCount() {
- return Number(
- getStats(this, IDX_QUIC_SESSION_STATS_ACK_DELAY_RETRANSMIT_COUNT));
- }
-
- get peerInitiatedStreamCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_STREAMS_IN_COUNT));
- }
-
- get selfInitiatedStreamCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_STREAMS_OUT_COUNT));
- }
-
- get keyUpdateCount() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_KEYUPDATE_COUNT));
- }
-
- get minRTT() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_MIN_RTT));
- }
-
- get latestRTT() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_LATEST_RTT));
- }
-
- get smoothedRTT() {
- return Number(getStats(this, IDX_QUIC_SESSION_STATS_SMOOTHED_RTT));
- }
-
- updateKey() {
- const state = this[kInternalState];
- // Initiates a key update for the connection.
- if (this.destroyed) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is already destroyed`);
- }
- if (this.closing) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is closing`);
- }
- if (!state.handshakeConfirmed)
- throw new ERR_INVALID_STATE('Handshake is not yet confirmed');
- return this[kHandle].updateKey();
- }
-
- get handshakeAckHistogram() {
- return this[kInternalState].handshakeAckHistogram;
- }
-
- get handshakeContinuationHistogram() {
- return this[kInternalState].handshakeContinuationHistogram;
- }
-
- [kRemoveFromSocket]() {
- return this[kHandle].removeFromSocket();
- }
-}
-class QuicServerSession extends QuicSession {
- [kInternalServerState] = {
- context: undefined
- };
-
- constructor(socket, handle, options) {
- const {
- highWaterMark,
- defaultEncoding,
- ocspHandler,
- clientHelloHandler,
- context,
- } = options;
- super(socket, {
- highWaterMark,
- defaultEncoding,
- ocspHandler,
- clientHelloHandler
- });
- this[kInternalServerState].context = context;
- this[kSetHandle](handle);
- }
-
- // Called only when a clientHello event handler is registered.
- // Allows user code an opportunity to interject into the start
- // of the TLS handshake.
- async [kClientHello](alpn, servername, ciphers) {
- const internalState = this[kInternalState];
- return internalState.clientHelloHandler?.(alpn, servername, ciphers);
- }
-
- async [kHandleOcsp](servername) {
- const internalState = this[kInternalState];
- const { context } = this[kInternalServerState];
- if (!internalState.ocspHandler || !context) return undefined;
- return internalState.ocspHandler('request', {
- servername,
- certificate: context.context.getCertificate(),
- issuer: context.context.getIssuer()
- });
- }
-
- get allowEarlyData() { return false; }
-}
-
-class QuicClientSession extends QuicSession {
- [kInternalClientState] = {
- allowEarlyData: false,
- handshakeStarted: false,
- minDHSize: undefined,
- secureContext: undefined,
- };
-
- constructor(socket, options, type, ip) {
- const sc_options = {
- ...options,
- minVersion: 'TLSv1.3',
- maxVersion: 'TLSv1.3',
- };
- const {
- autoStart,
- alpn,
- dcid,
- minDHSize,
- ocspHandler,
- port,
- preferredAddressPolicy,
- remoteTransportParams,
- servername,
- sessionTicket,
- verifyHostnameIdentity,
- qlog,
- highWaterMark,
- defaultEncoding,
- } = validateQuicClientSessionOptions(options);
-
- if (!verifyHostnameIdentity && !warnedVerifyHostnameIdentity) {
- warnedVerifyHostnameIdentity = true;
- process.emitWarning(
- 'QUIC hostname identity verification is disabled. This violates QUIC ' +
- 'specification requirements and reduces security. Hostname identity ' +
- 'verification should only be disabled for debugging purposes.'
- );
- }
-
- super(socket, {
- servername,
- alpn,
- highWaterMark,
- defaultEncoding,
- ocspHandler
- });
- const state = this[kInternalClientState];
- state.handshakeStarted = autoStart;
- state.minDHSize = minDHSize;
-
- state.secureContext =
- createSecureContext(
- sc_options,
- initSecureContextClient);
-
- const transportParams = validateTransportParams(options);
-
- state.allowEarlyData =
- remoteTransportParams !== undefined &&
- sessionTicket !== undefined;
-
- setTransportParams(transportParams);
-
- const handle =
- _createClientSession(
- this.socket[kHandle],
- type,
- ip,
- port,
- state.secureContext.context,
- this.servername || ip,
- remoteTransportParams,
- sessionTicket,
- dcid,
- preferredAddressPolicy,
- this.alpnProtocol,
- (verifyHostnameIdentity ?
- QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY : 0) |
- (ocspHandler !== undefined ?
- QUICCLIENTSESSION_OPTION_REQUEST_OCSP : 0),
- qlog,
- autoStart);
-
- // If handle is a number, creating the session failed.
- if (typeof handle === 'number') {
- switch (handle) {
- case ERR_FAILED_TO_CREATE_SESSION:
- throw new ERR_QUIC_FAILED_TO_CREATE_SESSION();
- case ERR_INVALID_REMOTE_TRANSPORT_PARAMS:
- throw new ERR_QUIC_INVALID_REMOTE_TRANSPORT_PARAMS();
- case ERR_INVALID_TLS_SESSION_TICKET:
- throw new ERR_QUIC_INVALID_TLS_SESSION_TICKET();
- default:
- throw new ERR_OPERATION_FAILED(`Unspecified reason [${handle}]`);
- }
- }
-
- this[kSetHandle](handle);
- }
-
- [kHandshakePost]() {
- const { type, size } = this.ephemeralKeyInfo;
- if (type === 'DH' && size < this[kInternalClientState].minDHSize) {
- this.destroy(new ERR_TLS_DH_PARAM_SIZE(size));
- return false;
- }
- return true;
- }
-
- async [kHandleOcsp](data) {
- const internalState = this[kInternalState];
- return internalState.ocspHandler?.('response', { data });
- }
-
- get allowEarlyData() {
- return this[kInternalClientState].allowEarlyData;
- }
-
- get handshakeStarted() {
- return this[kInternalClientState].handshakeStarted;
- }
-
- startHandshake() {
- const state = this[kInternalClientState];
- if (this.destroyed) {
- throw new ERR_INVALID_STATE(
- `${this.constructor.name} is already destroyed`);
- }
- if (state.handshakeStarted)
- return;
- state.handshakeStarted = true;
- this[kHandle].startHandshake();
- }
-
- get ephemeralKeyInfo() {
- return this[kHandle] !== undefined ?
- this[kHandle].getEphemeralKeyInfo() :
- {};
- }
-
- async setSocket(socket, natRebinding = false) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicClientSession is already destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicClientSession is closing');
- if (!(socket instanceof QuicSocket))
- throw new ERR_INVALID_ARG_TYPE('socket', 'QuicSocket', socket);
- if (socket.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket is already destroyed');
- if (socket.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
- if (typeof natRebinding !== 'boolean')
- throw new ERR_INVALID_ARG_TYPE('natRebinding', 'boolean', true);
-
- await socket[kMaybeBind]();
-
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicClientSession was destroyed');
- if (this.closing)
- throw new ERR_INVALID_STATE('QuicClientSession is closing');
- if (socket.destroyed)
- throw new ERR_INVALID_STATE('QuicSocket was destroyed');
- if (socket.closing)
- throw new ERR_INVALID_STATE('QuicSocket is closing');
-
- if (this.socket) {
- this.socket[kRemoveSession](this);
- this[kSetSocket](undefined);
- }
- socket[kAddSession](this);
- this[kSetSocket](socket, natRebinding);
- }
-}
-
-function streamOnResume() {
- if (!this.destroyed && this.readable)
- this[kHandle].readStart();
-}
-
-function streamOnPause() {
- if (!this.destroyed)
- this[kHandle].readStop();
-}
-class QuicStream extends Duplex {
- [kInternalState] = {
- closed: false,
- closePromise: undefined,
- closePromiseReject: undefined,
- closePromiseResolve: undefined,
- defaultEncoding: undefined,
- didRead: false,
- id: undefined,
- highWaterMark: undefined,
- push_id: undefined,
- resetCode: undefined,
- session: undefined,
- dataRateHistogram: undefined,
- dataSizeHistogram: undefined,
- dataAckHistogram: undefined,
- ready: false,
- sharedState: undefined,
- stats: undefined,
- };
-
- constructor(options, session, handle, push_id) {
- const {
- highWaterMark,
- defaultEncoding,
- readable = true,
- writable = true,
- } = options;
-
- super({
- readable,
- writable,
- highWaterMark,
- defaultEncoding,
- allowHalfOpen: true,
- decodeStrings: true,
- emitClose: true,
- autoDestroy: true,
- captureRejections: true,
- });
- const state = this[kInternalState];
- state.highWaterMark = highWaterMark;
- state.defaultEncoding = defaultEncoding;
- state.session = session;
- state.push_id = push_id;
- this._readableState.readingMore = true;
- this.on('pause', streamOnPause);
-
- if (handle !== undefined)
- this[kSetHandle](handle);
- }
-
- async _construct(callback) {
- try {
- if (this[kInternalState].ready)
- return callback();
-
- // Handle is already initialized
- const unidirectional = !this.readable;
-
- await this.session[kHandshakeComplete]();
-
- if (this.destroyed) {
- throw new ERR_INVALID_STATE('QuicStream was destroyed');
- }
- if (this.session.destroyed) {
- throw new ERR_INVALID_STATE(
- `${this.session.constructor.name} was destroyed`);
- }
- if (this.session.closing) {
- throw new ERR_INVALID_STATE(
- `${this.session.constructor.name} is closing`);
- }
-
- const handle =
- unidirectional ?
- _openUnidirectionalStream(this.session[kHandle]) :
- _openBidirectionalStream(this.session[kHandle]);
-
- if (handle === undefined)
- throw new ERR_OPERATION_FAILED('Unable to create QuicStream');
-
- this[kSetHandle](handle);
- callback();
- } catch (error) {
- callback(error);
- }
- }
-
- // Set handle is called once the QuicSession has been able
- // to complete creation of the internal QuicStream handle.
- // This will happen only after the QuicSession's own
- // internal handle has been created. The QuicStream object
- // is still minimally usable before this but any data
- // written will be buffered until kSetHandle is called.
- [kSetHandle](handle) {
- const state = this[kInternalState];
- const current = this[kHandle];
- this[kHandle] = handle;
- if (handle !== undefined) {
- handle.onread = onStreamRead;
- handle[owner_symbol] = this;
- this[async_id_symbol] = handle.getAsyncId();
- state.id = handle.id();
- state.dataRateHistogram = new Histogram(handle.rate);
- state.dataSizeHistogram = new Histogram(handle.size);
- state.dataAckHistogram = new Histogram(handle.ack);
- state.sharedState = new QuicStreamSharedState(handle.state);
- state.session[kAddStream](state.id, this);
- state.ready = true;
- this.emit(kReady);
- } else {
- if (current !== undefined) {
- current.stats[IDX_QUIC_STREAM_STATS_DESTROYED_AT] =
- process.hrtime.bigint();
- state.stats = new BigInt64Array(current.stats);
- }
- state.sharedState = undefined;
- if (state.dataRateHistogram)
- state.dataRateHistogram[kDestroyHistogram]();
- if (state.dataSizeHistogram)
- state.dataSizeHistogram[kDestroyHistogram]();
- if (state.dataAckHistogram)
- state.dataAckHistogram[kDestroyHistogram]();
- }
- }
-
- [kStreamReset](code) {
- // Receiving a reset from the peer indicates that it is no
- // longer sending any data, we can safely close the readable
- // side of the Duplex here.
- this[kInternalState].resetCode = code;
- this.push(null);
- this.read();
- }
-
- [kClose]() {
- const state = this[kInternalState];
-
- if (this.destroyed) {
- return PromiseReject(
- new ERR_INVALID_STATE('QuicStream is already destroyed'));
- }
-
- const promise = deferredClosePromise(state);
- if (this.readable) {
- this.push(null);
- this.read();
- }
-
- if (this.writable) {
- this.end();
- }
-
- // TODO(@jasnell): Investigate later if a Promise version
- // of finished() can work here instead.
- return promise;
- }
-
- close() {
- return this[kInternalState].closePromise || this[kClose]();
- }
-
- _destroy(error, callback) {
- const state = this[kInternalState];
- const handle = this[kHandle];
- this[kSetHandle]();
- if (handle !== undefined)
- handle.destroy();
- state.session[kRemoveStream](this);
-
- if (error && typeof state.closePromiseReject === 'function')
- state.closePromiseReject(error);
- else if (typeof state.closePromiseResolve === 'function')
- state.closePromiseResolve();
-
- // TODO(@jasnell): Investigate how we can eliminate the nextTick here
- process.nextTick(() => callback(error));
- }
-
- [kDestroy](code) {
- // TODO(@jasnell): If code is non-zero, and stream is not otherwise
- // naturally shutdown, then we should destroy with an error.
-
- // Put the QuicStream into detached mode before calling destroy
- this[kSetHandle]();
- this.destroy();
- }
-
- [kHeaders](headers, kind, push_id) {
- // TODO(@jasnell): Convert the headers into a proper object
- let name;
- switch (kind) {
- case QUICSTREAM_HEADERS_KIND_NONE:
- // Fall through
- case QUICSTREAM_HEADERS_KIND_INITIAL:
- name = 'initialHeaders';
- break;
- case QUICSTREAM_HEADERS_KIND_INFORMATIONAL:
- name = 'informationalHeaders';
- break;
- case QUICSTREAM_HEADERS_KIND_TRAILING:
- name = 'trailingHeaders';
- break;
- case QUICSTREAM_HEADERS_KIND_PUSH:
- name = 'pushHeaders';
- break;
- default:
- assert.fail('Invalid headers kind');
- }
- process.nextTick(FunctionPrototypeBind(emit, this, name, headers, push_id));
- }
-
- [kAfterAsyncWrite]({ bytes }) {
- // There's currently nothing we need to do here. We have
- // to have this but it's a non-op
- }
-
- [kUpdateTimer]() {
- // Timeout is implemented in the QuicSession at the native
- // layer. We have to have this here but it's a non-op
- }
-
- [kTrackWriteState](stream, bytes) {
- // There's currently nothing to do here.
- }
-
- [kInspect](depth, options) {
- const direction = this.bidirectional ? 'bidirectional' : 'unidirectional';
- const initiated = this.serverInitiated ? 'server' : 'client';
- return customInspect(this, {
- id: this[kInternalState].id,
- detached: this.detached,
- direction,
- initiated,
- writableState: this._writableState,
- readableState: this._readableState
- }, depth, options);
- }
-
- get detached() {
- // The QuicStream is detached if it is yet destroyed
- // but the underlying handle is undefined. While in
- // detached mode, the QuicStream may still have
- // data pending in the read queue, but writes will
- // not be permitted.
- return this[kHandle] === undefined;
- }
-
- get serverInitiated() {
- return !!(this[kInternalState].id & 0b01);
- }
-
- get clientInitiated() {
- return !this.serverInitiated;
- }
-
- get unidirectional() {
- return !!(this[kInternalState].id & 0b10);
- }
-
- get bidirectional() {
- return !this.unidirectional;
- }
-
- [kWriteGeneric](writev, data, encoding, cb) {
- if (this.destroyed || this.detached)
- return;
-
- this[kUpdateTimer]();
- const req = (writev) ?
- writevGeneric(this, data, cb) :
- writeGeneric(this, data, encoding, cb);
-
- this[kTrackWriteState](this, req.bytes);
- }
-
- _write(data, encoding, cb) {
- this[kWriteGeneric](false, data, encoding, cb);
- }
-
- _writev(data, cb) {
- this[kWriteGeneric](true, data, '', cb);
- }
-
- // Called when the last chunk of data has been
- // acknowledged by the peer and end has been
- // called. By calling shutdown, we're telling
- // the native side that no more data will be
- // coming so that a fin stream packet can be
- // sent, allowing any remaining final stream
- // frames to be sent if necessary.
- //
- // When end() is called, we set the writeEnded
- // flag so that we can know earlier when there
- // is not going to be any more data being written
- // but that is only used when end() is called
- // with a final chunk to write.
- _final(cb) {
- if (!this.detached) {
- const state = this[kInternalState];
- if (state.sharedState?.finSent)
- return cb();
- const handle = this[kHandle];
- const req = new ShutdownWrap();
- req.oncomplete = () => {
- req.handle = undefined;
- cb();
- };
- req.handle = handle;
- if (handle.shutdown(req) === 1)
- return req.oncomplete();
- return;
- }
- return cb();
- }
-
- end(...args) {
- if (!this.destroyed) {
- if (!this.detached)
- this[kInternalState].sharedState.writeEnded = true;
- ReflectApply(super.end, this, args);
- }
- return this;
- }
-
- _read(nread) {
- if (this.destroyed) {
- this.push(null);
- return;
- }
- const state = this[kInternalState];
- if (!state.didRead) {
- this._readableState.readingMore = false;
- state.didRead = true;
- }
-
- FunctionPrototypeCall(streamOnResume, this);
- }
-
- sendFile(path, options = {}) {
- if (this.detached)
- throw new ERR_INVALID_STATE('Unable to send file');
- fs.open(path, 'r',
- FunctionPrototypeBind(QuicStream[kOnFileOpened], this, options));
- }
-
- static [kOnFileOpened](options, err, fd) {
- const onError = options.onError;
- if (err) {
- if (onError) {
- this.close();
- onError(err);
- } else {
- this.destroy(err);
- }
- return;
- }
-
- if (this.destroyed || this.closed) {
- fs.close(fd, assert.ifError);
- return;
- }
-
- this.sendFD(fd, options, true);
- }
-
- sendFD(fd, { offset = -1, length = -1 } = {}, ownsFd = false) {
- if (this.destroyed || this[kInternalState].closed)
- return;
-
- if (this.detached)
- throw new ERR_INVALID_STATE('Unable to send file descriptor');
-
- validateInteger(offset, 'options.offset', /* min */ -1);
- validateInteger(length, 'options.length', /* min */ -1);
-
- if (fd instanceof fsPromisesInternal.FileHandle)
- fd = fd.fd;
- else if (typeof fd !== 'number')
- throw new ERR_INVALID_ARG_TYPE('fd', ['number', 'FileHandle'], fd);
-
- this[kUpdateTimer]();
- this.ownsFd = ownsFd;
-
- defaultTriggerAsyncIdScope(this[async_id_symbol],
- QuicStream[kStartFilePipe],
- this, fd, offset, length);
- }
-
- static [kStartFilePipe](stream, fd, offset, length) {
- const handle = new FileHandle(fd, offset, length);
- handle.onread = QuicStream[kOnPipedFileHandleRead];
- handle.stream = stream;
-
- const pipe = new StreamPipe(handle, stream[kHandle]);
- pipe.onunpipe = QuicStream[kOnFileUnpipe];
- pipe.start();
-
- // Exact length of the file doesn't matter here, since the
- // stream is closing anyway - just use 1 to signify that
- // a write does exist
- stream[kTrackWriteState](stream, 1);
- }
-
- static [kOnFileUnpipe]() { // Called on the StreamPipe instance.
- const stream = this.sink[owner_symbol];
- if (stream.ownsFd)
- PromisePrototypeCatch(this.source.close(),
- FunctionPrototypeBind(stream.destroy, stream));
- else
- this.source.releaseFD();
- stream.end();
- }
-
- static [kOnPipedFileHandleRead]() {
- const err = streamBaseState[kReadBytesOrError];
- if (err < 0 && err !== UV_EOF) {
- this.stream.destroy(errnoException(err, 'sendFD'));
- }
- }
-
- get resetReceived() {
- const state = this[kInternalState];
- return (state.resetCode !== undefined) ?
- { code: state.resetCode | 0 } :
- undefined;
- }
-
- get id() {
- return this[kInternalState].id;
- }
-
- get push_id() {
- return this[kInternalState].push_id;
- }
-
- get session() {
- return this[kInternalState].session;
- }
-
- get dataRateHistogram() {
- return this[kInternalState].dataRateHistogram;
- }
-
- get dataSizeHistogram() {
- return this[kInternalState].dataSizeHistogram;
- }
-
- get dataAckHistogram() {
- return this[kInternalState].dataAckHistogram;
- }
-
- pushStream(headers = {}, options = {}) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicStream is already destroyed');
-
- if (this.detached) {
- throw new ERR_INVALID_STATE(
- 'Push stream could not be opened on this QuicSession. ' +
- 'Push is either disabled or currently blocked.');
- }
-
- const state = this[kInternalState];
- const {
- highWaterMark = state.highWaterMark,
- defaultEncoding = state.defaultEncoding,
- } = validateQuicStreamOptions(options);
-
- validateObject(headers, 'headers');
-
- // This is a small performance optimization for http/3,
- // where push streams are only supported for client
- // initiated, bidirectional streams. For any other alpn,
- // we'll make the attempt to push and handle the failure
- // after.
- if (!this.clientInitiated &&
- !this.bidirectional &&
- this.session.alpnProtocol === 'h3-29') {
- throw new ERR_INVALID_STATE(
- 'Push streams are only supported on client-initiated, ' +
- 'bidirectional streams');
- }
-
- // TODO(@jasnell): The assertValidPseudoHeader validator
- // here is HTTP/3 specific. If we end up with another
- // QUIC application protocol that supports push streams,
- // we will need to select a validator based on the
- // alpn value.
- const handle = this[kHandle].submitPush(
- mapToHeaders(headers, assertValidPseudoHeader));
-
- // If undefined is returned, it either means that push
- // streams are not supported by the underlying application,
- // or push streams are currently disabled/blocked. This
- // will typically be the case with HTTP/3 when the client
- // peer has disabled push.
- if (handle === undefined) {
- throw new ERR_INVALID_STATE(
- 'Push stream could not be opened on this QuicSession. ' +
- 'Push is either disabled or currently blocked.');
- }
-
- return new QuicStream({
- readable: false,
- highWaterMark,
- defaultEncoding,
- }, this.session, handle);
- }
-
- submitInformationalHeaders(headers = {}) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicStream is already destroyed');
-
- if (this.detached)
- throw new ERR_INVALID_STATE('Unable to submit headers');
-
- validateObject(headers, 'headers');
-
- // TODO(@jasnell): The validators here are specific to the QUIC
- // protocol. In the case below, these are the http/3 validators
- // (which are identical to the rules for http/2). We need to
- // find a way for this to be easily abstracted based on the
- // selected alpn.
-
- let validator;
- if (this.session instanceof QuicServerSession) {
- validator =
- this.clientInitiated ?
- assertValidPseudoHeaderResponse :
- assertValidPseudoHeader;
- } else { // QuicClientSession
- validator =
- this.clientInitiated ?
- assertValidPseudoHeader :
- assertValidPseudoHeaderResponse;
- }
-
- return this[kHandle].submitInformationalHeaders(
- mapToHeaders(headers, validator));
- }
-
- submitInitialHeaders(headers = {}, options = {}) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicStream is already destroyed');
-
- if (this.detached)
- throw new ERR_INVALID_STATE('Unable to submit headers');
-
- const { terminal } = { ...options };
-
- if (terminal !== undefined)
- validateBoolean(terminal, 'options.terminal');
- validateObject(headers, 'headers');
-
- // TODO(@jasnell): The validators here are specific to the QUIC
- // protocol. In the case below, these are the http/3 validators
- // (which are identical to the rules for http/2). We need to
- // find a way for this to be easily abstracted based on the
- // selected alpn.
-
- let validator;
- if (this.session instanceof QuicServerSession) {
- validator =
- this.clientInitiated ?
- assertValidPseudoHeaderResponse :
- assertValidPseudoHeader;
- } else { // QuicClientSession
- validator =
- this.clientInitiated ?
- assertValidPseudoHeader :
- assertValidPseudoHeaderResponse;
- }
-
- return this[kHandle].submitHeaders(
- mapToHeaders(headers, validator),
- terminal ?
- QUICSTREAM_HEADER_FLAGS_TERMINAL :
- QUICSTREAM_HEADER_FLAGS_NONE);
- }
-
- submitTrailingHeaders(headers = {}) {
- if (this.destroyed)
- throw new ERR_INVALID_STATE('QuicStream is already destroyed');
-
- if (this.detached)
- throw new ERR_INVALID_STATE('Unable to submit headers');
-
- validateObject(headers, 'headers');
-
- // TODO(@jasnell): The validators here are specific to the QUIC
- // protocol. In the case below, these are the http/3 validators
- // (which are identical to the rules for http/2). We need to
- // find a way for this to be easily abstracted based on the
- // selected alpn.
-
- return this[kHandle].submitTrailers(
- mapToHeaders(headers, assertValidPseudoHeaderTrailer));
- }
-
- get duration() {
- const end = getStats(this, IDX_QUIC_STREAM_STATS_DESTROYED_AT) ||
- process.hrtime.bigint();
- return Number(end - getStats(this, IDX_QUIC_STREAM_STATS_CREATED_AT));
- }
-
- get bytesReceived() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_BYTES_RECEIVED));
- }
-
- get bytesSent() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_BYTES_SENT));
- }
-
- get maxExtendedOffset() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_MAX_OFFSET));
- }
-
- get finalSize() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_FINAL_SIZE));
- }
-
- get maxAcknowledgedOffset() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_MAX_OFFSET_ACK));
- }
-
- get maxReceivedOffset() {
- return Number(getStats(this, IDX_QUIC_STREAM_STATS_MAX_OFFSET_RECV));
- }
-}
-
-function createSocket(options) {
- return new QuicSocket(options);
-}
-
-module.exports = {
- createSocket,
- kUDPHandleForTesting,
- kRemoveFromSocket,
-};
-
-/* eslint-enable no-use-before-define */
-
-// A single QuicSocket may act as both a Server and a Client.
-// There are two kinds of sessions:
-// * QuicServerSession
-// * QuicClientSession
-//
-// It is important to understand that QUIC sessions are
-// independent of the QuicSocket. A default configuration
-// for QuicServerSession and QuicClientSessions may be
-// set when the QuicSocket is created, but the actual
-// configuration for a particular QuicSession instance is
-// not set until the session itself is created.
-//
-// QuicSockets and QuicSession instances have distinct
-// configuration options that apply independently:
-//
-// QuicSocket Options:
-// * `lookup` {Function} A function used to resolve DNS names.
-// * `type` {string} Either `'udp4'` or `'udp6'`, defaults to
-// `'udp4'`.
-// * `port` {number} The local IP port the QuicSocket will
-// bind to.
-// * `address` {string} The local IP address or hostname that
-// the QuicSocket will bind to. If a hostname is given, the
-// `lookup` function will be invoked to resolve an IP address.
-// * `ipv6Only`
-// * `reuseAddr`
-//
-// Keep in mind that while all QUIC network traffic is encrypted
-// using TLS 1.3, every QuicSession maintains it's own SecureContext
-// that is completely independent of the QuicSocket. Every
-// QuicServerSession and QuicClientSession could, in theory,
-// use a completely different TLS 1.3 configuration. To keep it
-// simple, however, we use the same SecureContext for all QuicServerSession
-// instances, but that may be something we want to revisit later.
-//
-// Every QuicSession has two sets of configuration parameters:
-// * Options
-// * Transport Parameters
-//
-// Options establish implementation specific operation parameters,
-// such as the default highwatermark for new QuicStreams. Transport
-// Parameters are QUIC specific and are passed to the peer as part
-// of the TLS handshake.
-//
-// Every QuicSession may have separate options and transport
-// parameters, even within the same QuicSocket, so the configuration
-// must be established when the session is created.
-//
-// When creating a QuicSocket, it is possible to set a default
-// configuration for both QuicServerSession and QuicClientSession
-// options.
-//
-// const soc = createSocket({
-// type: 'udp4',
-// port: 0,
-// server: {
-// // QuicServerSession configuration defaults
-// },
-// client: {
-// // QuicClientSession configuration defaults
-// }
-// });
-//
-// When calling listen() on the created QuicSocket, the server
-// specific configuration that will be used for all new
-// QuicServerSession instances will be given, with the values
-// provided to createSocket() using the server option used
-// as a default.
-//
-// When calling connect(), the client specific configuration
-// will be given, with the values provided to the createSocket()
-// using the client option used as a default.
-
-
-// Some lifecycle documentation for the various objects:
-//
-// QuicSocket
-// Close
-// * Close all existing Sessions
-// * Do not allow any new Sessions (inbound or outbound)
-// * Destroy once there are no more sessions
-
-// Destroy
-// * Destroy all remaining sessions
-// * Destroy and free the QuicSocket handle immediately
-// * If Error, emit Error event
-// * Emit Close event
-
-// QuicClientSession
-// Close
-// * Allow existing Streams to complete normally
-// * Do not allow any new Streams (inbound or outbound)
-// * Destroy once there are no more streams
-
-// Destroy
-// * Send CONNECTION_CLOSE
-// * Destroy all remaining Streams
-// * Remove Session from Parent Socket
-// * Destroy and free the QuicSession handle immediately
-// * If Error, emit Error event
-// * Emit Close event
-
-// QuicServerSession
-// Close
-// * Allow existing Streams to complete normally
-// * Do not allow any new Streams (inbound or outbound)
-// * Destroy once there are no more streams
-// Destroy
-// * Send CONNECTION_CLOSE
-// * Destroy all remaining Streams
-// * Remove Session from Parent Socket
-// * Destroy and free the QuicSession handle immediately
-// * If Error, emit Error event
-// * Emit Close event
-
-// QuicStream
-// Destroy
-// * Remove Stream From Parent Session
-// * Destroy and free the QuicStream handle immediately
-// * If Error, emit Error event
-// * Emit Close event
-
-// QuicEndpoint States:
-// Initial -- Created, Endpoint not yet bound to local UDP
-// port.
-// Pending -- Binding to local UDP port has been initialized.
-// Bound -- Binding to local UDP port has completed.
-// Closed -- Endpoint has been unbound from the local UDP
-// port.
-// Error -- An error has been encountered, endpoint has
-// been unbound and is no longer usable.
-//
-// QuicSocket States:
-// Initial -- Created, QuicSocket has at least one
-// QuicEndpoint. All QuicEndpoints are in the
-// Initial state.
-// Pending -- QuicSocket has at least one QuicEndpoint in the
-// Pending state.
-// Bound -- QuicSocket has at least one QuicEndpoint in the
-// Bound state.
-// Closed -- All QuicEndpoints are in the closed state.
-// Destroyed -- QuicSocket is no longer usable
-// Destroyed-With-Error -- An error has been encountered, socket is no
-// longer usable
-//
-// QuicSession States:
-// Initial -- Created, QuicSocket state undetermined,
-// no internal QuicSession Handle assigned.
-// Ready
-// QuicSocket Ready -- QuicSocket in Bound state.
-// Handle Assigned -- Internal QuicSession Handle assigned.
-// TLS Handshake Started --
-// TLS Handshake Completed --
-// TLS Handshake Confirmed --
-// Closed -- Graceful Close Initiated
-// Destroyed -- QuicSession is no longer usable
-// Destroyed-With-Error -- An error has been encountered, session is no
-// longer usable
-//
-// QuicStream States:
-// Initial Writable/Corked -- Created, QuicSession in Initial State
-// Open Writable/Uncorked -- QuicSession in Ready State
-// Closed -- Graceful Close Initiated
-// Destroyed -- QuicStream is no longer usable
-// Destroyed-With-Error -- An error has been encountered, stream is no
-// longer usable
diff --git a/lib/internal/quic/util.js b/lib/internal/quic/util.js
deleted file mode 100644
index 97da695364..0000000000
--- a/lib/internal/quic/util.js
+++ /dev/null
@@ -1,1052 +0,0 @@
-'use strict';
-
-const {
- Boolean,
- Number,
- NumberINFINITY,
- NumberNEGATIVE_INFINITY,
-} = primordials;
-
-const {
- codes: {
- ERR_INVALID_ARG_TYPE,
- ERR_INVALID_ARG_VALUE,
- ERR_OUT_OF_RANGE,
- },
-} = require('internal/errors');
-
-const {
- symbols: {
- owner_symbol,
- },
-} = require('internal/async_hooks');
-
-const { inspect } = require('internal/util/inspect');
-
-const { Readable } = require('stream');
-const {
- kHandle,
- kUpdateTimer,
- onStreamRead,
-} = require('internal/stream_base_commons');
-
-const endianness = require('os').endianness();
-
-const assert = require('internal/assert');
-assert(process.versions.ngtcp2 !== undefined);
-
-const {
- isIP,
-} = require('internal/net');
-
-const {
- getOptionValue,
- getAllowUnauthorized,
-} = require('internal/options');
-
-const { Buffer } = require('buffer');
-
-const {
- sessionConfig,
- http3Config,
- constants: {
- AF_INET,
- AF_INET6,
- NGHTTP3_ALPN_H3,
- DEFAULT_RETRYTOKEN_EXPIRATION,
- DEFAULT_MAX_CONNECTIONS,
- DEFAULT_MAX_CONNECTIONS_PER_HOST,
- DEFAULT_MAX_STATELESS_RESETS_PER_HOST,
- IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_REMOTE,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI,
- IDX_QUIC_SESSION_MAX_DATA,
- IDX_QUIC_SESSION_MAX_STREAMS_BIDI,
- IDX_QUIC_SESSION_MAX_STREAMS_UNI,
- IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT,
- IDX_QUIC_SESSION_MAX_ACK_DELAY,
- IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE,
- IDX_QUIC_SESSION_CC_ALGO,
- IDX_QUIC_SESSION_CONFIG_COUNT,
-
- IDX_QUICSESSION_STATE_KEYLOG_ENABLED,
- IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED,
- IDX_QUICSESSION_STATE_OCSP_ENABLED,
- IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED,
- IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED,
- IDX_QUICSESSION_STATE_HANDSHAKE_CONFIRMED,
- IDX_QUICSESSION_STATE_IDLE_TIMEOUT,
- IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI,
- IDX_QUICSESSION_STATE_MAX_STREAMS_UNI,
- IDX_QUICSESSION_STATE_MAX_DATA_LEFT,
- IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT,
-
- IDX_QUICSOCKET_STATE_SERVER_LISTENING,
- IDX_QUICSOCKET_STATE_SERVER_BUSY,
- IDX_QUICSOCKET_STATE_STATELESS_RESET_DISABLED,
-
- IDX_QUICSTREAM_STATE_WRITE_ENDED,
- IDX_QUICSTREAM_STATE_READ_STARTED,
- IDX_QUICSTREAM_STATE_READ_PAUSED,
- IDX_QUICSTREAM_STATE_READ_ENDED,
- IDX_QUICSTREAM_STATE_FIN_SENT,
- IDX_QUICSTREAM_STATE_FIN_RECEIVED,
-
- IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY,
- IDX_HTTP3_QPACK_BLOCKED_STREAMS,
- IDX_HTTP3_MAX_HEADER_LIST_SIZE,
- IDX_HTTP3_MAX_PUSHES,
- IDX_HTTP3_MAX_HEADER_PAIRS,
- IDX_HTTP3_MAX_HEADER_LENGTH,
- IDX_HTTP3_CONFIG_COUNT,
- MAX_RETRYTOKEN_EXPIRATION,
- MIN_RETRYTOKEN_EXPIRATION,
- NGTCP2_NO_ERROR,
- NGTCP2_MAX_CIDLEN,
- NGTCP2_MIN_CIDLEN,
- NGTCP2_CC_ALGO_CUBIC,
- NGTCP2_CC_ALGO_RENO,
- QUIC_PREFERRED_ADDRESS_IGNORE,
- QUIC_PREFERRED_ADDRESS_USE,
- QUIC_ERROR_APPLICATION,
- }
-} = internalBinding('quic');
-
-const {
- validateBoolean,
- validateBuffer,
- validateFunction,
- validateInteger,
- validateObject,
- validatePort,
- validateString,
-} = require('internal/validators');
-
-const kDefaultQuicCiphers = 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:' +
- 'TLS_CHACHA20_POLY1305_SHA256';
-const kDefaultGroups = 'P-256:X25519:P-384:P-521';
-
-let dns;
-
-function lazyDNS() {
- if (!dns)
- dns = require('dns').promises;
- return dns;
-}
-
-// This is here rather than in internal/validators to
-// prevent performance degredation in default cases.
-function validateNumber(value, name,
- min = NumberNEGATIVE_INFINITY,
- max = NumberINFINITY) {
- if (typeof value !== 'number')
- throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
- if (value < min || value > max)
- throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value);
-}
-
-function getSocketType(type = 'udp4') {
- switch (type) {
- case 'udp4': return [AF_INET, false];
- case 'udp6': return [AF_INET6, false];
- case 'udp6-only': return [AF_INET6, true];
- }
- throw new ERR_INVALID_ARG_VALUE('options.type', type);
-}
-
-function defaultLookup(address, type) {
- const { lookup } = lazyDNS();
- return lookup(address || (type === 6 ? '::1' : '127.0.0.1'), type);
-}
-
-function validateCloseCode(code) {
- if (code != null && typeof code === 'object') {
- return {
- closeCode: code.code || NGTCP2_NO_ERROR,
- closeFamily: code.family || QUIC_ERROR_APPLICATION,
- };
- } else if (typeof code === 'number') {
- return {
- closeCode: code,
- closeFamily: QUIC_ERROR_APPLICATION,
- };
- }
- throw new ERR_INVALID_ARG_TYPE('code', ['number', 'Object'], code);
-}
-
-function validateLookup(lookup) {
- if (lookup) {
- validateFunction(lookup, 'options.lookup');
- }
-}
-
-function validatePreferredAddress(address) {
- if (address !== undefined) {
- validateObject(address, 'options.preferredAddress');
- validateString(address.address, 'options.preferredAddress.address');
- if (address.port !== undefined)
- validatePort(address.port, 'options.preferredAddress.port');
- getSocketType(address.type);
- }
- return address;
-}
-
-// Validate known transport parameters, ignoring any that are not
-// supported. Ensures that only supported parameters are passed on.
-function validateTransportParams(params) {
- const {
- activeConnectionIdLimit,
- maxStreamDataBidiLocal,
- maxStreamDataBidiRemote,
- maxStreamDataUni,
- maxData,
- maxStreamsBidi,
- maxStreamsUni,
- idleTimeout,
- maxUdpPayloadSize,
- maxAckDelay,
- preferredAddress,
- rejectUnauthorized,
- requestCert,
- congestionAlgorithm = 'reno',
- h3: {
- qpackMaxTableCapacity,
- qpackBlockedStreams,
- maxHeaderListSize,
- maxPushes,
- maxHeaderPairs,
- maxHeaderLength = getOptionValue('--max-http-header-size'),
- },
- } = { h3: {}, ...params };
-
- if (activeConnectionIdLimit !== undefined) {
- validateInteger(
- activeConnectionIdLimit,
- 'options.activeConnectionIdLimit',
- /* min */ 2,
- /* max */ 8);
- }
- if (maxStreamDataBidiLocal !== undefined) {
- validateInteger(
- maxStreamDataBidiLocal,
- 'options.maxStreamDataBidiLocal',
- /* min */ 0);
- }
- if (maxStreamDataBidiRemote !== undefined) {
- validateInteger(
- maxStreamDataBidiRemote,
- 'options.maxStreamDataBidiRemote',
- /* min */ 0);
- }
- if (maxStreamDataUni !== undefined) {
- validateInteger(
- maxStreamDataUni,
- 'options.maxStreamDataUni',
- /* min */ 0);
- }
- if (maxData !== undefined) {
- validateInteger(
- maxData,
- 'options.maxData',
- /* min */ 0);
- }
- if (maxStreamsBidi !== undefined) {
- validateInteger(
- maxStreamsBidi,
- 'options.maxStreamsBidi',
- /* min */ 0);
- }
- if (maxStreamsUni !== undefined) {
- validateInteger(
- maxStreamsUni,
- 'options.maxStreamsUni',
- /* min */ 0);
- }
- if (idleTimeout !== undefined) {
- validateInteger(
- idleTimeout,
- 'options.idleTimeout',
- /* min */ 0);
- }
- if (maxUdpPayloadSize !== undefined) {
- validateInteger(
- maxUdpPayloadSize,
- 'options.maxUdpPayloadSize',
- /* min */ 0);
- }
- if (maxAckDelay !== undefined) {
- validateInteger(
- maxAckDelay,
- 'options.maxAckDelay',
- /* min */ 0);
- }
- if (qpackMaxTableCapacity !== undefined) {
- validateInteger(
- qpackMaxTableCapacity,
- 'options.h3.qpackMaxTableCapacity',
- /* min */ 0);
- }
- if (qpackBlockedStreams !== undefined) {
- validateInteger(
- qpackBlockedStreams,
- 'options.h3.qpackBlockedStreams',
- /* min */ 0);
- }
- if (maxHeaderListSize !== undefined) {
- validateInteger(
- maxHeaderListSize,
- 'options.h3.maxHeaderListSize',
- /* min */ 0);
- }
- if (maxPushes !== undefined) {
- validateInteger(
- maxPushes,
- 'options.h3.maxPushes',
- /* min */ 0);
- }
- if (maxHeaderPairs !== undefined) {
- validateInteger(
- maxHeaderPairs,
- 'options.h3.maxHeaderPairs',
- /* min */ 0);
- }
- if (maxHeaderLength !== undefined) {
- validateInteger(
- maxHeaderLength,
- 'options.h3.maxHeaderLength',
- /* min */ 0);
- }
- let ccAlgo = NGTCP2_CC_ALGO_RENO;
- if (congestionAlgorithm !== undefined) {
- validateString(congestionAlgorithm, 'options.conjestionAlgorithm');
- switch (congestionAlgorithm) {
- case 'reno':
- // This is the default
- break;
- case 'cubic':
- ccAlgo = NGTCP2_CC_ALGO_CUBIC;
- break;
- default:
- throw new ERR_INVALID_ARG_VALUE(
- 'options.congestionAlgorithm',
- congestionAlgorithm,
- 'is not supported');
- }
- }
-
- validatePreferredAddress(preferredAddress);
-
- return {
- activeConnectionIdLimit,
- maxStreamDataBidiLocal,
- maxStreamDataBidiRemote,
- maxStreamDataUni,
- maxData,
- maxStreamsBidi,
- maxStreamsUni,
- idleTimeout,
- maxUdpPayloadSize,
- maxAckDelay,
- preferredAddress,
- rejectUnauthorized,
- requestCert,
- congestionAlgorithm: ccAlgo,
- h3: {
- qpackMaxTableCapacity,
- qpackBlockedStreams,
- maxHeaderListSize,
- maxPushes,
- maxHeaderPairs,
- maxHeaderLength,
- }
- };
-}
-
-function validateQuicClientSessionOptions(options = {}) {
- const {
- autoStart = true,
- address = 'localhost',
- alpn = '',
- dcid: dcid_value,
- minDHSize = 1024,
- ocspHandler,
- port = 0,
- preferredAddressPolicy = 'ignore',
- remoteTransportParams,
- servername = (isIP(address) ? '' : address),
- sessionTicket,
- verifyHostnameIdentity = true,
- qlog = false,
- highWaterMark,
- defaultEncoding,
- } = options;
-
- validateBoolean(autoStart, 'options.autoStart');
- validateNumber(minDHSize, 'options.minDHSize');
- validatePort(port, 'options.port');
- validateString(address, 'options.address');
- validateString(alpn, 'options.alpn');
- validateString(servername, 'options.servername');
-
- if (isIP(servername)) {
- throw new ERR_INVALID_ARG_VALUE(
- 'options.servername',
- servername,
- 'cannot be an IP address');
- }
-
- if (remoteTransportParams !== undefined)
- validateBuffer(remoteTransportParams, 'options.remoteTransportParams');
-
- if (sessionTicket !== undefined)
- validateBuffer(sessionTicket, 'options.sessionTicket');
-
- let dcid;
- if (dcid_value !== undefined) {
- if (typeof dcid_value === 'string') {
- // If it's a string, it must be a hex encoded string
- try {
- Buffer.from(dcid_value, 'hex');
- } catch {
- throw new ERR_INVALID_ARG_VALUE(
- 'options.dcid',
- dcid_value,
- 'is not a valid QUIC connection ID');
- }
- }
-
- validateBuffer(
- dcid_value,
- 'options.dcid',
- ['string', 'Buffer', 'TypedArray', 'DataView']);
-
- if (dcid_value.length > NGTCP2_MAX_CIDLEN ||
- dcid_value.length < NGTCP2_MIN_CIDLEN) {
- throw new ERR_INVALID_ARG_VALUE(
- 'options.dcid',
- dcid_value.toString('hex'),
- 'is not a valid QUIC connection ID'
- );
- }
-
- dcid = dcid_value;
- }
-
- if (preferredAddressPolicy !== undefined)
- validateString(preferredAddressPolicy, 'options.preferredAddressPolicy');
-
- validateBoolean(verifyHostnameIdentity, 'options.verifyHostnameIdentity');
- validateBoolean(qlog, 'options.qlog');
-
- if (ocspHandler !== undefined && typeof ocspHandler !== 'function') {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.ocspHandler',
- 'functon',
- ocspHandler);
- }
-
- return {
- autoStart,
- address,
- alpn,
- dcid,
- minDHSize,
- ocspHandler,
- port,
- preferredAddressPolicy:
- preferredAddressPolicy === 'accept' ?
- QUIC_PREFERRED_ADDRESS_USE :
- QUIC_PREFERRED_ADDRESS_IGNORE,
- remoteTransportParams,
- servername,
- sessionTicket,
- verifyHostnameIdentity,
- qlog,
- ...validateQuicStreamOptions({ highWaterMark, defaultEncoding })
- };
-}
-
-function validateQuicStreamOptions(options = {}) {
- validateObject(options);
- const {
- defaultEncoding = 'utf8',
- halfOpen,
- highWaterMark,
- } = options;
- if (!Buffer.isEncoding(defaultEncoding)) {
- throw new ERR_INVALID_ARG_VALUE(
- 'options.defaultEncoding',
- defaultEncoding,
- 'is not a valid encoding');
- }
- if (halfOpen !== undefined)
- validateBoolean(halfOpen, 'options.halfOpen');
- if (highWaterMark !== undefined) {
- validateInteger(
- highWaterMark,
- 'options.highWaterMark',
- /* min */ 0);
- }
- return {
- defaultEncoding,
- halfOpen,
- highWaterMark,
- };
-}
-
-function validateQuicEndpointOptions(options = {}, name = 'options') {
- validateObject(options, name);
- const {
- address,
- lookup,
- port = 0,
- reuseAddr = false,
- type = 'udp4',
- preferred = false,
- } = options;
- if (address !== undefined)
- validateString(address, 'options.address');
- validatePort(port, 'options.port');
- validateString(type, 'options.type');
- validateLookup(lookup);
- validateBoolean(reuseAddr, 'options.reuseAddr');
- validateBoolean(preferred, 'options.preferred');
- const [typeVal, ipv6Only] = getSocketType(type);
- return {
- type: typeVal,
- ipv6Only,
- address,
- lookup,
- port,
- preferred,
- reuseAddr,
- };
-}
-
-function validateQuicSocketOptions(options = {}) {
- validateObject(options, 'options');
-
- const {
- client = {},
- disableStatelessReset = false,
- endpoint = { port: 0, type: 'udp4' },
- lookup = defaultLookup,
- maxConnections = DEFAULT_MAX_CONNECTIONS,
- maxConnectionsPerHost = DEFAULT_MAX_CONNECTIONS_PER_HOST,
- maxStatelessResetsPerHost = DEFAULT_MAX_STATELESS_RESETS_PER_HOST,
- qlog = false,
- retryTokenTimeout = DEFAULT_RETRYTOKEN_EXPIRATION,
- server = {},
- statelessResetSecret,
- validateAddress = false,
- } = options;
-
- const { type } = validateQuicEndpointOptions(endpoint, 'options.endpoint');
- validateObject(client, 'options.client');
- validateObject(server, 'options.server');
- validateLookup(lookup);
- validateBoolean(validateAddress, 'options.validateAddress');
- validateBoolean(qlog, 'options.qlog');
- validateBoolean(disableStatelessReset, 'options.disableStatelessReset');
-
- if (retryTokenTimeout !== undefined) {
- validateInteger(
- retryTokenTimeout,
- 'options.retryTokenTimeout',
- /* min */ MIN_RETRYTOKEN_EXPIRATION,
- /* max */ MAX_RETRYTOKEN_EXPIRATION);
- }
- if (maxConnections !== undefined) {
- validateInteger(
- maxConnections,
- 'options.maxConnections',
- /* min */ 1);
- }
- if (maxConnectionsPerHost !== undefined) {
- validateInteger(
- maxConnectionsPerHost,
- 'options.maxConnectionsPerHost',
- /* min */ 1);
- }
- if (maxStatelessResetsPerHost !== undefined) {
- validateInteger(
- maxStatelessResetsPerHost,
- 'options.maxStatelessResetsPerHost',
- /* min */ 1);
- }
-
- if (statelessResetSecret !== undefined) {
- validateBuffer(statelessResetSecret, 'options.statelessResetSecret');
- if (statelessResetSecret.length !== 16)
- throw new ERR_INVALID_ARG_VALUE(
- 'options.statelessResetSecret',
- statelessResetSecret,
- 'must be exactly 16 bytes in length');
- }
-
- return {
- endpoint,
- client,
- lookup,
- maxConnections,
- maxConnectionsPerHost,
- maxStatelessResetsPerHost,
- retryTokenTimeout,
- server,
- type,
- validateAddress,
- qlog,
- statelessResetSecret,
- disableStatelessReset,
- };
-}
-
-function validateQuicSocketListenOptions(options = {}) {
- validateObject(options);
- const {
- alpn = NGHTTP3_ALPN_H3,
- defaultEncoding,
- highWaterMark,
- ocspHandler,
- clientHelloHandler,
- requestCert,
- rejectUnauthorized,
- lookup,
- } = options;
- validateString(alpn, 'options.alpn');
- if (rejectUnauthorized !== undefined)
- validateBoolean(rejectUnauthorized, 'options.rejectUnauthorized');
- if (requestCert !== undefined)
- validateBoolean(requestCert, 'options.requestCert');
- if (lookup !== undefined)
- validateLookup(lookup);
- if (ocspHandler !== undefined && typeof ocspHandler !== 'function') {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.ocspHandler',
- 'function',
- ocspHandler);
- }
- if (clientHelloHandler !== undefined &&
- typeof clientHelloHandler !== 'function') {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.clientHelloHandler',
- 'function',
- clientHelloHandler);
- }
- const transportParams = validateTransportParams(options);
-
- return {
- alpn,
- lookup,
- ocspHandler,
- clientHelloHandler,
- rejectUnauthorized,
- requestCert,
- transportParams,
- ...validateQuicStreamOptions({ highWaterMark, defaultEncoding })
- };
-}
-
-function validateQuicSocketConnectOptions(options = {}) {
- validateObject(options);
- const {
- type = 'udp4',
- address,
- lookup,
- } = options;
- if (address !== undefined)
- validateString(address, 'options.address');
- if (lookup !== undefined)
- validateLookup(lookup);
- const [typeVal] = getSocketType(type);
- return { type: typeVal, address, lookup };
-}
-
-function validateCreateSecureContextOptions(options = {}) {
- validateObject(options);
- const {
- ca,
- cert,
- ciphers = kDefaultQuicCiphers,
- clientCertEngine,
- crl,
- dhparam,
- ecdhCurve,
- groups = kDefaultGroups,
- honorCipherOrder,
- key,
- earlyData = true, // Early data is enabled by default
- passphrase,
- pfx,
- sessionIdContext,
- secureProtocol
- } = options;
- validateString(ciphers, 'option.ciphers');
- validateString(groups, 'option.groups');
- if (earlyData !== undefined)
- validateBoolean(earlyData, 'option.earlyData');
-
- // Additional validation occurs within the tls
- // createSecureContext function.
- return {
- ca,
- cert,
- ciphers,
- clientCertEngine,
- crl,
- dhparam,
- ecdhCurve,
- groups,
- honorCipherOrder,
- key,
- earlyData,
- passphrase,
- pfx,
- sessionIdContext,
- secureProtocol
- };
-}
-
-function setConfigField(buffer, val, index) {
- if (typeof val === 'number') {
- buffer[index] = val;
- return 1 << index;
- }
- return 0;
-}
-
-// Extracts configuration options and updates the aliased buffer
-// arrays that are used to communicate config choices to the c++
-// internals.
-function setTransportParams(config) {
- const {
- activeConnectionIdLimit,
- maxStreamDataBidiLocal,
- maxStreamDataBidiRemote,
- maxStreamDataUni,
- maxData,
- maxStreamsBidi,
- maxStreamsUni,
- idleTimeout,
- maxUdpPayloadSize,
- maxAckDelay,
- congestionAlgorithm,
- h3: {
- qpackMaxTableCapacity,
- qpackBlockedStreams,
- maxHeaderListSize,
- maxPushes,
- maxHeaderPairs,
- maxHeaderLength,
- },
- } = { h3: {}, ...config };
-
- // The const flags is a bitmap that is used to communicate whether or not a
- // given configuration value has been explicitly provided.
- const flags = setConfigField(sessionConfig,
- activeConnectionIdLimit,
- IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT) |
- setConfigField(sessionConfig,
- maxStreamDataBidiLocal,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL) |
- setConfigField(sessionConfig,
- maxStreamDataBidiRemote,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_REMOTE) |
- setConfigField(sessionConfig,
- maxStreamDataUni,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI) |
- setConfigField(sessionConfig,
- maxData,
- IDX_QUIC_SESSION_MAX_DATA) |
- setConfigField(sessionConfig,
- maxStreamsBidi,
- IDX_QUIC_SESSION_MAX_STREAMS_BIDI) |
- setConfigField(sessionConfig,
- maxStreamsUni,
- IDX_QUIC_SESSION_MAX_STREAMS_UNI) |
- setConfigField(sessionConfig,
- idleTimeout,
- IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT) |
- setConfigField(sessionConfig,
- maxAckDelay,
- IDX_QUIC_SESSION_MAX_ACK_DELAY) |
- setConfigField(sessionConfig,
- maxUdpPayloadSize,
- IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE) |
- setConfigField(sessionConfig,
- congestionAlgorithm,
- IDX_QUIC_SESSION_CC_ALGO);
-
- sessionConfig[IDX_QUIC_SESSION_CONFIG_COUNT] = flags;
-
- const h3flags = setConfigField(http3Config,
- qpackMaxTableCapacity,
- IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY) |
- setConfigField(http3Config,
- qpackBlockedStreams,
- IDX_HTTP3_QPACK_BLOCKED_STREAMS) |
- setConfigField(http3Config,
- maxHeaderListSize,
- IDX_HTTP3_MAX_HEADER_LIST_SIZE) |
- setConfigField(http3Config,
- maxPushes,
- IDX_HTTP3_MAX_PUSHES) |
- setConfigField(http3Config,
- maxHeaderPairs,
- IDX_HTTP3_MAX_HEADER_PAIRS) |
- setConfigField(http3Config,
- maxHeaderLength,
- IDX_HTTP3_MAX_HEADER_LENGTH);
-
- http3Config[IDX_HTTP3_CONFIG_COUNT] = h3flags;
-}
-
-// Some events that are emitted originate from the C++ internals and are
-// fairly expensive and optional. An aliased array buffer is used to
-// communicate that a handler has been added for the optional events
-// so that the C++ internals know there is an actual listener. The event
-// will not be emitted if there is no handler.
-function toggleListeners(state, event, on) {
- if (state === undefined)
- return;
- switch (event) {
- case 'keylog':
- state.keylogEnabled = on;
- break;
- case 'pathValidation':
- state.pathValidatedEnabled = on;
- break;
- case 'usePreferredAddress':
- state.usePreferredAddressEnabled = on;
- break;
- }
-}
-
-class QuicStreamSharedState {
- constructor(state) {
- this[kHandle] = Buffer.from(state);
- }
-
- get writeEnded() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_WRITE_ENDED));
- }
-
- set writeEnded(on) {
- this[kHandle].writeUInt8(on ? 1 : 0, IDX_QUICSTREAM_STATE_WRITE_ENDED);
- }
-
- get readStarted() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_READ_STARTED));
- }
-
- get readPaused() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_READ_PAUSED));
- }
-
- set readPaused(on) {
- this[kHandle].writeUInt8(on ? 1 : 0, IDX_QUICSTREAM_STATE_READ_PAUSED);
- }
-
- get readEnded() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_READ_ENDED));
- }
-
- set readEnded(on) {
- this[kHandle].writeUInt8(on ? 1 : 0, IDX_QUICSTREAM_STATE_READ_ENDED);
- }
-
- get finSent() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_FIN_SENT));
- }
-
- get finReceived() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSTREAM_STATE_FIN_RECEIVED));
- }
-}
-
-class QuicSocketSharedState {
- constructor(state) {
- this[kHandle] = Buffer.from(state);
- }
-
- get serverListening() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSOCKET_STATE_SERVER_LISTENING));
- }
-
- set serverListening(on) {
- this[kHandle].writeUInt8(on ? 1 : 0, IDX_QUICSOCKET_STATE_SERVER_LISTENING);
- }
-
- get serverBusy() {
- return Boolean(this[kHandle].readUInt8(IDX_QUICSOCKET_STATE_SERVER_BUSY));
- }
-
- set serverBusy(on) {
- this[kHandle].writeUInt8(on ? 1 : 0, IDX_QUICSOCKET_STATE_SERVER_BUSY);
- }
-
- get statelessResetDisabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSOCKET_STATE_STATELESS_RESET_DISABLED));
- }
-
- set statelessResetDisabled(on) {
- this[kHandle].writeUInt8(on ? 1 : 0,
- IDX_QUICSOCKET_STATE_STATELESS_RESET_DISABLED);
- }
-}
-
-// A utility class used to handle reading / modifying shared JS/C++
-// state associated with a QuicSession
-class QuicSessionSharedState {
- constructor(state) {
- this[kHandle] = Buffer.from(state);
- }
-
- get keylogEnabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_KEYLOG_ENABLED));
- }
-
- set keylogEnabled(on) {
- this[kHandle]
- .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_KEYLOG_ENABLED);
- }
-
- get clientHelloEnabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED));
- }
-
- set clientHelloEnabled(on) {
- this[kHandle]
- .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_CLIENT_HELLO_ENABLED);
- }
-
- get ocspEnabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_OCSP_ENABLED));
- }
-
- set ocspEnabled(on) {
- this[kHandle]
- .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_OCSP_ENABLED);
- }
-
- get pathValidatedEnabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED));
- }
-
- set pathValidatedEnabled(on) {
- this[kHandle]
- .writeUInt8(on ? 1 : 0, IDX_QUICSESSION_STATE_PATH_VALIDATED_ENABLED);
- }
-
- get usePreferredAddressEnabled() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED));
- }
-
- set usePreferredAddressEnabled(on) {
- this[kHandle]
- .writeUInt8(on ? 1 : 0,
- IDX_QUICSESSION_STATE_USE_PREFERRED_ADDRESS_ENABLED);
- }
-
- get handshakeConfirmed() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_HANDSHAKE_CONFIRMED));
- }
-
- get idleTimeout() {
- return Boolean(this[kHandle]
- .readUInt8(IDX_QUICSESSION_STATE_IDLE_TIMEOUT));
- }
-
- get maxStreamsBidi() {
- return Number(endianness === 'BE' ?
- this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI) :
- this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_STREAMS_BIDI));
- }
-
- get maxStreamsUni() {
- return Number(endianness === 'BE' ?
- this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_STREAMS_UNI) :
- this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_STREAMS_UNI));
- }
-
- get maxDataLeft() {
- return Number(endianness === 'BE' ?
- this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_MAX_DATA_LEFT) :
- this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_MAX_DATA_LEFT));
- }
-
- get bytesInFlight() {
- return Number(endianness === 'BE' ?
- this[kHandle].readBigInt64BE(IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT) :
- this[kHandle].readBigInt64LE(IDX_QUICSESSION_STATE_BYTES_IN_FLIGHT));
- }
-}
-
-class QLogStream extends Readable {
- constructor(handle) {
- super({ autoDestroy: true });
- this[kHandle] = handle;
- handle[owner_symbol] = this;
- handle.onread = onStreamRead;
- }
-
- _read() {
- if (this[kHandle])
- this[kHandle].readStart();
- }
-
- _destroy() {
- // Release the references on the handle so that
- // it can be garbage collected.
- this[kHandle][owner_symbol] = undefined;
- this[kHandle] = undefined;
- }
-
- [kUpdateTimer]() {
- // Does nothing
- }
-}
-
-function customInspect(self, obj, depth, options) {
- if (depth < 0)
- return self;
-
- const opts = {
- ...options,
- depth: options.depth == null ? null : options.depth - 1
- };
-
- return `${self.constructor.name} ${inspect(obj, opts)}`;
-}
-
-module.exports = {
- customInspect,
- getAllowUnauthorized,
- getSocketType,
- defaultLookup,
- setTransportParams,
- toggleListeners,
- validateNumber,
- validateCloseCode,
- validateTransportParams,
- validateQuicClientSessionOptions,
- validateQuicSocketOptions,
- validateQuicStreamOptions,
- validateQuicSocketListenOptions,
- validateQuicEndpointOptions,
- validateCreateSecureContextOptions,
- validateQuicSocketConnectOptions,
- QuicStreamSharedState,
- QuicSocketSharedState,
- QuicSessionSharedState,
- QLogStream,
-};
diff --git a/lib/net.js b/lib/net.js
index fcc911cb86..94aae1fa9f 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -45,9 +45,6 @@ let debug = require('internal/util/debuglog').debuglog('net', (fn) => {
debug = fn;
});
const {
- assertCrypto,
-} = require('internal/util');
-const {
isIP,
isIPv4,
isIPv6,
@@ -1777,25 +1774,3 @@ module.exports = {
Socket,
Stream: Socket, // Legacy naming
};
-
-if (process.versions.ngtcp2 !== undefined) {
- let quic;
-
- function lazyQuic() {
- if (quic === undefined) {
- assertCrypto();
- quic = require('internal/quic/core');
- process.emitWarning(
- 'The QUIC protocol is experimental and not yet ' +
- 'supported for production use',
- 'ExperimentalWarning');
- }
- return quic;
- }
-
- function createQuicSocket(...args) {
- return lazyQuic().createSocket(...args);
- }
-
- module.exports.createQuicSocket = createQuicSocket;
-}
diff --git a/node.gyp b/node.gyp
index a6ddb4e6dc..01ef5e3b6a 100644
--- a/node.gyp
+++ b/node.gyp
@@ -1,6 +1,5 @@
{
'variables': {
- 'experimental_quic': 'false',
'v8_use_siphash%': 0,
'v8_trace_maps%': 0,
'v8_enable_pointer_compression%': 0,
@@ -21,8 +20,6 @@
'node_shared_cares%': 'false',
'node_shared_libuv%': 'false',
'node_shared_nghttp2%': 'false',
- 'node_shared_ngtcp2%': 'false',
- 'node_shared_nghttp3%': 'false',
'node_use_openssl%': 'true',
'node_shared_openssl%': 'false',
'node_v8_options%': '',
@@ -211,8 +208,6 @@
'lib/internal/process/task_queues.js',
'lib/internal/querystring.js',
'lib/internal/readline/utils.js',
- 'lib/internal/quic/core.js',
- 'lib/internal/quic/util.js',
'lib/internal/repl.js',
'lib/internal/repl/await.js',
'lib/internal/repl/history.js',
@@ -980,38 +975,6 @@
'node_target_type=="executable"', {
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
}],
- [
- # We can only use QUIC if using our modified, static linked
- # OpenSSL because we have patched in the QUIC support.
- 'node_use_openssl=="true" and node_shared_openssl=="false" and experimental_quic==1', {
- 'defines': ['NODE_EXPERIMENTAL_QUIC=1'],
- 'sources': [
- 'src/node_bob.h',
- 'src/node_bob-inl.h',
- 'src/quic/node_quic_buffer.h',
- 'src/quic/node_quic_buffer-inl.h',
- 'src/quic/node_quic_crypto.h',
- 'src/quic/node_quic_session.h',
- 'src/quic/node_quic_session-inl.h',
- 'src/quic/node_quic_socket.h',
- 'src/quic/node_quic_socket-inl.h',
- 'src/quic/node_quic_stream.h',
- 'src/quic/node_quic_stream-inl.h',
- 'src/quic/node_quic_util.h',
- 'src/quic/node_quic_util-inl.h',
- 'src/quic/node_quic_state.h',
- 'src/quic/node_quic_default_application.h',
- 'src/quic/node_quic_http3_application.h',
- 'src/quic/node_quic_buffer.cc',
- 'src/quic/node_quic_crypto.cc',
- 'src/quic/node_quic_session.cc',
- 'src/quic/node_quic_socket.cc',
- 'src/quic/node_quic_stream.cc',
- 'src/quic/node_quic.cc',
- 'src/quic/node_quic_default_application.cc',
- 'src/quic/node_quic_http3_application.cc'
- ]
- }],
[ 'use_openssl_def==1', {
# TODO(bnoordhuis) Make all platforms export the same list of symbols.
# Teach mkssldef.py to generate linker maps that UNIX linkers understand.
@@ -1375,15 +1338,6 @@
'test/cctest/test_node_crypto.cc',
]
}],
- [ 'node_use_openssl=="true" and experimental_quic==1', {
- 'defines': [
- 'NODE_EXPERIMENTAL_QUIC=1',
- ],
- 'sources': [
- 'test/cctest/test_quic_buffer.cc',
- 'test/cctest/test_quic_cid.cc'
- ]
- }],
['v8_enable_inspector==1', {
'sources': [
'test/cctest/test_inspector_socket.cc',
@@ -1539,11 +1493,6 @@
'HAVE_OPENSSL=1',
],
}],
- [ 'node_use_openssl=="true" and experimental_quic==1', {
- 'defines': [
- 'NODE_EXPERIMENTAL_QUIC=1',
- ],
- }],
['v8_enable_inspector==1', {
'defines': [
'HAVE_INSPECTOR=1',
@@ -1598,11 +1547,6 @@
'HAVE_OPENSSL=1',
],
}],
- [ 'node_use_openssl=="true" and experimental_quic==1', {
- 'defines': [
- 'NODE_EXPERIMENTAL_QUIC=1',
- ],
- }],
['v8_enable_inspector==1', {
'defines': [
'HAVE_INSPECTOR=1',
diff --git a/node.gypi b/node.gypi
index dbe1b05cf5..43dbda7bbf 100644
--- a/node.gypi
+++ b/node.gypi
@@ -187,24 +187,6 @@
'dependencies': [ 'deps/nghttp2/nghttp2.gyp:nghttp2' ],
}],
- [
- 'experimental_quic==1', {
- 'conditions': [
- [
- 'node_shared_ngtcp2=="false"', {
- 'dependencies': [
- 'deps/ngtcp2/ngtcp2.gyp:ngtcp2',
- ]}
- ],
- [
- 'node_shared_nghttp3=="false"', {
- 'dependencies': [
- 'deps/nghttp3/nghttp3.gyp:nghttp3'
- ]}
- ]
- ]}
- ],
-
[ 'node_shared_brotli=="false"', {
'dependencies': [ 'deps/brotli/brotli.gyp:brotli' ],
}],
diff --git a/src/async_wrap.h b/src/async_wrap.h
index 76de08053b..522779d57a 100644
--- a/src/async_wrap.h
+++ b/src/async_wrap.h
@@ -60,12 +60,6 @@ namespace node {
V(PROCESSWRAP) \
V(PROMISE) \
V(QUERYWRAP) \
- V(QLOGSTREAM) \
- V(QUICCLIENTSESSION) \
- V(QUICSERVERSESSION) \
- V(QUICSENDWRAP) \
- V(QUICSOCKET) \
- V(QUICSTREAM) \
V(SHUTDOWNWRAP) \
V(SIGNALWRAP) \
V(STATWATCHER) \
diff --git a/src/env.h b/src/env.h
index 514a3871b4..829e2f9fb0 100644
--- a/src/env.h
+++ b/src/env.h
@@ -366,7 +366,6 @@ constexpr size_t kFsStatsBufferLength =
V(pubkey_string, "pubkey") \
V(public_exponent_string, "publicExponent") \
V(query_string, "query") \
- V(http3_alpn_string, "h3-29") \
V(rate_string, "rate") \
V(raw_string, "raw") \
V(read_host_object_string, "_readHostObject") \
@@ -435,16 +434,6 @@ constexpr size_t kFsStatsBufferLength =
V(x_forwarded_string, "x-forwarded-for") \
V(zero_return_string, "ZERO_RETURN")
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
-# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \
- V(quicclientsession_instance_template, v8::ObjectTemplate) \
- V(quicserversession_instance_template, v8::ObjectTemplate) \
- V(quicserverstream_instance_template, v8::ObjectTemplate) \
- V(quicsocketsendwrap_instance_template, v8::ObjectTemplate)
-#else
-# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
-#endif
-
#define ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V) \
V(async_wrap_ctor_template, v8::FunctionTemplate) \
V(async_wrap_object_ctor_template, v8::FunctionTemplate) \
@@ -479,34 +468,7 @@ constexpr size_t kFsStatsBufferLength =
V(tty_constructor_template, v8::FunctionTemplate) \
V(write_wrap_template, v8::ObjectTemplate) \
V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) \
- V(x509_constructor_template, v8::FunctionTemplate) \
- QUIC_ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
-
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
-# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
- V(quic_on_socket_close_function, v8::Function) \
- V(quic_on_socket_server_busy_function, v8::Function) \
- V(quic_on_session_cert_function, v8::Function) \
- V(quic_on_session_client_hello_function, v8::Function) \
- V(quic_on_session_close_function, v8::Function) \
- V(quic_on_session_handshake_function, v8::Function) \
- V(quic_on_session_keylog_function, v8::Function) \
- V(quic_on_session_path_validation_function, v8::Function) \
- V(quic_on_session_use_preferred_address_function, v8::Function) \
- V(quic_on_session_qlog_function, v8::Function) \
- V(quic_on_session_ready_function, v8::Function) \
- V(quic_on_session_status_function, v8::Function) \
- V(quic_on_session_ticket_function, v8::Function) \
- V(quic_on_session_version_negotiation_function, v8::Function) \
- V(quic_on_stream_close_function, v8::Function) \
- V(quic_on_stream_error_function, v8::Function) \
- V(quic_on_stream_ready_function, v8::Function) \
- V(quic_on_stream_reset_function, v8::Function) \
- V(quic_on_stream_headers_function, v8::Function) \
- V(quic_on_stream_blocked_function, v8::Function)
-#else
-# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
-#endif
+ V(x509_constructor_template, v8::FunctionTemplate)
#define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
V(async_hooks_after_function, v8::Function) \
@@ -563,8 +525,7 @@ constexpr size_t kFsStatsBufferLength =
V(tls_wrap_constructor_function, v8::Function) \
V(trace_category_state_function, v8::Function) \
V(udp_constructor_function, v8::Function) \
- V(url_constructor_function, v8::Function) \
- QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
+ V(url_constructor_function, v8::Function)
class Environment;
struct AllocatedBuffer;
diff --git a/src/node_binding.cc b/src/node_binding.cc
index 0db930adff..6c7ab4b21e 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -14,12 +14,6 @@
#define NODE_BUILTIN_OPENSSL_MODULES(V)
#endif
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
-#define NODE_BUILTIN_QUIC_MODULES(V) V(quic)
-#else
-#define NODE_BUILTIN_QUIC_MODULES(V)
-#endif
-
#if NODE_HAVE_I18N_SUPPORT
#define NODE_BUILTIN_ICU_MODULES(V) V(icu)
#else
@@ -98,7 +92,6 @@
#define NODE_BUILTIN_MODULES(V) \
NODE_BUILTIN_STANDARD_MODULES(V) \
NODE_BUILTIN_OPENSSL_MODULES(V) \
- NODE_BUILTIN_QUIC_MODULES(V) \
NODE_BUILTIN_ICU_MODULES(V) \
NODE_BUILTIN_PROFILER_MODULES(V) \
NODE_BUILTIN_DTRACE_MODULES(V)
diff --git a/src/node_errors.h b/src/node_errors.h
index 6158a968d2..984603c42e 100644
--- a/src/node_errors.h
+++ b/src/node_errors.h
@@ -78,8 +78,6 @@ void OnFatalError(const char* location, const char* message);
V(ERR_WASI_NOT_STARTED, Error) \
V(ERR_WORKER_INIT_FAILED, Error) \
V(ERR_PROTO_ACCESS, Error) \
- V(ERR_QUIC_CANNOT_SET_GROUPS, Error) \
- V(ERR_QUIC_FAILURE_SETTING_SNI_CONTEXT, Error)
#define V(code, type) \
inline v8::Local<v8::Value> code(v8::Isolate* isolate, \
@@ -156,9 +154,7 @@ void OnFatalError(const char* location, const char* message);
V(ERR_WORKER_INIT_FAILED, "Worker initialization failure") \
V(ERR_PROTO_ACCESS, \
"Accessing Object.prototype.__proto__ has been " \
- "disallowed with --disable-proto=throw") \
- V(ERR_QUIC_CANNOT_SET_GROUPS, "Cannot set groups") \
- V(ERR_QUIC_FAILURE_SETTING_SNI_CONTEXT, "Failure setting SNI context")
+ "disallowed with --disable-proto=throw")
#define V(code, message) \
inline v8::Local<v8::Value> code(v8::Isolate* isolate) { \
diff --git a/src/node_http_common.h b/src/node_http_common.h
index 8017c0d7aa..ad9f2a864e 100644
--- a/src/node_http_common.h
+++ b/src/node_http_common.h
@@ -270,7 +270,7 @@ class NgHeaders {
MaybeStackBuffer<char, 3000> buf_;
};
-// The ng libraries (nghttp2 and nghttp3) each use nearly identical
+// The ng libraries use nearly identical
// reference counted structures for retaining header name and value
// information in memory until the application is done with it.
// The NgRcBufPointer is an intelligent pointer capable of working
diff --git a/src/node_mem.h b/src/node_mem.h
index f8cdc20848..332d1cd1ef 100644
--- a/src/node_mem.h
+++ b/src/node_mem.h
@@ -8,7 +8,7 @@
namespace node {
namespace mem {
-// Both ngtcp2 and nghttp2 allow custom allocators that
+// nghttp2 allows custom allocators that
// follow exactly the same structure and behavior, but
// use different struct names. To allow for code re-use,
// the NgLibMemoryManager template class can be used for both.
diff --git a/src/node_metadata.cc b/src/node_metadata.cc
index e8864d3552..8d0a725de4 100644
--- a/src/node_metadata.cc
+++ b/src/node_metadata.cc
@@ -13,11 +13,6 @@
#include <openssl/opensslv.h>
#endif // HAVE_OPENSSL
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
-#include <ngtcp2/version.h>
-#include <nghttp3/version.h>
-#endif
-
#ifdef NODE_HAVE_I18N_SUPPORT
#include <unicode/timezone.h>
#include <unicode/ulocdata.h>
@@ -96,11 +91,6 @@ Metadata::Versions::Versions() {
openssl = GetOpenSSLVersion();
#endif
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
- ngtcp2 = NGTCP2_VERSION;
- nghttp3 = NGHTTP3_VERSION;
-#endif
-
#ifdef NODE_HAVE_I18N_SUPPORT
icu = U_ICU_VERSION;
unicode = U_UNICODE_VERSION;
diff --git a/src/node_metadata.h b/src/node_metadata.h
index 2a4571883d..bf7e5d3ff4 100644
--- a/src/node_metadata.h
+++ b/src/node_metadata.h
@@ -38,12 +38,6 @@ namespace node {
#define NODE_VERSIONS_KEY_CRYPTO(V)
#endif
-#if defined(NODE_EXPERIMENTAL_QUIC) && NODE_EXPERIMENTAL_QUIC
-#define NODE_VERSIONS_KEY_QUIC(V) V(ngtcp2) V(nghttp3)
-#else
-#define NODE_VERSIONS_KEY_QUIC(V)
-#endif
-
#ifdef NODE_HAVE_I18N_SUPPORT
#define NODE_VERSIONS_KEY_INTL(V) \
V(cldr) \
@@ -57,7 +51,6 @@ namespace node {
#define NODE_VERSIONS_KEYS(V) \
NODE_VERSIONS_KEYS_BASE(V) \
NODE_VERSIONS_KEY_CRYPTO(V) \
- NODE_VERSIONS_KEY_QUIC(V) \
NODE_VERSIONS_KEY_INTL(V)
class Metadata {
diff --git a/src/node_native_module.cc b/src/node_native_module.cc
index f7d73544d2..5a8cf12347 100644
--- a/src/node_native_module.cc
+++ b/src/node_native_module.cc
@@ -105,10 +105,6 @@ void NativeModuleLoader::InitializeModuleCategories() {
"internal/process/policy",
"internal/streams/lazy_transform",
#endif // !HAVE_OPENSSL
-#if !NODE_EXPERIMENTAL_QUIC
- "internal/quic/core",
- "internal/quic/util",
-#endif
"sys", // Deprecated.
"wasi", // Experimental.
"internal/test/binding",
diff --git a/src/quic/node_quic.cc b/src/quic/node_quic.cc
deleted file mode 100644
index f34c8669f9..0000000000
--- a/src/quic/node_quic.cc
+++ /dev/null
@@ -1,271 +0,0 @@
-#include "debug_utils-inl.h"
-#include "node.h"
-#include "env-inl.h"
-#include "crypto/crypto_context.h"
-#include "crypto/crypto_common.h"
-#include "node_errors.h"
-#include "node_process.h"
-#include "node_quic_crypto.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_stream-inl.h"
-#include "node_quic_state.h"
-#include "node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include "nghttp3/nghttp3.h"
-
-#include <memory>
-#include <utility>
-
-namespace node {
-
-using crypto::SecureContext;
-using v8::Context;
-using v8::Function;
-using v8::FunctionCallbackInfo;
-using v8::HandleScope;
-using v8::Isolate;
-using v8::Local;
-using v8::Object;
-using v8::Value;
-
-namespace quic {
-
-constexpr FastStringKey QuicState::binding_data_name;
-
-void QuicState::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("root_buffer", root_buffer);
-}
-
-namespace {
-// Register the JavaScript callbacks the internal binding will use to report
-// status and updates. This is called only once when the quic module is loaded.
-void QuicSetCallbacks(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- CHECK(args[0]->IsObject());
- Local<Object> obj = args[0].As<Object>();
-
-#define SETFUNCTION(name, callback) \
- do { \
- Local<Value> fn; \
- CHECK(obj->Get(env->context(), \
- FIXED_ONE_BYTE_STRING(env->isolate(), name)).ToLocal(&fn));\
- CHECK(fn->IsFunction()); \
- env->set_quic_on_##callback##_function(fn.As<Function>()); \
- } while (0)
-
- SETFUNCTION("onSocketClose", socket_close);
- SETFUNCTION("onSessionReady", session_ready);
- SETFUNCTION("onSessionCert", session_cert);
- SETFUNCTION("onSessionClientHello", session_client_hello);
- SETFUNCTION("onSessionClose", session_close);
- SETFUNCTION("onSessionHandshake", session_handshake);
- SETFUNCTION("onSessionKeylog", session_keylog);
- SETFUNCTION("onSessionUsePreferredAddress", session_use_preferred_address);
- SETFUNCTION("onSessionPathValidation", session_path_validation);
- SETFUNCTION("onSessionQlog", session_qlog);
- SETFUNCTION("onSessionStatus", session_status);
- SETFUNCTION("onSessionTicket", session_ticket);
- SETFUNCTION("onSessionVersionNegotiation", session_version_negotiation);
- SETFUNCTION("onStreamReady", stream_ready);
- SETFUNCTION("onStreamClose", stream_close);
- SETFUNCTION("onStreamError", stream_error);
- SETFUNCTION("onStreamReset", stream_reset);
- SETFUNCTION("onSocketServerBusy", socket_server_busy);
- SETFUNCTION("onStreamHeaders", stream_headers);
- SETFUNCTION("onStreamBlocked", stream_blocked);
-
-#undef SETFUNCTION
-}
-
-// Sets QUIC specific configuration options for the SecureContext.
-// It's entirely likely that there's a better way to do this, but
-// for now this works.
-template <ngtcp2_crypto_side side>
-void QuicInitSecureContext(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- CHECK(args[0]->IsObject()); // Secure Context
- CHECK(args[1]->IsString()); // groups
- CHECK(args[2]->IsBoolean()); // early data
-
- SecureContext* sc;
- ASSIGN_OR_RETURN_UNWRAP(&sc, args[0].As<Object>(),
- args.GetReturnValue().Set(UV_EBADF));
- const node::Utf8Value groups(env->isolate(), args[1]);
-
- bool early_data = args[2]->BooleanValue(env->isolate());
-
- InitializeSecureContext(
- BaseObjectPtr<SecureContext>(sc),
- early_data,
- side);
-
- if (!crypto::SetGroups(sc, *groups))
- THROW_ERR_QUIC_CANNOT_SET_GROUPS(env);
-}
-} // namespace
-
-void Initialize(Local<Object> target,
- Local<Value> unused,
- Local<Context> context,
- void* priv) {
- Environment* env = Environment::GetCurrent(context);
- Isolate* isolate = env->isolate();
- HandleScope handle_scope(isolate);
-
- HistogramBase::Initialize(env);
-
- QuicState* const state =
- env->AddBindingData<QuicState>(context, target);
- if (state == nullptr) return;
-
-#define SET_STATE_TYPEDARRAY(name, field) \
- target->Set(context, \
- FIXED_ONE_BYTE_STRING(isolate, (name)), \
- (field.GetJSArray())).Check()
- SET_STATE_TYPEDARRAY("sessionConfig", state->quicsessionconfig_buffer);
- SET_STATE_TYPEDARRAY("http3Config", state->http3config_buffer);
-#undef SET_STATE_TYPEDARRAY
-
- QuicSocket::Initialize(env, target, context);
- QuicEndpoint::Initialize(env, target, context);
- QuicSession::Initialize(env, target, context);
- QuicStream::Initialize(env, target, context);
-
- env->SetMethod(target,
- "setCallbacks",
- QuicSetCallbacks);
- env->SetMethod(target,
- "initSecureContext",
- QuicInitSecureContext<NGTCP2_CRYPTO_SIDE_SERVER>);
- env->SetMethod(target,
- "initSecureContextClient",
- QuicInitSecureContext<NGTCP2_CRYPTO_SIDE_CLIENT>);
-
- Local<Object> constants = Object::New(env->isolate());
-
-// TODO(@jasnell): Audit which constants are actually being used in JS
-#define QUIC_CONSTANTS(V) \
- V(DEFAULT_MAX_STREAM_DATA_BIDI_LOCAL) \
- V(DEFAULT_RETRYTOKEN_EXPIRATION) \
- V(DEFAULT_MAX_CONNECTIONS) \
- V(DEFAULT_MAX_CONNECTIONS_PER_HOST) \
- V(DEFAULT_MAX_STATELESS_RESETS_PER_HOST) \
- V(IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY) \
- V(IDX_HTTP3_QPACK_BLOCKED_STREAMS) \
- V(IDX_HTTP3_MAX_HEADER_LIST_SIZE) \
- V(IDX_HTTP3_MAX_PUSHES) \
- V(IDX_HTTP3_MAX_HEADER_PAIRS) \
- V(IDX_HTTP3_MAX_HEADER_LENGTH) \
- V(IDX_HTTP3_CONFIG_COUNT) \
- V(IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT) \
- V(IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT) \
- V(IDX_QUIC_SESSION_MAX_DATA) \
- V(IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL) \
- V(IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_REMOTE) \
- V(IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI) \
- V(IDX_QUIC_SESSION_MAX_STREAMS_BIDI) \
- V(IDX_QUIC_SESSION_MAX_STREAMS_UNI) \
- V(IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE) \
- V(IDX_QUIC_SESSION_ACK_DELAY_EXPONENT) \
- V(IDX_QUIC_SESSION_DISABLE_MIGRATION) \
- V(IDX_QUIC_SESSION_MAX_ACK_DELAY) \
- V(IDX_QUIC_SESSION_CC_ALGO) \
- V(IDX_QUIC_SESSION_CONFIG_COUNT) \
- V(MAX_RETRYTOKEN_EXPIRATION) \
- V(MIN_RETRYTOKEN_EXPIRATION) \
- V(NGTCP2_APP_NOERROR) \
- V(NGTCP2_PATH_VALIDATION_RESULT_FAILURE) \
- V(NGTCP2_PATH_VALIDATION_RESULT_SUCCESS) \
- V(NGTCP2_CC_ALGO_CUBIC) \
- V(NGTCP2_CC_ALGO_RENO) \
- V(QUIC_ERROR_APPLICATION) \
- V(QUIC_ERROR_CRYPTO) \
- V(QUIC_ERROR_SESSION) \
- V(QUIC_PREFERRED_ADDRESS_USE) \
- V(QUIC_PREFERRED_ADDRESS_IGNORE) \
- V(QUICCLIENTSESSION_OPTION_REQUEST_OCSP) \
- V(QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY) \
- V(QUICSERVERSESSION_OPTION_REJECT_UNAUTHORIZED) \
- V(QUICSERVERSESSION_OPTION_REQUEST_CERT) \
- V(QUICSOCKET_OPTIONS_VALIDATE_ADDRESS) \
- V(QUICSTREAM_HEADER_FLAGS_NONE) \
- V(QUICSTREAM_HEADER_FLAGS_TERMINAL) \
- V(QUICSTREAM_HEADERS_KIND_NONE) \
- V(QUICSTREAM_HEADERS_KIND_INFORMATIONAL) \
- V(QUICSTREAM_HEADERS_KIND_PUSH) \
- V(QUICSTREAM_HEADERS_KIND_INITIAL) \
- V(QUICSTREAM_HEADERS_KIND_TRAILING) \
- V(ERR_FAILED_TO_CREATE_SESSION) \
- V(UV_EBADF)
-
-#define V(id, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUICSESSION_STATE_##id);
- QUICSESSION_SHARED_STATE(V)
-#undef V
-
-#define V(id, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUICSOCKET_STATE_##id);
- QUICSOCKET_SHARED_STATE(V)
-#undef V
-
-#define V(id, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUICSTREAM_STATE_##id);
- QUICSTREAM_SHARED_STATE(V)
-#undef V
-
-#define V(name, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_STATS_##name);
- SESSION_STATS(V)
-#undef V
-
-#define V(name, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SOCKET_STATS_##name);
- SOCKET_STATS(V)
-#undef V
-
-#define V(name, _, __) \
- NODE_DEFINE_CONSTANT(constants, IDX_QUIC_STREAM_STATS_##name);
- STREAM_STATS(V)
-#undef V
-
-#define V(name) NODE_DEFINE_CONSTANT(constants, name);
- QUIC_CONSTANTS(V)
-#undef V
-
- NODE_DEFINE_CONSTANT(constants, NGTCP2_DEFAULT_MAX_PKTLEN);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_PROTO_VER);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_DEFAULT_MAX_ACK_DELAY);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_MAX_CIDLEN);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_MIN_CIDLEN);
-
- NODE_DEFINE_CONSTANT(constants, NGTCP2_NO_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_INTERNAL_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_CONNECTION_REFUSED);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_FLOW_CONTROL_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_STREAM_LIMIT_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_STREAM_STATE_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_FINAL_SIZE_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_FRAME_ENCODING_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_TRANSPORT_PARAMETER_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_CONNECTION_ID_LIMIT_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_PROTOCOL_VIOLATION);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_INVALID_TOKEN);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_APPLICATION_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_CRYPTO_BUFFER_EXCEEDED);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_KEY_UPDATE_ERROR);
- NODE_DEFINE_CONSTANT(constants, NGTCP2_CRYPTO_ERROR);
-
- NODE_DEFINE_CONSTANT(constants, AF_INET);
- NODE_DEFINE_CONSTANT(constants, AF_INET6);
- NODE_DEFINE_STRING_CONSTANT(constants,
- NODE_STRINGIFY_HELPER(NGHTTP3_ALPN_H3),
- NGHTTP3_ALPN_H3);
-
- target->Set(context, env->constants_string(), constants).FromJust();
-}
-
-} // namespace quic
-} // namespace node
-
-NODE_MODULE_CONTEXT_AWARE_INTERNAL(quic, node::quic::Initialize)
diff --git a/src/quic/node_quic_buffer-inl.h b/src/quic/node_quic_buffer-inl.h
deleted file mode 100644
index 25f130ac9f..0000000000
--- a/src/quic/node_quic_buffer-inl.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_BUFFER_INL_H_
-#define SRC_QUIC_NODE_QUIC_BUFFER_INL_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node_quic_buffer.h"
-#include "node_bob-inl.h"
-#include "util-inl.h"
-#include "uv.h"
-
-#include <algorithm>
-
-namespace node {
-
-namespace quic {
-
-QuicBufferChunk::QuicBufferChunk(size_t len)
- : data_buf_(len, 0),
- buf_(uv_buf_init(reinterpret_cast<char*>(data_buf_.data()), len)),
- length_(len),
- done_called_(true) {}
-
-QuicBufferChunk::QuicBufferChunk(uv_buf_t buf, DoneCB done)
- : buf_(buf),
- length_(buf.len) {
- if (done != nullptr)
- done_ = std::move(done);
-}
-
-QuicBufferChunk::~QuicBufferChunk() {
- CHECK(done_called_);
-}
-
-size_t QuicBufferChunk::Seek(size_t amount) {
- amount = std::min(amount, remaining());
- buf_.base += amount;
- buf_.len -= amount;
- return amount;
-}
-
-size_t QuicBufferChunk::Consume(size_t amount) {
- amount = std::min(amount, length_);
- length_ -= amount;
- return amount;
-}
-
-void QuicBufferChunk::Done(int status) {
- if (done_called_) return;
- done_called_ = true;
- if (done_ != nullptr)
- std::move(done_)(status);
-}
-
-QuicBuffer::QuicBuffer(QuicBuffer&& src) noexcept
- : head_(src.head_),
- tail_(src.tail_),
- ended_(src.ended_),
- length_(src.length_) {
- root_ = std::move(src.root_);
- src.head_ = nullptr;
- src.tail_ = nullptr;
- src.length_ = 0;
- src.remaining_ = 0;
- src.ended_ = false;
-}
-
-QuicBuffer& QuicBuffer::operator=(QuicBuffer&& src) noexcept {
- if (this == &src) return *this;
- this->~QuicBuffer();
- return *new(this) QuicBuffer(std::move(src));
-}
-
-bool QuicBuffer::is_empty(uv_buf_t buf) {
- DCHECK_IMPLIES(buf.base == nullptr, buf.len == 0);
- return buf.len == 0;
-}
-
-size_t QuicBuffer::Consume(size_t amount) {
- return Consume(0, amount);
-}
-
-size_t QuicBuffer::Cancel(int status) {
- if (canceled_) return 0;
- canceled_ = true;
- size_t t = Consume(status, length());
- return t;
-}
-
-void QuicBuffer::Push(uv_buf_t buf, DoneCB done) {
- std::unique_ptr<QuicBufferChunk> chunk =
- std::make_unique<QuicBufferChunk>(buf, done);
- Push(std::move(chunk));
-}
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-#endif // SRC_QUIC_NODE_QUIC_BUFFER_INL_H_
diff --git a/src/quic/node_quic_buffer.cc b/src/quic/node_quic_buffer.cc
deleted file mode 100644
index ebe230271a..0000000000
--- a/src/quic/node_quic_buffer.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-#include "node_quic_buffer-inl.h" // NOLINT(build/include)
-#include "node_bob-inl.h"
-#include "util.h"
-#include "uv.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-namespace node {
-namespace quic {
-
-void QuicBufferChunk::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("buf", data_buf_);
- tracker->TrackField("next", next_);
-}
-
-size_t QuicBuffer::Push(uv_buf_t* bufs, size_t nbufs, DoneCB done) {
- size_t len = 0;
- if (UNLIKELY(nbufs == 0)) {
- done(0);
- return 0;
- }
- DCHECK_NOT_NULL(bufs);
- size_t n = 0;
- while (nbufs > 1) {
- if (!is_empty(bufs[n])) {
- Push(bufs[n]);
- len += bufs[n].len;
- }
- n++;
- nbufs--;
- }
- if (!is_empty(bufs[n])) {
- Push(bufs[n], done);
- len += bufs[n].len;
- }
- // Special case if all the bufs were empty.
- if (UNLIKELY(len == 0))
- done(0);
-
- return len;
-}
-
-void QuicBuffer::Push(std::unique_ptr<QuicBufferChunk> chunk) {
- CHECK(!ended_);
- length_ += chunk->remaining();
- remaining_ += chunk->remaining();
- if (!tail_) {
- root_ = std::move(chunk);
- head_ = tail_ = root_.get();
- } else {
- tail_->next_ = std::move(chunk);
- tail_ = tail_->next_.get();
- if (!head_)
- head_ = tail_;
- }
-}
-
-size_t QuicBuffer::Seek(size_t amount) {
- size_t len = 0;
- while (head_ && amount > 0) {
- size_t amt = head_->Seek(amount);
- amount -= amt;
- len += amt;
- remaining_ -= amt;
- if (head_->remaining())
- break;
- head_ = head_->next_.get();
- }
- return len;
-}
-
-bool QuicBuffer::Pop(int status) {
- if (!root_)
- return false;
- std::unique_ptr<QuicBufferChunk> root(std::move(root_));
- root_ = std::move(root.get()->next_);
-
- if (head_ == root.get())
- head_ = root_.get();
- if (tail_ == root.get())
- tail_ = root_.get();
-
- root->Done(status);
- return true;
-}
-
-size_t QuicBuffer::Consume(int status, size_t amount) {
- size_t amt = std::min(amount, length_);
- size_t len = 0;
- while (root_ && amt > 0) {
- auto root = root_.get();
- size_t consumed = root->Consume(amt);
- len += consumed;
- length_ -= consumed;
- amt -= consumed;
- if (root->length() > 0)
- break;
- Pop(status);
- }
- return len;
-}
-
-void QuicBuffer::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("root", root_);
-}
-
-int QuicBuffer::DoPull(
- bob::Next<ngtcp2_vec> next,
- int options,
- ngtcp2_vec* data,
- size_t count,
- size_t max_count_hint) {
- size_t len = 0;
- size_t numbytes = 0;
- int status = bob::Status::STATUS_CONTINUE;
-
- // There's no data to read.
- if (!remaining() || head_ == nullptr) {
- status = is_ended() ?
- bob::Status::STATUS_END :
- bob::Status::STATUS_BLOCK;
- std::move(next)(status, nullptr, 0, [](size_t len) {});
- return status;
- }
-
- // Ensure that there's storage space.
- MaybeStackBuffer<ngtcp2_vec, kMaxVectorCount> vec;
- if (data == nullptr || count == 0) {
- vec.AllocateSufficientStorage(max_count_hint);
- data = vec.out();
- } else {
- max_count_hint = std::min(count, max_count_hint);
- }
-
- // Build the list of buffers.
- QuicBufferChunk* pos = head_;
- while (pos != nullptr && len < max_count_hint) {
- data[len].base = reinterpret_cast<uint8_t*>(pos->buf().base);
- data[len].len = pos->buf().len;
- numbytes += data[len].len;
- len++;
- pos = pos->next_.get();
- }
-
- // If the buffer is ended, and the number of bytes
- // matches the total remaining and OPTIONS_END is
- // used, set the status to STATUS_END.
- if (is_ended() &&
- numbytes == remaining() &&
- options & bob::OPTIONS_END)
- status = bob::Status::STATUS_END;
-
- // Pass the data back out to the caller.
- std::move(next)(
- status,
- data,
- len,
- [this](size_t len) { Seek(len); });
-
- return status;
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_buffer.h b/src/quic/node_quic_buffer.h
deleted file mode 100644
index 3d81a28176..0000000000
--- a/src/quic/node_quic_buffer.h
+++ /dev/null
@@ -1,239 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_BUFFER_H_
-#define SRC_QUIC_NODE_QUIC_BUFFER_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "memory_tracker-inl.h"
-#include "ngtcp2/ngtcp2.h"
-#include "node.h"
-#include "node_bob.h"
-#include "node_internals.h"
-#include "util.h"
-#include "uv.h"
-
-#include <vector>
-
-namespace node {
-namespace quic {
-
-class QuicBuffer;
-
-constexpr size_t kMaxVectorCount = 16;
-
-using DoneCB = std::function<void(int)>;
-
-// When data is sent over QUIC, we are required to retain it in memory
-// until we receive an acknowledgement that it has been successfully
-// received. The QuicBuffer object is what we use to handle that
-// and track until it is acknowledged. To understand the QuicBuffer
-// object itself, it is important to understand how ngtcp2 and nghttp3
-// handle data that is given to it to serialize into QUIC packets.
-//
-// An individual QUIC packet may contain multiple QUIC frames. Whenever
-// we create a QUIC packet, we really have no idea what frames are going
-// to be encoded or how much buffered handshake or stream data is going
-// to be included within that QuicPacket. If there is buffered data
-// available for a stream, we provide an array of pointers to that data
-// and an indication about how much data is available, then we leave it
-// entirely up to ngtcp2 and nghttp3 to determine how much of the data
-// to encode into the QUIC packet. It is only *after* the QUIC packet
-// is encoded that we can know how much was actually written.
-//
-// Once written to a QUIC Packet, we have to keep the data in memory
-// until an acknowledgement is received. In QUIC, acknowledgements are
-// received per range of packets.
-//
-// QuicBuffer is complicated because it needs to be able to accomplish
-// three things: (a) buffering uv_buf_t instances passed down from
-// JavaScript without memcpy and keeping track of the Write callback
-// associated with each, (b) tracking what data has already been
-// encoded in a QUIC packet and what data is remaining to be read, and
-// (c) tracking which data has been acknowledged and which hasn't.
-// QuicBuffer is further complicated by design quirks and limitations
-// of the StreamBase API and how it interacts with the JavaScript side.
-//
-// QuicBuffer is a linked list of QuicBufferChunk instances.
-// A single QuicBufferChunk wraps a single non-zero-length uv_buf_t.
-// When the QuicBufferChunk is created, we capture the total length
-// of the buffer and the total number of bytes remaining to be sent.
-// Initially, these numbers are identical.
-//
-// When data is encoded into a QuicPacket, we advance the QuicBufferChunk's
-// remaining-to-be-read by the number of bytes actually encoded. If there
-// are no more bytes remaining to be encoded, we move to the next chunk
-// in the linked list.
-//
-// When an acknowledgement is received, we decrement the QuicBufferChunk's
-// length by the number of acknowledged bytes. Once the unacknowledged
-// length reaches 0, we invoke the callback function associated with the
-// QuicBufferChunk (if any).
-//
-// QuicStream is a StreamBase implementation. For every DoWrite call,
-// it receives one or more uv_buf_t instances in a single batch associated
-// with a single write callback. For each uv_buf_t DoWrite gets, a
-// corresponding QuicBufferChunk is added to the QuicBuffer, with the
-// callback associated with the final chunk added to the list.
-
-
-// A QuicBufferChunk contains the actual buffered data
-// along with a callback to be called when the data has
-// been consumed.
-//
-// Any given chunk has a remaining-to-be-acknowledged length (length()) and a
-// remaining-to-be-read-length (remaining()). The former tracks the number
-// of bytes that have yet to be acknowledged by the QUIC peer. Once the
-// remaining-to-be-acknowledged length reaches zero, the done callback
-// associated with the QuicBufferChunk can be called and the QuicBufferChunk
-// can be discarded. The remaining-to-be-read length is adjusted as data is
-// serialized into QUIC packets and sent.
-// The remaining-to-be-acknowledged length is adjusted using consume(),
-// while the remaining-to-be-ead length is adjusted using seek().
-class QuicBufferChunk final : public MemoryRetainer {
- public:
- // Default non-op done handler.
- static void default_done(int status) {}
-
- // In this variant, the QuicBufferChunk owns the underlying
- // data storage within a vector. The data will be
- // freed when the QuicBufferChunk is destroyed.
- inline explicit QuicBufferChunk(size_t len);
-
- // In this variant, the QuicBufferChunk only maintains a
- // pointer to the underlying data buffer. The QuicBufferChunk
- // does not take ownership of the buffer. The done callback
- // is invoked to let the caller know when the chunk is no
- // longer being used.
- inline QuicBufferChunk(uv_buf_t buf_, DoneCB done_);
-
- inline ~QuicBufferChunk() override;
-
- // Invokes the done callback associated with the QuicBufferChunk.
- inline void Done(int status);
-
- // length() provides the remaining-to-be-acknowledged length.
- // The QuicBufferChunk must be retained in memory while this
- // count is greater than zero. The length is adjusted by
- // calling Consume();
- inline size_t length() const { return length_; }
-
- // remaining() provides the remaining-to-be-read length number of bytes.
- // The length is adjusted by calling Seek()
- inline size_t remaining() const { return buf_.len; }
-
- // Consumes (acknowledges) the given number of bytes. If amount
- // is greater than length(), only length() bytes are consumed.
- // Returns the actual number of bytes consumed.
- inline size_t Consume(size_t amount);
-
- // Seeks (reads) the given number of bytes. If amount is greater
- // than remaining(), only remaining() bytes are read. Returns
- // the actual number of bytes read.
- inline size_t Seek(size_t amount);
-
- uint8_t* out() { return reinterpret_cast<uint8_t*>(buf_.base); }
- uv_buf_t buf() { return buf_; }
- const uv_buf_t buf() const { return buf_; }
-
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_MEMORY_INFO_NAME(QuicBufferChunk)
- SET_SELF_SIZE(QuicBufferChunk)
-
- private:
- std::vector<uint8_t> data_buf_;
- uv_buf_t buf_;
- DoneCB done_ = default_done;
- size_t length_ = 0;
- bool done_called_ = false;
- std::unique_ptr<QuicBufferChunk> next_;
-
- friend class QuicBuffer;
-};
-
-class QuicBuffer final : public bob::SourceImpl<ngtcp2_vec>,
- public MemoryRetainer {
- public:
- QuicBuffer() = default;
-
- inline QuicBuffer(QuicBuffer&& src) noexcept;
- inline QuicBuffer& operator=(QuicBuffer&& src) noexcept;
-
- ~QuicBuffer() override {
- Cancel(); // Cancel the remaining data
- CHECK_EQ(length_, 0);
- }
-
- // Marks the QuicBuffer as having ended, preventing new QuicBufferChunk
- // instances from being appended to the linked list and allowing the
- // Pull operation to know when to signal that the flow of data is
- // completed.
- void End() { ended_ = true; }
- bool is_ended() const { return ended_; }
-
- // Push one or more uv_buf_t instances into the buffer.
- // the DoneCB callback will be invoked when the last
- // uv_buf_t in the bufs array is consumed and popped out
- // of the internal linked list. Ownership of the uv_buf_t
- // remains with the caller.
- size_t Push(
- uv_buf_t* bufs,
- size_t nbufs,
- DoneCB done = QuicBufferChunk::default_done);
-
- // Pushes a single QuicBufferChunk into the linked list
- void Push(std::unique_ptr<QuicBufferChunk> chunk);
-
- // Consume the given number of bytes within the buffer. If amount
- // is greater than length(), length() bytes are consumed. Returns
- // the actual number of bytes consumed.
- inline size_t Consume(size_t amount);
-
- // Cancels the remaining bytes within the buffer.
- inline size_t Cancel(int status = UV_ECANCELED);
-
- // Seeks (reads) the given number of bytes. If amount is greater
- // than remaining(), seeks remaining() bytes. Returns the actual
- // number of bytes read.
- size_t Seek(size_t amount);
-
- // The total number of unacknowledged bytes remaining.
- size_t length() const { return length_; }
-
- // The total number of unread bytes remaining.
- size_t remaining() const { return remaining_; }
-
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_MEMORY_INFO_NAME(QuicBuffer);
- SET_SELF_SIZE(QuicBuffer);
-
- protected:
- int DoPull(
- bob::Next<ngtcp2_vec> next,
- int options,
- ngtcp2_vec* data,
- size_t count,
- size_t max_count_hint) override;
-
- private:
- inline static bool is_empty(uv_buf_t buf);
- size_t Consume(int status, size_t amount);
- bool Pop(int status = 0);
- inline void Push(uv_buf_t buf, DoneCB done = nullptr);
-
- std::unique_ptr<QuicBufferChunk> root_;
- QuicBufferChunk* head_ = nullptr; // Current Read Position
- QuicBufferChunk* tail_ = nullptr; // Current Write Position
-
- bool canceled_ = false;
- bool ended_ = false;
- size_t length_ = 0;
- size_t remaining_ = 0;
-
- friend class QuicBufferChunk;
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_BUFFER_H_
diff --git a/src/quic/node_quic_crypto.cc b/src/quic/node_quic_crypto.cc
deleted file mode 100644
index 74bb4f1878..0000000000
--- a/src/quic/node_quic_crypto.cc
+++ /dev/null
@@ -1,748 +0,0 @@
-#include "node_quic_crypto.h"
-#include "env-inl.h"
-#include "node_crypto.h"
-#include "crypto/crypto_util.h"
-#include "crypto/crypto_context.h"
-#include "crypto/crypto_common.h"
-#include "node_process.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include "node_url.h"
-#include "string_bytes.h"
-#include "v8.h"
-#include "util-inl.h"
-
-#include <ngtcp2/ngtcp2.h>
-#include <ngtcp2/ngtcp2_crypto.h>
-#include <nghttp3/nghttp3.h> // NGHTTP3_ALPN_H3
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-#include <openssl/ssl.h>
-#include <openssl/x509v3.h>
-
-#include <iterator>
-#include <numeric>
-#include <unordered_map>
-#include <string>
-#include <sstream>
-#include <vector>
-
-namespace node {
-
-using crypto::EntropySource;
-using v8::Local;
-using v8::Value;
-
-namespace quic {
-
-bool SessionTicketAppData::Set(const uint8_t* data, size_t len) {
- if (set_)
- return false;
- set_ = true;
- SSL_SESSION_set1_ticket_appdata(session_, data, len);
- return set_;
-}
-
-bool SessionTicketAppData::Get(uint8_t** data, size_t* len) const {
- return SSL_SESSION_get0_ticket_appdata(
- session_,
- reinterpret_cast<void**>(data),
- len) == 1;
-}
-
-namespace {
-constexpr int kCryptoTokenKeylen = 32;
-constexpr int kCryptoTokenIvlen = 32;
-
-// Used solely to derive the keys used to generate and
-// validate retry tokens. The implementation of this is
-// Node.js specific. We use the current implementation
-// because it is simple.
-bool DeriveTokenKey(
- uint8_t* token_key,
- uint8_t* token_iv,
- const uint8_t* rand_data,
- size_t rand_datalen,
- const ngtcp2_crypto_ctx& ctx,
- const uint8_t* token_secret) {
- static constexpr int kCryptoTokenSecretlen = 32;
- uint8_t secret[kCryptoTokenSecretlen];
-
- return
- NGTCP2_OK(ngtcp2_crypto_hkdf_extract(
- secret,
- &ctx.md,
- token_secret,
- kTokenSecretLen,
- rand_data,
- rand_datalen)) &&
- NGTCP2_OK(ngtcp2_crypto_derive_packet_protection_key(
- token_key,
- token_iv,
- nullptr,
- &ctx.aead,
- &ctx.md,
- secret,
- kCryptoTokenSecretlen));
-}
-
-// Retry tokens are generated only by QUIC servers. They
-// are opaque to QUIC clients and must not be guessable by
-// on- or off-path attackers. A QUIC server sends a RETRY
-// token as a way of initiating explicit path validation
-// with a client in response to an initial QUIC packet.
-// The client, upon receiving a RETRY, must abandon the
-// initial connection attempt and try again, including the
-// received retry token in the new initial packet sent to
-// the server. If the server is performing explicit
-// valiation, it will look for the presence of the retry
-// token and validate it if found. The internal structure
-// of the retry token must be meaningful to the server,
-// and the server must be able to validate the token without
-// relying on any state left over from the previous connection
-// attempt. The implementation here is entirely Node.js
-// specific.
-//
-// The token is generated by:
-// 1. Appending the raw bytes of given socket address, the current
-// timestamp, and the original CID together into a single byte
-// array.
-// 2. Generating a block of random data that is used together with
-// the token secret to cryptographically derive an encryption key.
-// 3. Encrypting the byte array from step 1 using the encryption key
-// from step 2.
-// 4. Appending random data generated in step 2 to the token.
-//
-// The token secret must be kept secret on the QUIC server that
-// generated the retry. When multiple QUIC servers are used in a
-// cluster, it cannot be guaranteed that the same QUIC server
-// instance will receive the subsequent new Initial packet. Therefore,
-// all QUIC servers in the cluster should either share or be aware
-// of the same token secret or a mechanism needs to be implemented
-// to ensure that subsequent packets are routed to the same QUIC
-// server instance.
-//
-// A malicious peer could attempt to guess the token secret by
-// sending a large number specially crafted RETRY-eliciting packets
-// to a server then analyzing the resulting retry tokens. To reduce
-// the possibility of such attacks, the current implementation of
-// QuicSocket generates the token secret randomly for each instance,
-// and the number of RETRY responses sent to a given remote address
-// should be limited. Such attacks should be of little actual value
-// in most cases.
-bool GenerateRetryToken(
- uint8_t* token,
- size_t* tokenlen,
- const SocketAddress& addr,
- const QuicCID& ocid,
- const uint8_t* token_secret) {
- std::array<uint8_t, 4096> plaintext;
- uint8_t rand_data[kTokenRandLen];
- uint8_t token_key[kCryptoTokenKeylen];
- uint8_t token_iv[kCryptoTokenIvlen];
-
- ngtcp2_crypto_ctx ctx;
- ngtcp2_crypto_ctx_initial(&ctx);
- size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(&ctx.aead);
- uint64_t now = uv_hrtime();
-
- auto p = std::begin(plaintext);
- p = std::copy_n(addr.raw(), addr.length(), p);
- p = std::copy_n(reinterpret_cast<uint8_t*>(&now), sizeof(uint64_t), p);
- p = std::copy_n(ocid->data, ocid->datalen, p);
-
- EntropySource(rand_data, kTokenRandLen);
-
- if (!DeriveTokenKey(
- token_key,
- token_iv,
- rand_data,
- kTokenRandLen,
- ctx,
- token_secret)) {
- return false;
- }
-
- ngtcp2_crypto_aead_ctx aead_ctx;
- if (NGTCP2_ERR(ngtcp2_crypto_aead_ctx_encrypt_init(
- &aead_ctx,
- &ctx.aead,
- token_key,
- ivlen))) {
- return false;
- }
-
- size_t plaintextlen = std::distance(std::begin(plaintext), p);
- if (NGTCP2_ERR(ngtcp2_crypto_encrypt(
- token,
- &ctx.aead,
- &aead_ctx,
- plaintext.data(),
- plaintextlen,
- token_iv,
- ivlen,
- addr.raw(),
- addr.length()))) {
- return false;
- }
-
- *tokenlen = plaintextlen + ngtcp2_crypto_aead_taglen(&ctx.aead);
- memcpy(token + (*tokenlen), rand_data, kTokenRandLen);
- *tokenlen += kTokenRandLen;
- return true;
-}
-} // namespace
-
-// A stateless reset token is used when a QUIC endpoint receives a
-// QUIC packet with a short header but the associated connection ID
-// cannot be matched to any known QuicSession. In such cases, the
-// receiver may choose to send a subtle opaque indication to the
-// sending peer that state for the QuicSession has apparently been
-// lost. For any on- or off- path attacker, a stateless reset packet
-// resembles any other QUIC packet with a short header. In order to
-// be successfully handled as a stateless reset, the peer must have
-// already seen a reset token issued to it associated with the given
-// CID. The token itself is opaque to the peer that receives is but
-// must be possible to statelessly recreate by the peer that
-// originally created it. The actual implementation is Node.js
-// specific but we currently defer to a utility function provided
-// by ngtcp2.
-bool GenerateResetToken(
- uint8_t* token,
- const uint8_t* secret,
- const QuicCID& cid) {
- ngtcp2_crypto_ctx ctx;
- ngtcp2_crypto_ctx_initial(&ctx);
- return NGTCP2_OK(ngtcp2_crypto_generate_stateless_reset_token(
- token,
- &ctx.md,
- secret,
- NGTCP2_STATELESS_RESET_TOKENLEN,
- cid.cid()));
-}
-
-// Generates a RETRY packet. See the notes for GenerateRetryToken for details.
-std::unique_ptr<QuicPacket> GenerateRetryPacket(
- const uint8_t* token_secret,
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr) {
-
- uint8_t token[256];
- size_t tokenlen = sizeof(token);
-
- if (!GenerateRetryToken(token, &tokenlen, remote_addr, dcid, token_secret))
- return {};
-
- QuicCID cid;
- EntropySource(cid.data(), kScidLen);
- cid.set_length(kScidLen);
-
- size_t pktlen = tokenlen + (2 * NGTCP2_MAX_CIDLEN) + scid.length() + 8;
-
- auto packet = QuicPacket::Create("retry", pktlen);
- ssize_t nwrite =
- ngtcp2_crypto_write_retry(
- packet->data(),
- NGTCP2_MAX_PKTLEN_IPV4,
- scid.cid(),
- cid.cid(),
- dcid.cid(),
- token,
- tokenlen);
- if (nwrite <= 0)
- return {};
- packet->set_length(nwrite);
- return packet;
-}
-
-// Validates a retry token included in the given header. This will return
-// true if the token cannot be validated, false otherwise. A token is
-// valid if it can be successfully decrypted using the key derived from
-// random data embedded in the token, the structure of the token matches
-// that generated by the GenerateRetryToken function, and the token was
-// not generated earlier than now - verification_expiration. If validation
-// is successful, ocid will be updated to the original connection ID encoded
-// in the encrypted token.
-bool InvalidRetryToken(
- const ngtcp2_vec& token,
- const SocketAddress& addr,
- QuicCID* ocid,
- const uint8_t* token_secret,
- uint64_t verification_expiration) {
-
- if (token.len < kTokenRandLen)
- return true;
-
- ngtcp2_crypto_ctx ctx;
- ngtcp2_crypto_ctx_initial(&ctx);
-
- size_t ivlen = ngtcp2_crypto_packet_protection_ivlen(&ctx.aead);
-
- size_t ciphertextlen = token.len - kTokenRandLen;
- const uint8_t* ciphertext = token.base;
- const uint8_t* rand_data = token.base + ciphertextlen;
-
- uint8_t token_key[kCryptoTokenKeylen];
- uint8_t token_iv[kCryptoTokenIvlen];
-
- if (!DeriveTokenKey(
- token_key,
- token_iv,
- rand_data,
- kTokenRandLen,
- ctx,
- token_secret)) {
- return true;
- }
-
- uint8_t plaintext[4096];
-
- ngtcp2_crypto_aead_ctx aead_ctx;
- if (NGTCP2_ERR(ngtcp2_crypto_aead_ctx_decrypt_init(
- &aead_ctx,
- &ctx.aead,
- token_key,
- ivlen))) {
- return true;
- }
-
- if (NGTCP2_ERR(ngtcp2_crypto_decrypt(
- plaintext,
- &ctx.aead,
- &aead_ctx,
- ciphertext,
- ciphertextlen,
- token_iv,
- ivlen,
- addr.raw(),
- addr.length()))) {
- return true;
- }
-
- size_t plaintextlen = ciphertextlen - ngtcp2_crypto_aead_taglen(&ctx.aead);
- if (plaintextlen < addr.length() + sizeof(uint64_t))
- return true;
-
- ssize_t cil = plaintextlen - addr.length() - sizeof(uint64_t);
- if ((cil != 0 && (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN)) ||
- memcmp(plaintext, addr.raw(), addr.length()) != 0) {
- return true;
- }
-
- uint64_t t;
- memcpy(&t, plaintext + addr.length(), sizeof(uint64_t));
-
- // 10-second window by default, but configurable for each
- // QuicSocket instance with a MIN_RETRYTOKEN_EXPIRATION second
- // minimum and a MAX_RETRYTOKEN_EXPIRATION second maximum.
- if (t + verification_expiration * NGTCP2_SECONDS < uv_hrtime())
- return true;
-
- ngtcp2_cid_init(
- ocid->cid(),
- plaintext + addr.length() + sizeof(uint64_t),
- cil);
-
- return false;
-}
-
-// Get the ALPN protocol identifier that was negotiated for the session
-Local<Value> GetALPNProtocol(const QuicSession& session) {
- QuicCryptoContext* ctx = session.crypto_context();
- Environment* env = session.env();
- std::string alpn = ctx->selected_alpn();
- // This supposed to be `NGHTTP3_ALPN_H3 + 1`
- // Details see https://github.com/nodejs/node/issues/33959
- if (alpn == &NGHTTP3_ALPN_H3[1]) {
- return env->http3_alpn_string();
- } else {
- return ToV8Value(
- env->context(),
- alpn,
- env->isolate()).FromMaybe(Local<Value>());
- }
-}
-
-namespace {
-int CertCB(SSL* ssl, void* arg) {
- QuicSession* session = static_cast<QuicSession*>(arg);
- int ret;
- switch (SSL_get_tlsext_status_type(ssl)) {
- case TLSEXT_STATUSTYPE_ocsp:
- ret = session->crypto_context()->OnOCSP();
- return UNLIKELY(session->is_destroyed()) ? 0 : ret;
- default:
- return 1;
- }
-}
-
-void Keylog_CB(const SSL* ssl, const char* line) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- session->crypto_context()->Keylog(line);
-}
-
-int Client_Hello_CB(
- SSL* ssl,
- int* tls_alert,
- void* arg) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- int ret = session->crypto_context()->OnClientHello();
- if (UNLIKELY(session->is_destroyed())) {
- *tls_alert = SSL_R_SSL_HANDSHAKE_FAILURE;
- return 0;
- }
- switch (ret) {
- case 0:
- return 1;
- case -1:
- return -1;
- default:
- *tls_alert = ret;
- return 0;
- }
-}
-
-int AlpnSelection(
- SSL* ssl,
- const unsigned char** out,
- unsigned char* outlen,
- const unsigned char* in,
- unsigned int inlen,
- void* arg) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
-
- unsigned char* tmp;
-
- // The QuicServerSession supports exactly one ALPN identifier. If that does
- // not match any of the ALPN identifiers provided in the client request,
- // then we fail here. Note that this will not fail the TLS handshake, so
- // we have to check later if the ALPN matches the expected identifier or not.
- if (SSL_select_next_proto(
- &tmp,
- outlen,
- reinterpret_cast<const unsigned char*>(session->alpn().c_str()),
- session->alpn().length(),
- in,
- inlen) == OPENSSL_NPN_NO_OVERLAP) {
- return SSL_TLSEXT_ERR_NOACK;
- }
- *out = tmp;
- return SSL_TLSEXT_ERR_OK;
-}
-
-int AllowEarlyDataCB(SSL* ssl, void* arg) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- return session->allow_early_data() ? 1 : 0;
-}
-
-int TLS_Status_Callback(SSL* ssl, void* arg) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- return session->crypto_context()->OnTLSStatus();
-}
-
-int New_Session_Callback(SSL* ssl, SSL_SESSION* session) {
- QuicSession* s = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- return s->set_session(session);
-}
-
-int GenerateSessionTicket(SSL* ssl, void* arg) {
- QuicSession* s = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- SessionTicketAppData app_data(SSL_get_session(ssl));
- s->SetSessionTicketAppData(app_data);
- return 1;
-}
-
-SSL_TICKET_RETURN DecryptSessionTicket(
- SSL* ssl,
- SSL_SESSION* session,
- const unsigned char* keyname,
- size_t keyname_len,
- SSL_TICKET_STATUS status,
- void* arg) {
- QuicSession* s = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- SessionTicketAppData::Flag flag = SessionTicketAppData::Flag::STATUS_NONE;
- switch (status) {
- default:
- return SSL_TICKET_RETURN_IGNORE;
- case SSL_TICKET_EMPTY:
- // Fall through
- case SSL_TICKET_NO_DECRYPT:
- return SSL_TICKET_RETURN_IGNORE_RENEW;
- case SSL_TICKET_SUCCESS_RENEW:
- flag = SessionTicketAppData::Flag::STATUS_RENEW;
- // Fall through
- case SSL_TICKET_SUCCESS:
- SessionTicketAppData app_data(session);
- switch (s->GetSessionTicketAppData(app_data, flag)) {
- default:
- return SSL_TICKET_RETURN_IGNORE;
- case SessionTicketAppData::Status::TICKET_IGNORE:
- return SSL_TICKET_RETURN_IGNORE;
- case SessionTicketAppData::Status::TICKET_IGNORE_RENEW:
- return SSL_TICKET_RETURN_IGNORE_RENEW;
- case SessionTicketAppData::Status::TICKET_USE:
- return SSL_TICKET_RETURN_USE;
- case SessionTicketAppData::Status::TICKET_USE_RENEW:
- return SSL_TICKET_RETURN_USE_RENEW;
- }
- }
-}
-
-int SetEncryptionSecrets(
- SSL* ssl,
- OSSL_ENCRYPTION_LEVEL ossl_level,
- const uint8_t* read_secret,
- const uint8_t* write_secret,
- size_t secret_len) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- return session->crypto_context()->OnSecrets(
- from_ossl_level(ossl_level),
- read_secret,
- write_secret,
- secret_len) ? 1 : 0;
-}
-
-int AddHandshakeData(
- SSL* ssl,
- OSSL_ENCRYPTION_LEVEL ossl_level,
- const uint8_t* data,
- size_t len) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- session->crypto_context()->WriteHandshake(
- from_ossl_level(ossl_level),
- data,
- len);
- return 1;
-}
-
-int FlushFlight(SSL* ssl) { return 1; }
-
-int SendAlert(
- SSL* ssl,
- enum ssl_encryption_level_t level,
- uint8_t alert) {
- QuicSession* session = static_cast<QuicSession*>(SSL_get_app_data(ssl));
- session->crypto_context()->set_tls_alert(alert);
- return 1;
-}
-
-bool SetTransportParams(QuicSession* session, const crypto::SSLPointer& ssl) {
- ngtcp2_transport_params params;
- ngtcp2_conn_get_local_transport_params(session->connection(), &params);
- uint8_t buf[512];
- ssize_t nwrite = ngtcp2_encode_transport_params(
- buf,
- arraysize(buf),
- NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
- &params);
- return nwrite >= 0 &&
- SSL_set_quic_transport_params(ssl.get(), buf, nwrite) == 1;
-}
-
-SSL_QUIC_METHOD quic_method = SSL_QUIC_METHOD{
- SetEncryptionSecrets,
- AddHandshakeData,
- FlushFlight,
- SendAlert
-};
-
-void SetHostname(const crypto::SSLPointer& ssl, const std::string& hostname) {
- // If the hostname is an IP address, use an empty string
- // as the hostname instead.
- X509_VERIFY_PARAM* param = SSL_get0_param(ssl.get());
- X509_VERIFY_PARAM_set_hostflags(param, 0);
-
- if (UNLIKELY(SocketAddress::is_numeric_host(hostname.c_str()))) {
- SSL_set_tlsext_host_name(ssl.get(), "");
- CHECK_EQ(X509_VERIFY_PARAM_set1_host(param, "", 0), 1);
- } else {
- SSL_set_tlsext_host_name(ssl.get(), hostname.c_str());
- CHECK_EQ(
- X509_VERIFY_PARAM_set1_host(param, hostname.c_str(), hostname.length()),
- 1);
- }
-}
-
-} // namespace
-
-void InitializeTLS(QuicSession* session, const crypto::SSLPointer& ssl) {
- QuicCryptoContext* ctx = session->crypto_context();
- Environment* env = session->env();
- QuicState* quic_state = session->quic_state();
-
- SSL_set_app_data(ssl.get(), session);
- SSL_set_cert_cb(ssl.get(), CertCB,
- const_cast<void*>(reinterpret_cast<const void*>(session)));
- SSL_set_verify(ssl.get(), SSL_VERIFY_NONE, crypto::VerifyCallback);
-
- // Enable tracing if the `--trace-tls` command line flag is used.
- if (env->options()->trace_tls) {
- ctx->EnableTrace();
- if (quic_state->warn_trace_tls) {
- quic_state->warn_trace_tls = false;
- ProcessEmitWarning(env,
- "Enabling --trace-tls can expose sensitive data "
- "in the resulting log");
- }
- }
-
- switch (ctx->side()) {
- case NGTCP2_CRYPTO_SIDE_CLIENT: {
- SSL_set_connect_state(ssl.get());
- crypto::SetALPN(ssl, session->alpn());
- SetHostname(ssl, session->hostname());
- if (ctx->is_option_set(QUICCLIENTSESSION_OPTION_REQUEST_OCSP))
- SSL_set_tlsext_status_type(ssl.get(), TLSEXT_STATUSTYPE_ocsp);
- break;
- }
- case NGTCP2_CRYPTO_SIDE_SERVER: {
- SSL_set_accept_state(ssl.get());
- if (ctx->is_option_set(QUICSERVERSESSION_OPTION_REQUEST_CERT)) {
- int verify_mode = SSL_VERIFY_PEER;
- if (ctx->is_option_set(QUICSERVERSESSION_OPTION_REJECT_UNAUTHORIZED))
- verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- SSL_set_verify(ssl.get(), verify_mode, crypto::VerifyCallback);
- }
- break;
- }
- default:
- UNREACHABLE();
- }
-
- ngtcp2_conn_set_tls_native_handle(session->connection(), ssl.get());
- SetTransportParams(session, ssl);
-}
-
-void InitializeSecureContext(
- BaseObjectPtr<crypto::SecureContext> sc,
- bool early_data,
- ngtcp2_crypto_side side) {
- constexpr static unsigned char session_id_ctx[] = "node.js quic server";
- switch (side) {
- case NGTCP2_CRYPTO_SIDE_SERVER:
- SSL_CTX_set_options(
- **sc,
- (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
- SSL_OP_SINGLE_ECDH_USE |
- SSL_OP_CIPHER_SERVER_PREFERENCE |
- SSL_OP_NO_ANTI_REPLAY);
-
- SSL_CTX_set_mode(**sc, SSL_MODE_RELEASE_BUFFERS);
-
- SSL_CTX_set_alpn_select_cb(**sc, AlpnSelection, nullptr);
- SSL_CTX_set_client_hello_cb(**sc, Client_Hello_CB, nullptr);
-
- SSL_CTX_set_session_ticket_cb(
- **sc,
- GenerateSessionTicket,
- DecryptSessionTicket,
- nullptr);
-
- if (early_data) {
- SSL_CTX_set_max_early_data(**sc, 0xffffffff);
- SSL_CTX_set_allow_early_data_cb(**sc, AllowEarlyDataCB, nullptr);
- }
-
- SSL_CTX_set_session_id_context(
- **sc,
- session_id_ctx,
- sizeof(session_id_ctx) - 1);
- break;
- case NGTCP2_CRYPTO_SIDE_CLIENT:
- SSL_CTX_set_session_cache_mode(
- **sc,
- SSL_SESS_CACHE_CLIENT |
- SSL_SESS_CACHE_NO_INTERNAL_STORE);
- SSL_CTX_sess_set_new_cb(**sc, New_Session_Callback);
- break;
- default:
- UNREACHABLE();
- }
- SSL_CTX_set_min_proto_version(**sc, TLS1_3_VERSION);
- SSL_CTX_set_max_proto_version(**sc, TLS1_3_VERSION);
- SSL_CTX_set_default_verify_paths(**sc);
- SSL_CTX_set_tlsext_status_cb(**sc, TLS_Status_Callback);
- SSL_CTX_set_keylog_callback(**sc, Keylog_CB);
- SSL_CTX_set_tlsext_status_arg(**sc, nullptr);
- SSL_CTX_set_quic_method(**sc, &quic_method);
-}
-
-ngtcp2_crypto_level from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level) {
- switch (ossl_level) {
- case ssl_encryption_initial:
- return NGTCP2_CRYPTO_LEVEL_INITIAL;
- case ssl_encryption_early_data:
- return NGTCP2_CRYPTO_LEVEL_EARLY;
- case ssl_encryption_handshake:
- return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- case ssl_encryption_application:
- return NGTCP2_CRYPTO_LEVEL_APP;
- default:
- UNREACHABLE();
- }
-}
-
-const char* crypto_level_name(ngtcp2_crypto_level level) {
- switch (level) {
- case NGTCP2_CRYPTO_LEVEL_INITIAL:
- return "initial";
- case NGTCP2_CRYPTO_LEVEL_EARLY:
- return "early";
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- return "handshake";
- case NGTCP2_CRYPTO_LEVEL_APP:
- return "app";
- default:
- UNREACHABLE();
- }
-}
-
-// When using IPv6, QUIC recommends the use of IPv6 Flow Labels
-// as specified in https://tools.ietf.org/html/rfc6437. These
-// are used as a means of reliably associating packets exchanged
-// as part of a single flow and protecting against certain kinds
-// of attacks.
-uint32_t GenerateFlowLabel(
- const SocketAddress& local,
- const SocketAddress& remote,
- const QuicCID& cid,
- const uint8_t* secret,
- size_t secretlen) {
- static constexpr size_t kInfoLen =
- (sizeof(sockaddr_in6) * 2) + NGTCP2_MAX_CIDLEN;
-
- uint32_t label = 0;
-
- std::array<uint8_t, kInfoLen> plaintext;
- size_t infolen = local.length() + remote.length() + cid.length();
- CHECK_LE(infolen, kInfoLen);
-
- ngtcp2_crypto_ctx ctx;
- ngtcp2_crypto_ctx_initial(&ctx);
-
- auto p = std::begin(plaintext);
- p = std::copy_n(local.raw(), local.length(), p);
- p = std::copy_n(remote.raw(), remote.length(), p);
- p = std::copy_n(cid->data, cid->datalen, p);
-
- ngtcp2_crypto_hkdf_expand(
- reinterpret_cast<uint8_t*>(&label),
- sizeof(label),
- &ctx.md,
- secret,
- secretlen,
- plaintext.data(),
- infolen);
-
- label &= kLabelMask;
- DCHECK_LE(label, kLabelMask);
- return label;
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_crypto.h b/src/quic/node_quic_crypto.h
deleted file mode 100644
index e37c5e059a..0000000000
--- a/src/quic/node_quic_crypto.h
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_CRYPTO_H_
-#define SRC_QUIC_NODE_QUIC_CRYPTO_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node_crypto.h"
-#include "node_quic_util.h"
-#include "v8.h"
-
-#include <ngtcp2/ngtcp2.h>
-#include <ngtcp2/ngtcp2_crypto.h>
-#include <openssl/ssl.h>
-
-namespace node {
-
-namespace quic {
-
-// Crypto and OpenSSL related utility functions used in
-// various places throughout the QUIC implementation.
-
-// Forward declaration
-class QuicSession;
-class QuicPacket;
-
-// many ngtcp2 functions return 0 to indicate success
-// and non-zero to indicate failure. Most of the time,
-// for such functions we don't care about the specific
-// return value so we simplify using a macro.
-
-#define NGTCP2_ERR(V) (V != 0)
-#define NGTCP2_OK(V) (V == 0)
-
-// Called by QuicInitSecureContext to initialize the
-// given SecureContext with the defaults for the given
-// QUIC side (client or server).
-void InitializeSecureContext(
- BaseObjectPtr<crypto::SecureContext> sc,
- bool early_data,
- ngtcp2_crypto_side side);
-
-// Called in the QuicSession::InitServer and
-// QuicSession::InitClient to configure the
-// appropriate settings for the SSL* associated
-// with the session.
-void InitializeTLS(QuicSession* session, const crypto::SSLPointer& ssl);
-
-// Generates a stateless reset token using HKDF with the
-// cid and token secret as input. The token secret is
-// either provided by user code when a QuicSocket is
-// created or is generated randomly.
-//
-// QUIC leaves the generation of stateless session tokens
-// up to the implementation to figure out. The idea, however,
-// is that it ought to be possible to generate a stateless
-// reset token reliably even when all state for a connection
-// has been lost. We use the cid as it's the only reliably
-// consistent bit of data we have when a session is destroyed.
-bool GenerateResetToken(
- uint8_t* token,
- const uint8_t* secret,
- const QuicCID& cid);
-
-// The Retry Token is an encrypted token that is sent to the client
-// by the server as part of the path validation flow. The plaintext
-// format within the token is opaque and only meaningful the server.
-// We can structure it any way we want. It needs to:
-// * be hard to guess
-// * be time limited
-// * be specific to the client address
-// * be specific to the original cid
-// * contain random data.
-std::unique_ptr<QuicPacket> GenerateRetryPacket(
- const uint8_t* token_secret,
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr);
-
-// The IPv6 Flow Label is generated and set whenever IPv6 is used.
-// The label is derived as a cryptographic function of the CID,
-// local and remote addresses, and the given secret, that is then
-// truncated to a 20-bit value (per IPv6 requirements). In QUIC,
-// the flow label *may* be used as a way of disambiguating IP
-// packets that belong to the same flow from a remote peer.
-uint32_t GenerateFlowLabel(
- const SocketAddress& local,
- const SocketAddress& remote,
- const QuicCID& cid,
- const uint8_t* secret,
- size_t secretlen);
-
-// Verifies the validity of a retry token. Returns true if the
-// token is *not valid*, false otherwise. If the token is valid,
-// the ocid will be updated to the original CID value encoded
-// within the successfully validated, encrypted token.
-bool InvalidRetryToken(
- const ngtcp2_vec& token,
- const SocketAddress& addr,
- QuicCID* ocid,
- const uint8_t* token_secret,
- uint64_t verification_expiration);
-
-// Get the ALPN protocol identifier that was negotiated for the session
-v8::Local<v8::Value> GetALPNProtocol(const QuicSession& session);
-
-ngtcp2_crypto_level from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level);
-const char* crypto_level_name(ngtcp2_crypto_level level);
-
-// SessionTicketAppData is a utility class that is used only during
-// the generation or access of TLS stateless sesson tickets. It
-// exists solely to provide a easier way for QuicApplication instances
-// to set relevant metadata in the session ticket when it is created,
-// and the exract and subsequently verify that data when a ticket is
-// received and is being validated. The app data is completely opaque
-// to anything other than the server-side of the QuicApplication that
-// sets it.
-class SessionTicketAppData {
- public:
- enum class Status {
- TICKET_USE,
- TICKET_USE_RENEW,
- TICKET_IGNORE,
- TICKET_IGNORE_RENEW
- };
-
- enum class Flag {
- STATUS_NONE,
- STATUS_RENEW
- };
-
- explicit SessionTicketAppData(SSL_SESSION* session) : session_(session) {}
- bool Set(const uint8_t* data, size_t len);
- bool Get(uint8_t** data, size_t* len) const;
-
- private:
- bool set_ = false;
- SSL_SESSION* session_;
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-#endif // SRC_QUIC_NODE_QUIC_CRYPTO_H_
diff --git a/src/quic/node_quic_default_application.cc b/src/quic/node_quic_default_application.cc
deleted file mode 100644
index 5005d3d691..0000000000
--- a/src/quic/node_quic_default_application.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-#include "debug_utils-inl.h"
-#include "node_quic_buffer-inl.h"
-#include "node_quic_default_application.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_stream-inl.h"
-#include "node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include <ngtcp2/ngtcp2.h>
-
-#include <vector>
-
-namespace node {
-namespace quic {
-
-namespace {
-void Consume(ngtcp2_vec** pvec, size_t* pcnt, size_t len) {
- ngtcp2_vec* v = *pvec;
- size_t cnt = *pcnt;
-
- for (; cnt > 0; --cnt, ++v) {
- if (v->len > len) {
- v->len -= len;
- v->base += len;
- break;
- }
- len -= v->len;
- }
-
- *pvec = v;
- *pcnt = cnt;
-}
-
-int IsEmpty(const ngtcp2_vec* vec, size_t cnt) {
- size_t i;
- for (i = 0; i < cnt && vec[i].len == 0; ++i) {}
- return i == cnt;
-}
-} // anonymous namespace
-
-DefaultApplication::DefaultApplication(
- QuicSession* session)
- : QuicApplication(session) {}
-
-bool DefaultApplication::Initialize() {
- if (needs_init()) {
- Debug(session(), "Default QUIC Application Initialized");
- set_init_done();
- }
- return true;
-}
-
-void DefaultApplication::ScheduleStream(int64_t stream_id) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (LIKELY(stream && !stream->is_destroyed())) {
- Debug(session(), "Scheduling stream %" PRIu64, stream_id);
- stream->Schedule(&stream_queue_);
- }
-}
-
-void DefaultApplication::UnscheduleStream(int64_t stream_id) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (LIKELY(stream)) {
- Debug(session(), "Unscheduling stream %" PRIu64, stream_id);
- stream->Unschedule();
- }
-}
-
-void DefaultApplication::ResumeStream(int64_t stream_id) {
- ScheduleStream(stream_id);
-}
-
-bool DefaultApplication::ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) {
- // Ensure that the QuicStream exists before deferring to
- // QuicApplication specific processing logic.
- Debug(session(), "Default QUIC Application receiving stream data");
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (!stream) {
- // Shutdown the stream explicitly if the session is being closed.
- if (session()->is_graceful_closing()) {
- session()->ShutdownStream(stream_id, NGTCP2_ERR_CLOSING);
- return true;
- }
-
- // One potential DOS attack vector is to send a bunch of
- // empty stream frames to commit resources. Check that
- // here. Essentially, we only want to create a new stream
- // if the datalen is greater than 0, otherwise, we ignore
- // the packet. ngtcp2 should be handling this for us,
- // but we handle it just to be safe.
- if (UNLIKELY(datalen == 0))
- return true;
-
- stream = session()->CreateStream(stream_id);
- }
- CHECK(stream);
-
- // If the stream ended up being destroyed immediately after
- // creation, just skip the data processing and return.
- if (UNLIKELY(stream->is_destroyed()))
- return true;
-
- stream->ReceiveData(flags, data, datalen, offset);
- return true;
-}
-
-int DefaultApplication::GetStreamData(StreamData* stream_data) {
- QuicStream* stream = stream_queue_.PopFront();
- // If stream is nullptr, there are no streams with data pending.
- if (stream == nullptr)
- return 0;
-
- stream_data->stream.reset(stream);
- stream_data->id = stream->id();
-
- auto next = [&](
- int status,
- const ngtcp2_vec* data,
- size_t count,
- bob::Done done) {
- switch (status) {
- case bob::Status::STATUS_BLOCK:
- // Fall through
- case bob::Status::STATUS_WAIT:
- // Fall through
- case bob::Status::STATUS_EOS:
- return;
- case bob::Status::STATUS_END:
- stream_data->fin = 1;
- }
-
- stream_data->count = count;
-
- if (count > 0) {
- stream->Schedule(&stream_queue_);
- stream_data->remaining = get_length(data, count);
- } else {
- stream_data->remaining = 0;
- }
- };
-
- if (LIKELY(!stream->is_eos())) {
- CHECK_GE(stream->Pull(
- std::move(next),
- bob::Options::OPTIONS_SYNC,
- stream_data->data,
- arraysize(stream_data->data),
- kMaxVectorCount), 0);
- }
-
- return 0;
-}
-
-bool DefaultApplication::StreamCommit(
- StreamData* stream_data,
- size_t datalen) {
- CHECK(stream_data->stream);
- stream_data->remaining -= datalen;
- Consume(&stream_data->buf, &stream_data->count, datalen);
- stream_data->stream->Commit(datalen);
- return true;
-}
-
-bool DefaultApplication::ShouldSetFin(const StreamData& stream_data) {
- if (!stream_data.stream ||
- !IsEmpty(stream_data.buf, stream_data.count))
- return false;
- return !stream_data.stream->is_writable();
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_default_application.h b/src/quic/node_quic_default_application.h
deleted file mode 100644
index 52c9044c0e..0000000000
--- a/src/quic/node_quic_default_application.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_DEFAULT_APPLICATION_H_
-#define SRC_QUIC_NODE_QUIC_DEFAULT_APPLICATION_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node_quic_stream.h"
-#include "node_quic_session.h"
-#include "node_quic_util.h"
-#include "util.h"
-#include "v8.h"
-
-namespace node {
-
-namespace quic {
-
-// The DefaultApplication is used whenever an unknown/unrecognized
-// alpn identifier is used. It switches the QUIC implementation into
-// a minimal/generic mode that defers all application level processing
-// to the user-code level. Headers are not supported by QuicStream
-// instances created under the default application.
-class DefaultApplication final : public QuicApplication {
- public:
- explicit DefaultApplication(QuicSession* session);
-
- bool Initialize() override;
-
- void StopTrackingMemory(void* ptr) override {
- // Do nothing. Not used.
- }
-
- bool ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) override;
-
- int GetStreamData(StreamData* stream_data) override;
-
- void ResumeStream(int64_t stream_id) override;
- bool ShouldSetFin(const StreamData& stream_data) override;
- bool StreamCommit(StreamData* stream_data, size_t datalen) override;
-
- SET_SELF_SIZE(DefaultApplication)
- SET_MEMORY_INFO_NAME(DefaultApplication)
- SET_NO_MEMORY_INFO()
-
- private:
- void ScheduleStream(int64_t stream_id);
- void UnscheduleStream(int64_t stream_id);
-
- QuicStream::Queue stream_queue_;
-};
-
-} // namespace quic
-
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-#endif // SRC_QUIC_NODE_QUIC_DEFAULT_APPLICATION_H_
diff --git a/src/quic/node_quic_http3_application.cc b/src/quic/node_quic_http3_application.cc
deleted file mode 100644
index 82cd677d1c..0000000000
--- a/src/quic/node_quic_http3_application.cc
+++ /dev/null
@@ -1,941 +0,0 @@
-#include "node.h"
-#include "debug_utils-inl.h"
-#include "node_mem-inl.h"
-#include "node_quic_buffer-inl.h"
-#include "node_quic_http3_application.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_stream-inl.h"
-#include "node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include "node_http_common-inl.h"
-
-#include <ngtcp2/ngtcp2.h>
-#include <nghttp3/nghttp3.h>
-#include <algorithm>
-
-namespace node {
-
-using v8::Array;
-using v8::Local;
-
-namespace quic {
-
-// nghttp3 uses a numeric identifier for a large number
-// of known HTTP header names. These allow us to use
-// static strings for those rather than allocating new
-// strings all of the time. The list of strings supported
-// is included in node_http_common.h
-#define V1(name, value) case NGHTTP3_QPACK_TOKEN__##name: return value;
-#define V2(name, value) case NGHTTP3_QPACK_TOKEN_##name: return value;
-const char* Http3HeaderTraits::ToHttpHeaderName(int32_t token) {
- switch (token) {
- default:
- // Fall through
- case -1: return nullptr;
- HTTP_SPECIAL_HEADERS(V1)
- HTTP_REGULAR_HEADERS(V2)
- }
-}
-#undef V1
-#undef V2
-
-template <typename M, typename T>
-void Http3Application::SetConfig(
- int idx,
- M T::*member) {
- AliasedFloat64Array& buffer = session()->quic_state()->http3config_buffer;
- uint64_t flags = static_cast<uint64_t>(buffer[IDX_HTTP3_CONFIG_COUNT]);
- if (flags & (1ULL << idx))
- config_.*member = static_cast<uint64_t>(buffer[idx]);
-}
-
-Http3Application::Http3Application(
- QuicSession* session)
- : QuicApplication(session),
- alloc_info_(MakeAllocator()) {
- // Collect Configuration Details.
- SetConfig<size_t>(IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY,
- &Http3ApplicationConfig::qpack_max_table_capacity);
- SetConfig<size_t>(IDX_HTTP3_QPACK_BLOCKED_STREAMS,
- &Http3ApplicationConfig::qpack_blocked_streams);
- SetConfig(IDX_HTTP3_MAX_HEADER_LIST_SIZE,
- &Http3ApplicationConfig::max_field_section_size);
- SetConfig(IDX_HTTP3_MAX_PUSHES,
- &Http3ApplicationConfig::max_pushes);
- SetConfig(IDX_HTTP3_MAX_HEADER_PAIRS,
- &Http3ApplicationConfig::max_header_pairs);
- SetConfig(IDX_HTTP3_MAX_HEADER_LENGTH,
- &Http3ApplicationConfig::max_header_length);
- set_max_header_pairs(
- session->is_server()
- ? GetServerMaxHeaderPairs(config_.max_header_pairs)
- : GetClientMaxHeaderPairs(config_.max_header_pairs));
- set_max_header_length(config_.max_header_length);
-
- session->quic_state()->http3config_buffer[IDX_HTTP3_CONFIG_COUNT] = 0;
-}
-
-// Push streams in HTTP/3 are a bit complicated.
-// First, it's important to know that only an HTTP/3 server can
-// create a push stream.
-// Second, a push stream is essentially an *assumed* request. For
-// instance, if a client requests a webpage that has links to css
-// and js files, and the server expects the client to send subsequent
-// requests for those css and js files, the server can shortcut the
-// process by opening a push stream for each additional resource
-// it assumes the client to make.
-// Third, a push stream can only be opened within the context
-// of an HTTP/3 request/response. Essentially, a server receives
-// a request and while processing the response, the server can
-// open one or more push streams.
-//
-// Now... a push stream consists of two components: a push promise
-// and a push fulfillment. The push promise is sent *as part of
-// the response on the original stream* and is assigned a push id
-// and a block of headers containing the *assumed request headers*.
-// The push promise is sent on the request/response bidirectional
-// stream.
-// The push fulfillment is a unidirectional stream opened by the
-// server that contains the push id, the response header block, and
-// the response payload.
-// Here's where it can get a bit complicated: the server sends the
-// push promise and the push fulfillment on two different, and
-// independent QUIC streams. The push id is used to correlate
-// those on the client side, but, it's entirely possible for the
-// client to receive the push fulfillment before it actually receives
-// the push promise. It's *unlikely*, but it's possible. Fortunately,
-// nghttp3 handles the complexity of that for us internally but
-// makes for some weird timing and could lead to some amount of
-// buffering to occur.
-//
-// The *logical* order of events from the client side *should*
-// be: (a) receive the push promise containing assumed request
-// headers, (b) receive the push fulfillment containing the
-// response headers followed immediately by the response payload.
-//
-// On the server side, the steps are: (a) first create the push
-// promise creating the push_id then (b) open the unidirectional
-// stream that will be used to fullfil the push promise. Once that
-// unidirectional stream is created, the push id and unidirectional
-// stream ID must be bound. The CreateAndBindPushStream handles (b)
-int64_t Http3Application::CreateAndBindPushStream(int64_t push_id) {
- CHECK(session()->is_server());
- int64_t stream_id;
- if (!session()->OpenUnidirectionalStream(&stream_id))
- return 0;
- return nghttp3_conn_bind_push_stream(
- connection(),
- push_id,
- stream_id) == 0 ? stream_id : 0;
-}
-
-bool Http3Application::SubmitPushPromise(
- int64_t id,
- int64_t* push_id,
- int64_t* stream_id,
- const Http3Headers& headers) {
- // Successfully creating the push promise and opening the
- // fulfillment stream will queue nghttp3 up to send data.
- // Creating the SendSessionScope here ensures that when
- // SubmitPush exits, SendPendingData will be called if
- // we are not within the context of an ngtcp2 callback.
- QuicSession::SendSessionScope send_scope(session());
-
- Debug(
- session(),
- "Submitting %d push promise headers",
- headers.length());
- if (nghttp3_conn_submit_push_promise(
- connection(),
- push_id,
- id,
- headers.data(),
- headers.length()) != 0) {
- return false;
- }
- // Once we've successfully submitting the push promise and have
- // a push id assigned, we create the push fulfillment stream.
- *stream_id = CreateAndBindPushStream(*push_id);
- return *stream_id != 0; // push stream can never use stream id 0
-}
-
-bool Http3Application::SubmitInformation(
- int64_t id,
- const Http3Headers& headers) {
- QuicSession::SendSessionScope send_scope(session());
- Debug(
- session(),
- "Submitting %d informational headers for stream %" PRId64,
- headers.length(),
- id);
- return nghttp3_conn_submit_info(
- connection(),
- id,
- headers.data(),
- headers.length()) == 0;
-}
-
-bool Http3Application::SubmitTrailers(
- int64_t id,
- const Http3Headers& headers) {
- QuicSession::SendSessionScope send_scope(session());
- Debug(
- session(),
- "Submitting %d trailing headers for stream %" PRId64,
- headers.length(),
- id);
- return nghttp3_conn_submit_trailers(
- connection(),
- id,
- headers.data(),
- headers.length()) == 0;
-}
-
-bool Http3Application::SubmitHeaders(
- int64_t id,
- const Http3Headers& headers,
- int32_t flags) {
- QuicSession::SendSessionScope send_scope(session());
- static constexpr nghttp3_data_reader reader = {
- Http3Application::OnReadData };
- const nghttp3_data_reader* reader_ptr = nullptr;
- if (!(flags & QUICSTREAM_HEADER_FLAGS_TERMINAL))
- reader_ptr = &reader;
-
- switch (session()->crypto_context()->side()) {
- case NGTCP2_CRYPTO_SIDE_CLIENT:
- return nghttp3_conn_submit_request(
- connection(),
- id,
- headers.data(),
- headers.length(),
- reader_ptr,
- nullptr) == 0;
- case NGTCP2_CRYPTO_SIDE_SERVER:
- return nghttp3_conn_submit_response(
- connection(),
- id,
- headers.data(),
- headers.length(),
- reader_ptr) == 0;
- default:
- UNREACHABLE();
- }
-}
-
-// SubmitPush initiates a push stream by first creating a push promise
-// with an associated push id, then opening the unidirectional stream
-// that is used to fullfill it. Assuming both operations are successful,
-// the QuicStream instance is created and added to the server QuicSession.
-//
-// The headers block passed to the submit push contains the assumed
-// *request* headers. The response headers are provided using the
-// SubmitHeaders() function on the created QuicStream.
-BaseObjectPtr<QuicStream> Http3Application::SubmitPush(
- int64_t id,
- Local<Array> headers) {
- // If the QuicSession is not a server session, return false
- // immediately. Push streams cannot be sent by an HTTP/3 client.
- if (!session()->is_server())
- return {};
-
- Http3Headers nva(env(), headers);
- int64_t push_id;
- int64_t stream_id;
-
- // There are several reasons why push may fail. We currently handle
- // them all the same. Later we might want to differentiate when the
- // return value is NGHTTP3_ERR_PUSH_ID_BLOCKED.
- return SubmitPushPromise(id, &push_id, &stream_id, nva) ?
- QuicStream::New(session(), stream_id, push_id) :
- BaseObjectPtr<QuicStream>();
-}
-
-// Submit informational headers (response headers that use a 1xx
-// status code). If the QuicSession is not a server session, return
-// false immediately because info headers cannot be sent by a
-// client
-bool Http3Application::SubmitInformation(
- int64_t stream_id,
- Local<Array> headers) {
- if (!session()->is_server())
- return false;
- Http3Headers nva(session()->env(), headers);
- return SubmitInformation(stream_id, nva);
-}
-
-// For client sessions, submits request headers. For server sessions,
-// submits response headers.
-bool Http3Application::SubmitHeaders(
- int64_t stream_id,
- Local<Array> headers,
- uint32_t flags) {
- Http3Headers nva(session()->env(), headers);
- return SubmitHeaders(stream_id, nva, flags);
-}
-
-// Submits trailing headers for the HTTP/3 request or response.
-bool Http3Application::SubmitTrailers(
- int64_t stream_id,
- Local<Array> headers) {
- Http3Headers nva(session()->env(), headers);
- return SubmitTrailers(stream_id, nva);
-}
-
-void Http3Application::CheckAllocatedSize(size_t previous_size) const {
- CHECK_GE(current_nghttp3_memory_, previous_size);
-}
-
-void Http3Application::IncreaseAllocatedSize(size_t size) {
- current_nghttp3_memory_ += size;
-}
-
-void Http3Application::DecreaseAllocatedSize(size_t size) {
- current_nghttp3_memory_ -= size;
-}
-
-void Http3Application::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackFieldWithSize("current_nghttp3_memory",
- current_nghttp3_memory_);
-}
-
-// Creates the underlying nghttp3 connection state for the session.
-void Http3Application::CreateConnection() {
- // nghttp3_conn_server_new and nghttp3_conn_client_new share
- // identical definitions, so new_fn will work for both.
- using new_fn = decltype(&nghttp3_conn_server_new);
- static new_fn fns[] = {
- nghttp3_conn_client_new, // NGTCP2_CRYPTO_SIDE_CLIENT
- nghttp3_conn_server_new, // NGTCP2_CRYPTO_SIDE_SERVER
- };
-
- ngtcp2_crypto_side side = session()->crypto_context()->side();
- nghttp3_conn* conn;
-
- CHECK_EQ(fns[side](
- &conn,
- &callbacks_[side],
- &config_,
- &alloc_info_,
- this), 0);
- CHECK_NOT_NULL(conn);
- connection_.reset(conn);
-}
-
-// The HTTP/3 QUIC binding uses a single unidirectional control
-// stream in each direction to exchange frames impacting the entire
-// connection.
-bool Http3Application::CreateAndBindControlStream() {
- if (!session()->OpenUnidirectionalStream(&control_stream_id_))
- return false;
- Debug(
- session(),
- "Open stream %" PRId64 " and bind as control stream",
- control_stream_id_);
- return nghttp3_conn_bind_control_stream(
- connection(),
- control_stream_id_) == 0;
-}
-
-// The HTTP/3 QUIC binding creates two unidirectional streams in
-// each direction to exchange header compression details.
-bool Http3Application::CreateAndBindQPackStreams() {
- if (!session()->OpenUnidirectionalStream(&qpack_enc_stream_id_) ||
- !session()->OpenUnidirectionalStream(&qpack_dec_stream_id_)) {
- return false;
- }
- Debug(
- session(),
- "Open streams %" PRId64 " and %" PRId64 " and bind as qpack streams",
- qpack_enc_stream_id_,
- qpack_dec_stream_id_);
- return nghttp3_conn_bind_qpack_streams(
- connection(),
- qpack_enc_stream_id_,
- qpack_dec_stream_id_) == 0;
-}
-
-bool Http3Application::Initialize() {
- if (!needs_init())
- return false;
-
- // The QuicSession must allow for at least three local unidirectional streams.
- // This number is fixed by the http3 specification and represent the
- // control stream and two qpack management streams.
- if (session()->max_local_streams_uni() < 3)
- return false;
-
- Debug(session(), "QPack Max Table Capacity: %" PRIu64,
- config_.qpack_max_table_capacity);
- Debug(session(), "QPack Blocked Streams: %" PRIu64,
- config_.qpack_blocked_streams);
- Debug(session(), "Max Header List Size: %" PRIu64,
- config_.max_field_section_size);
- Debug(session(), "Max Pushes: %" PRIu64,
- config_.max_pushes);
-
- CreateConnection();
- Debug(session(), "HTTP/3 connection created");
-
- ngtcp2_transport_params params;
- session()->GetLocalTransportParams(&params);
-
- if (session()->is_server()) {
- nghttp3_conn_set_max_client_streams_bidi(
- connection(),
- params.initial_max_streams_bidi);
- }
-
- if (!CreateAndBindControlStream() ||
- !CreateAndBindQPackStreams()) {
- return false;
- }
-
- set_init_done();
- return true;
-}
-
-// All HTTP/3 control, header, and stream data arrives as QUIC stream data.
-// Here we pass the received data off to nghttp3 for processing. This will
-// trigger the invocation of the various nghttp3 callbacks.
-bool Http3Application::ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) {
- Debug(session(), "Receiving %" PRIu64 " bytes for stream %" PRIu64 "%s",
- datalen,
- stream_id,
- flags & NGTCP2_STREAM_DATA_FLAG_FIN ? " (fin)" : "");
- ssize_t nread =
- nghttp3_conn_read_stream(
- connection(),
- stream_id,
- data,
- datalen,
- flags & NGTCP2_STREAM_DATA_FLAG_FIN);
- if (nread < 0) {
- Debug(session(), "Failure to read HTTP/3 Stream Data [%" PRId64 "]", nread);
- return false;
- }
-
- return true;
-}
-
-// This is the QUIC-level stream data acknowledgement. It is called for
-// all streams, including unidirectional streams. This has to forward on
-// to nghttp3 for processing. The Http3Application::AckedStreamData might
-// be called as a result to acknowledge (and free) QuicStream data.
-void Http3Application::AcknowledgeStreamData(
- int64_t stream_id,
- uint64_t offset,
- size_t datalen) {
- if (nghttp3_conn_add_ack_offset(connection(), stream_id, datalen) != 0)
- Debug(session(), "Failure to acknowledge HTTP/3 Stream Data");
-}
-
-void Http3Application::StreamClose(
- int64_t stream_id,
- uint64_t app_error_code) {
- if (app_error_code == 0)
- app_error_code = NGTCP2_APP_NOERROR;
- nghttp3_conn_close_stream(connection(), stream_id, app_error_code);
- QuicApplication::StreamClose(stream_id, app_error_code);
-}
-
-void Http3Application::StreamReset(
- int64_t stream_id,
- uint64_t app_error_code) {
- nghttp3_conn_reset_stream(connection(), stream_id);
- QuicApplication::StreamReset(stream_id, app_error_code);
-}
-
-// When SendPendingData tries to send data for a given stream and there
-// is no data to send but the QuicStream is still writable, it will
-// be paused. When there's data available, the stream is resumed.
-void Http3Application::ResumeStream(int64_t stream_id) {
- nghttp3_conn_resume_stream(connection(), stream_id);
-}
-
-// When stream data cannot be sent because of flow control, it is marked
-// as being blocked. When the flow control windows expands, nghttp3 has
-// to be told to unblock the stream so it knows to try sending data again.
-void Http3Application::ExtendMaxStreamData(
- int64_t stream_id,
- uint64_t max_data) {
- nghttp3_conn_unblock_stream(connection(), stream_id);
-}
-
-// When stream data cannot be sent because of flow control, it is marked
-// as being blocked.
-bool Http3Application::BlockStream(int64_t stream_id) {
- int err = nghttp3_conn_block_stream(connection(), stream_id);
- if (err != 0) {
- session()->set_last_error(QUIC_ERROR_APPLICATION, err);
- return false;
- }
- return true;
-}
-
-// nghttp3 keeps track of how much QuicStream data it has available and
-// has sent. StreamCommit is called when a QuicPacket is serialized
-// and updates nghttp3's internal state.
-bool Http3Application::StreamCommit(StreamData* stream_data, size_t datalen) {
- int err = nghttp3_conn_add_write_offset(
- connection(),
- stream_data->id,
- datalen);
- if (err != 0) {
- session()->set_last_error(QUIC_ERROR_APPLICATION, err);
- return false;
- }
- return true;
-}
-
-// GetStreamData is called by SendPendingData to collect the QuicStream data
-// that is to be packaged into a serialized QuicPacket. There may or may not
-// be any stream data to send. The call to nghttp3_conn_writev_stream will
-// provide any available stream data (if any). If nghttp3 is not sure if
-// there is data to send, it will subsequently call Http3Application::ReadData
-// to collect available data from the QuicStream.
-int Http3Application::GetStreamData(StreamData* stream_data) {
- ssize_t ret = 0;
- if (connection() && session()->max_data_left()) {
- ret = nghttp3_conn_writev_stream(
- connection(),
- &stream_data->id,
- &stream_data->fin,
- reinterpret_cast<nghttp3_vec*>(stream_data->data),
- sizeof(stream_data->data));
- if (ret < 0)
- return static_cast<int>(ret);
- else
- stream_data->remaining = stream_data->count = static_cast<size_t>(ret);
- }
- if (stream_data->id > -1) {
- Debug(session(), "Selected %" PRId64 " buffers for stream %" PRId64 "%s",
- stream_data->count,
- stream_data->id,
- stream_data->fin == 1 ? " (fin)" : "");
- }
- return 0;
-}
-
-// Determines whether SendPendingData should set fin on the QuicStream
-bool Http3Application::ShouldSetFin(const StreamData& stream_data) {
- return stream_data.id > -1 &&
- !is_control_stream(stream_data.id) &&
- stream_data.fin == 1;
-}
-
-// This is where nghttp3 pulls the data from the outgoing
-// buffer to prepare it to be sent on the QUIC stream.
-ssize_t Http3Application::ReadData(
- int64_t stream_id,
- nghttp3_vec* vec,
- size_t veccnt,
- uint32_t* pflags) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- CHECK(stream);
-
- ssize_t ret = NGHTTP3_ERR_WOULDBLOCK;
-
- auto next = [&](
- int status,
- const ngtcp2_vec* data,
- size_t count,
- bob::Done done) {
- CHECK_LE(count, veccnt);
-
- switch (status) {
- case bob::Status::STATUS_BLOCK:
- // Fall through
- case bob::Status::STATUS_WAIT:
- // Fall through
- case bob::Status::STATUS_EOS:
- return;
- case bob::Status::STATUS_END:
- *pflags |= NGHTTP3_DATA_FLAG_EOF;
- break;
- }
-
- ret = count;
- size_t numbytes =
- nghttp3_vec_len(
- reinterpret_cast<const nghttp3_vec*>(data),
- count);
- std::move(done)(numbytes);
-
- Debug(session(), "Sending %" PRIu64 " bytes for stream %" PRId64,
- numbytes, stream_id);
- };
-
- CHECK_GE(stream->Pull(
- std::move(next),
- // Set OPTIONS_END here because nghttp3 takes over responsibility
- // for ensuring the data all gets written out.
- bob::Options::OPTIONS_END | bob::Options::OPTIONS_SYNC,
- reinterpret_cast<ngtcp2_vec*>(vec),
- veccnt,
- kMaxVectorCount), 0);
-
- return ret;
-}
-
-// Outgoing data is retained in memory until it is acknowledged.
-void Http3Application::AckedStreamData(int64_t stream_id, size_t datalen) {
- Acknowledge(stream_id, 0, datalen);
-}
-
-void Http3Application::StreamClosed(
- int64_t stream_id,
- uint64_t app_error_code) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (stream)
- stream->ReceiveData(1, nullptr, 0, 0);
-}
-
-BaseObjectPtr<QuicStream> Http3Application::FindOrCreateStream(
- int64_t stream_id) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (!stream) {
- if (session()->is_graceful_closing()) {
- nghttp3_conn_close_stream(connection(), stream_id, NGTCP2_ERR_CLOSING);
- return {};
- }
- stream = session()->CreateStream(stream_id);
- nghttp3_conn_set_stream_user_data(connection(), stream_id, stream.get());
- }
- CHECK(stream);
- return stream;
-}
-
-void Http3Application::ReceiveData(
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen) {
- FindOrCreateStream(stream_id)->ReceiveData(0, data, datalen, 0);
-}
-
-void Http3Application::DeferredConsume(
- int64_t stream_id,
- size_t consumed) {
- // Do nothing here for now. nghttp3 uses the on_deferred_consume
- // callback to notify when stream data that had previously been
- // deferred has been delivered to the application so that the
- // stream data offset can be extended. However, we extend the
- // data offset from within QuicStream when the data is delivered
- // so we don't have to do it here.
-}
-
-// Called when a nghttp3 detects that a new block of headers
-// has been received. Http3Application::ReceiveHeader will
-// be called for each name+value pair received, then
-// Http3Application::EndHeaders will be called to finalize
-// the header block.
-void Http3Application::BeginHeaders(
- int64_t stream_id,
- QuicStreamHeadersKind kind) {
- Debug(session(), "Starting header block for stream %" PRId64, stream_id);
- FindOrCreateStream(stream_id)->BeginHeaders(kind);
-}
-
-// As each header name+value pair is received, it is stored internally
-// by the QuicStream until stream->EndHeaders() is called, during which
-// the collected headers are converted to an array and passed off to
-// the javascript side.
-bool Http3Application::ReceiveHeader(
- int64_t stream_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags) {
- // Protect against zero-length headers (zero-length if either the
- // name or value are zero-length). Such headers are simply ignored.
- if (!Http3Header::IsZeroLength(name, value)) {
- Debug(session(), "Receiving header for stream %" PRId64, stream_id);
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- CHECK(stream);
- if (token == NGHTTP3_QPACK_TOKEN__STATUS) {
- nghttp3_vec vec = nghttp3_rcbuf_get_buf(value);
- if (vec.base[0] == '1')
- stream->set_headers_kind(QUICSTREAM_HEADERS_KIND_INFORMATIONAL);
- else
- stream->set_headers_kind(QUICSTREAM_HEADERS_KIND_INITIAL);
- }
- auto header = std::make_unique<Http3Header>(
- session()->env(),
- token,
- name,
- value,
- flags);
- return stream->AddHeader(std::move(header));
- }
- return true;
-}
-
-// Marks the completion of a headers block.
-void Http3Application::EndHeaders(int64_t stream_id, int64_t push_id) {
- Debug(session(), "Ending header block for stream %" PRId64, stream_id);
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- CHECK(stream);
- stream->EndHeaders();
-}
-
-void Http3Application::CancelPush(
- int64_t push_id,
- int64_t stream_id) {
- Debug(session(), "push stream canceled");
-}
-
-void Http3Application::PushStream(
- int64_t push_id,
- int64_t stream_id) {
- Debug(session(), "Received push stream %" PRIu64 " (%" PRIu64 ")",
- stream_id, push_id);
-}
-
-void Http3Application::SendStopSending(
- int64_t stream_id,
- uint64_t app_error_code) {
- ngtcp2_conn_shutdown_stream_read(
- session()->connection(),
- stream_id,
- app_error_code);
-}
-
-void Http3Application::EndStream(int64_t stream_id) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- CHECK(stream);
- stream->ReceiveData(1, nullptr, 0, 0);
-}
-
-const nghttp3_conn_callbacks Http3Application::callbacks_[2] = {
- // NGTCP2_CRYPTO_SIDE_CLIENT
- {
- OnAckedStreamData,
- OnStreamClose,
- OnReceiveData,
- OnDeferredConsume,
- OnBeginHeaders,
- OnReceiveHeader,
- OnEndHeaders,
- OnBeginTrailers, // Begin Trailers
- OnReceiveHeader, // Receive Trailer
- OnEndHeaders, // End Trailers
- OnBeginPushPromise,
- OnReceivePushPromise,
- OnEndPushPromise,
- OnCancelPush,
- OnSendStopSending,
- OnPushStream,
- OnEndStream
- },
- // NGTCP2_CRYPTO_SIDE_SERVER
- {
- OnAckedStreamData,
- OnStreamClose,
- OnReceiveData,
- OnDeferredConsume,
- OnBeginHeaders,
- OnReceiveHeader,
- OnEndHeaders,
- OnBeginTrailers, // Begin Trailers
- OnReceiveHeader, // Receive Trailer
- OnEndHeaders, // End Trailers
- OnBeginPushPromise,
- OnReceivePushPromise,
- OnEndPushPromise,
- OnCancelPush,
- OnSendStopSending,
- OnPushStream,
- OnEndStream
- }
-};
-
-int Http3Application::OnAckedStreamData(
- nghttp3_conn* conn,
- int64_t stream_id,
- size_t datalen,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->AckedStreamData(stream_id, datalen);
- return 0;
-}
-
-int Http3Application::OnStreamClose(
- nghttp3_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->StreamClosed(stream_id, app_error_code);
- return 0;
-}
-
-int Http3Application::OnReceiveData(
- nghttp3_conn* conn,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->ReceiveData(stream_id, data, datalen);
- return 0;
-}
-
-int Http3Application::OnDeferredConsume(
- nghttp3_conn* conn,
- int64_t stream_id,
- size_t consumed,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->DeferredConsume(stream_id, consumed);
- return 0;
-}
-
-int Http3Application::OnBeginHeaders(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->BeginHeaders(stream_id);
- return 0;
-}
-
-int Http3Application::OnBeginTrailers(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->BeginHeaders(stream_id, QUICSTREAM_HEADERS_KIND_TRAILING);
- return 0;
-}
-
-int Http3Application::OnReceiveHeader(
- nghttp3_conn* conn,
- int64_t stream_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- // TODO(@jasnell): Need to determine the appropriate response code here
- // for when the header is not going to be accepted.
- return app->ReceiveHeader(stream_id, token, name, value, flags) ?
- 0 : NGHTTP3_ERR_CALLBACK_FAILURE;
-}
-
-int Http3Application::OnEndHeaders(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->EndHeaders(stream_id);
- return 0;
-}
-
-int Http3Application::OnBeginPushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->BeginHeaders(stream_id, QUICSTREAM_HEADERS_KIND_PUSH);
- return 0;
-}
-
-int Http3Application::OnReceivePushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- if (!app->ReceiveHeader(stream_id, token, name, value, flags))
- return NGHTTP3_ERR_CALLBACK_FAILURE;
- return 0;
-}
-
-int Http3Application::OnEndPushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->EndHeaders(stream_id, push_id);
- return 0;
-}
-
-int Http3Application::OnCancelPush(
- nghttp3_conn* conn,
- int64_t push_id,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->CancelPush(push_id, stream_id);
- return 0;
-}
-
-int Http3Application::OnSendStopSending(
- nghttp3_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->SendStopSending(stream_id, app_error_code);
- return 0;
-}
-
-int Http3Application::OnPushStream(
- nghttp3_conn* conn,
- int64_t push_id,
- int64_t stream_id,
- void* conn_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->PushStream(push_id, stream_id);
- return 0;
-}
-
-int Http3Application::OnEndStream(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- app->EndStream(stream_id);
- return 0;
-}
-
-ssize_t Http3Application::OnReadData(
- nghttp3_conn* conn,
- int64_t stream_id,
- nghttp3_vec* vec,
- size_t veccnt,
- uint32_t* pflags,
- void* conn_user_data,
- void* stream_user_data) {
- Http3Application* app = static_cast<Http3Application*>(conn_user_data);
- return app->ReadData(stream_id, vec, veccnt, pflags);
-}
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_http3_application.h b/src/quic/node_quic_http3_application.h
deleted file mode 100644
index 3538741462..0000000000
--- a/src/quic/node_quic_http3_application.h
+++ /dev/null
@@ -1,331 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_HTTP3_APPLICATION_H_
-#define SRC_QUIC_NODE_QUIC_HTTP3_APPLICATION_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node.h"
-#include "node_http_common.h"
-#include "node_mem.h"
-#include "node_quic_session.h"
-#include "node_quic_stream-inl.h"
-#include "node_quic_util.h"
-#include "v8.h"
-#include <ngtcp2/ngtcp2.h>
-#include <nghttp3/nghttp3.h>
-
-namespace node {
-
-namespace quic {
-
-constexpr uint64_t DEFAULT_QPACK_MAX_TABLE_CAPACITY = 4096;
-constexpr uint64_t DEFAULT_QPACK_BLOCKED_STREAMS = 100;
-constexpr size_t DEFAULT_MAX_HEADER_LIST_SIZE = 65535;
-constexpr size_t DEFAULT_MAX_PUSHES = 65535;
-
-struct Http3RcBufferPointerTraits {
- typedef nghttp3_rcbuf rcbuf_t;
- typedef nghttp3_vec vector_t;
-
- static void inc(rcbuf_t* buf) {
- nghttp3_rcbuf_incref(buf);
- }
- static void dec(rcbuf_t* buf) {
- nghttp3_rcbuf_decref(buf);
- }
- static vector_t get_vec(const rcbuf_t* buf) {
- return nghttp3_rcbuf_get_buf(buf);
- }
- static bool is_static(const rcbuf_t* buf) {
- return nghttp3_rcbuf_is_static(buf);
- }
-};
-
-struct Http3HeadersTraits {
- typedef nghttp3_nv nv_t;
-};
-
-using Http3ConnectionPointer = DeleteFnPtr<nghttp3_conn, nghttp3_conn_del>;
-using Http3RcBufferPointer = NgRcBufPointer<Http3RcBufferPointerTraits>;
-using Http3Headers = NgHeaders<Http3HeadersTraits>;
-
-struct Http3HeaderTraits {
- typedef Http3RcBufferPointer rcbufferpointer_t;
- typedef QuicApplication allocator_t;
-
- static const char* ToHttpHeaderName(int32_t token);
-};
-
-using Http3Header = NgHeader<Http3HeaderTraits>;
-
-struct Http3ApplicationConfig : public nghttp3_conn_settings {
- Http3ApplicationConfig() {
- nghttp3_conn_settings_default(this);
- qpack_max_table_capacity = DEFAULT_QPACK_MAX_TABLE_CAPACITY;
- qpack_blocked_streams = DEFAULT_QPACK_BLOCKED_STREAMS;
- max_field_section_size = DEFAULT_MAX_HEADER_LIST_SIZE;
- max_pushes = DEFAULT_MAX_PUSHES;
- }
- uint64_t max_header_pairs = DEFAULT_MAX_HEADER_LIST_PAIRS;
- uint64_t max_header_length = DEFAULT_MAX_HEADER_LENGTH;
-};
-
-class Http3Application;
-using Http3MemoryManager =
- mem::NgLibMemoryManager<Http3Application, nghttp3_mem>;
-
-// Http3Application is used whenever the h3 alpn identifier is used.
-// It causes the QuicSession to apply HTTP/3 semantics to the connection,
-// including handling of headers and other HTTP/3 specific processing.
-class Http3Application final :
- public QuicApplication,
- public Http3MemoryManager {
- public:
- explicit Http3Application(QuicSession* session);
-
- bool Initialize() override;
-
- void StopTrackingMemory(void* ptr) override {
- Http3MemoryManager::StopTrackingMemory(ptr);
- }
-
- bool ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) override;
-
- void AcknowledgeStreamData(
- int64_t stream_id,
- uint64_t offset,
- size_t datalen) override;
-
- void StreamClose(int64_t stream_id, uint64_t app_error_code) override;
-
- void StreamReset(
- int64_t stream_id,
- uint64_t app_error_code) override;
-
- void ResumeStream(int64_t stream_id) override;
-
- void ExtendMaxStreamData(int64_t stream_id, uint64_t max_data) override;
-
- bool SubmitInformation(
- int64_t stream_id,
- v8::Local<v8::Array> headers) override;
-
- bool SubmitHeaders(
- int64_t stream_id,
- v8::Local<v8::Array> headers,
- uint32_t flags) override;
-
- bool SubmitTrailers(
- int64_t stream_id,
- v8::Local<v8::Array> headers) override;
-
- BaseObjectPtr<QuicStream> SubmitPush(
- int64_t id,
- v8::Local<v8::Array> headers) override;
-
- // Implementation for mem::NgLibMemoryManager
- void CheckAllocatedSize(size_t previous_size) const;
- void IncreaseAllocatedSize(size_t size);
- void DecreaseAllocatedSize(size_t size);
-
- SET_SELF_SIZE(Http3Application)
- SET_MEMORY_INFO_NAME(Http3Application)
- void MemoryInfo(MemoryTracker* tracker) const override;
-
- private:
- template <typename M = uint64_t, typename T>
- void SetConfig(int idx, M T::*member);
-
- nghttp3_conn* connection() const { return connection_.get(); }
- BaseObjectPtr<QuicStream> FindOrCreateStream(int64_t stream_id);
-
- bool CreateAndBindControlStream();
- bool CreateAndBindQPackStreams();
- int64_t CreateAndBindPushStream(int64_t push_id);
-
- int GetStreamData(StreamData* stream_data) override;
-
- bool BlockStream(int64_t stream_id) override;
- bool StreamCommit(StreamData* stream_data, size_t datalen) override;
- bool ShouldSetFin(const StreamData& data) override;
- bool SubmitPushPromise(
- int64_t id,
- int64_t* push_id,
- int64_t* stream_id,
- const Http3Headers& headers);
- bool SubmitInformation(int64_t id, const Http3Headers& headers);
- bool SubmitTrailers(int64_t id, const Http3Headers& headers);
- bool SubmitHeaders(int64_t id, const Http3Headers& headers, int32_t flags);
-
- ssize_t ReadData(
- int64_t stream_id,
- nghttp3_vec* vec,
- size_t veccnt,
- uint32_t* pflags);
-
- void AckedStreamData(int64_t stream_id, size_t datalen);
- void StreamClosed(int64_t stream_id, uint64_t app_error_code);
- void ReceiveData(int64_t stream_id, const uint8_t* data, size_t datalen);
- void DeferredConsume(int64_t stream_id, size_t consumed);
- void BeginHeaders(
- int64_t stream_id,
- QuicStreamHeadersKind kind = QUICSTREAM_HEADERS_KIND_NONE);
- bool ReceiveHeader(
- int64_t stream_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags);
- void EndHeaders(int64_t stream_id, int64_t push_id = 0);
- void CancelPush(int64_t push_id, int64_t stream_id);
- void SendStopSending(int64_t stream_id, uint64_t app_error_code);
- void PushStream(int64_t push_id, int64_t stream_id);
- void EndStream(int64_t stream_id);
-
- bool is_control_stream(int64_t stream_id) const {
- return stream_id == control_stream_id_ ||
- stream_id == qpack_dec_stream_id_ ||
- stream_id == qpack_enc_stream_id_;
- }
-
- nghttp3_mem alloc_info_;
- Http3ConnectionPointer connection_;
- int64_t control_stream_id_;
- int64_t qpack_enc_stream_id_;
- int64_t qpack_dec_stream_id_;
- size_t current_nghttp3_memory_ = 0;
-
- Http3ApplicationConfig config_;
-
- void CreateConnection();
-
- static const nghttp3_conn_callbacks callbacks_[2];
-
- static int OnAckedStreamData(
- nghttp3_conn* conn,
- int64_t stream_id,
- size_t datalen,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnStreamClose(
- nghttp3_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnReceiveData(
- nghttp3_conn* conn,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnDeferredConsume(
- nghttp3_conn* conn,
- int64_t stream_id,
- size_t consumed,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnBeginHeaders(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnBeginTrailers(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnReceiveHeader(
- nghttp3_conn* conn,
- int64_t stream_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnEndHeaders(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnBeginPushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnReceivePushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- int32_t token,
- nghttp3_rcbuf* name,
- nghttp3_rcbuf* value,
- uint8_t flags,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnEndPushPromise(
- nghttp3_conn* conn,
- int64_t stream_id,
- int64_t push_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnCancelPush(
- nghttp3_conn* conn,
- int64_t push_id,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnSendStopSending(
- nghttp3_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* conn_user_data,
- void* stream_user_data);
-
- static int OnPushStream(
- nghttp3_conn* conn,
- int64_t push_id,
- int64_t stream_id,
- void* conn_user_data);
-
- static int OnEndStream(
- nghttp3_conn* conn,
- int64_t stream_id,
- void* conn_user_data,
- void* stream_user_data);
-
- static ssize_t OnReadData(
- nghttp3_conn* conn,
- int64_t stream_id,
- nghttp3_vec* vec,
- size_t veccnt,
- uint32_t* pflags,
- void* conn_user_data,
- void* stream_user_data);
-};
-
-} // namespace quic
-
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-#endif // SRC_QUIC_NODE_QUIC_HTTP3_APPLICATION_H_
diff --git a/src/quic/node_quic_session-inl.h b/src/quic/node_quic_session-inl.h
deleted file mode 100644
index c506812b04..0000000000
--- a/src/quic/node_quic_session-inl.h
+++ /dev/null
@@ -1,447 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_SESSION_INL_H_
-#define SRC_QUIC_NODE_QUIC_SESSION_INL_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "debug_utils-inl.h"
-#include "node_crypto.h"
-#include "crypto/crypto_common.h"
-#include "node_quic_crypto.h"
-#include "node_quic_session.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_stream-inl.h"
-
-#include <openssl/ssl.h>
-#include <memory>
-#include <string>
-
-namespace node {
-
-namespace quic {
-
-void QuicSessionConfig::GenerateStatelessResetToken(
- QuicSession* session,
- const QuicCID& cid) {
- transport_params.stateless_reset_token_present = 1;
- StatelessResetToken token(
- transport_params.stateless_reset_token,
- session->socket()->session_reset_secret(),
- cid);
- Debug(session, "Generated stateless reset token %s for CID %s", token, cid);
-}
-
-void QuicSessionConfig::GeneratePreferredAddressToken(
- ConnectionIDStrategy connection_id_strategy,
- QuicSession* session,
- QuicCID* pscid) {
- connection_id_strategy(session, pscid->cid(), kScidLen);
- transport_params.preferred_address.cid = **pscid;
-
- StatelessResetToken(
- transport_params.preferred_address.stateless_reset_token,
- session->socket()->session_reset_secret(),
- *pscid);
-}
-
-void QuicSessionConfig::set_original_connection_id(
- const QuicCID& ocid,
- const QuicCID& scid) {
- if (ocid) {
- transport_params.original_dcid = *ocid;
- transport_params.retry_scid = *scid;
- transport_params.retry_scid_present = 1;
- } else {
- transport_params.original_dcid = *scid;
- }
-}
-
-void QuicSessionConfig::set_qlog(const ngtcp2_qlog_settings& qlog_) {
- qlog = qlog_;
-}
-
-QuicCryptoContext::QuicCryptoContext(
- QuicSession* session,
- BaseObjectPtr<crypto::SecureContext> secure_context,
- ngtcp2_crypto_side side,
- uint32_t options) :
- session_(session),
- secure_context_(secure_context),
- side_(side),
- options_(options) {
- ssl_.reset(SSL_new(secure_context_->ctx_.get()));
- CHECK(ssl_);
-}
-
-void QuicCryptoContext::Initialize() {
- InitializeTLS(session(), ssl_);
-}
-
-// Cancels and frees any remaining outbound handshake data
-// at each crypto level.
-uint64_t QuicCryptoContext::Cancel() {
- uint64_t len = handshake_[0].Cancel();
- len += handshake_[1].Cancel();
- len += handshake_[2].Cancel();
- return len;
-}
-
-v8::MaybeLocal<v8::Value> QuicCryptoContext::ocsp_response() const {
- Environment* env = session()->env();
- return crypto::GetSSLOCSPResponse(
- env,
- ssl_.get(),
- v8::Undefined(env->isolate()));
-}
-
-ngtcp2_crypto_level QuicCryptoContext::read_crypto_level() const {
- return from_ossl_level(SSL_quic_read_level(ssl_.get()));
-}
-
-ngtcp2_crypto_level QuicCryptoContext::write_crypto_level() const {
- return from_ossl_level(SSL_quic_write_level(ssl_.get()));
-}
-
-// TLS Keylogging is enabled per-QuicSession by attaching an handler to the
-// "keylog" event. Each keylog line is emitted to JavaScript where it can
-// be routed to whatever destination makes sense. Typically, this will be
-// to a keylog file that can be consumed by tools like Wireshark to intercept
-// and decrypt QUIC network traffic.
-void QuicCryptoContext::Keylog(const char* line) {
- if (UNLIKELY(session_->state_->keylog_enabled))
- session_->listener()->OnKeylog(line, strlen(line));
-}
-
-// Following a pause in the handshake for OCSP or client hello, we kickstart
-// the handshake again here by triggering ngtcp2 to serialize data.
-void QuicCryptoContext::ResumeHandshake() {
- // We haven't received any actual new handshake data but calling
- // this will trigger the handshake to continue.
- Receive(read_crypto_level(), 0, nullptr, 0);
- session_->SendPendingData();
-}
-
-// For 0RTT, this sets the TLS session data from the given buffer.
-bool QuicCryptoContext::set_session(crypto::SSLSessionPointer session) {
- if (side_ == NGTCP2_CRYPTO_SIDE_CLIENT && session != nullptr) {
- set_early_data(
- SSL_SESSION_get_max_early_data(session.get()) == 0xffffffffUL);
- }
- return crypto::SetTLSSession(ssl_, std::move(session));
-}
-
-v8::MaybeLocal<v8::Array> QuicCryptoContext::hello_ciphers() const {
- return crypto::GetClientHelloCiphers(session()->env(), ssl_);
-}
-
-v8::MaybeLocal<v8::Value> QuicCryptoContext::cipher_name() const {
- return crypto::GetCipherName(session()->env(), ssl_);
-}
-
-v8::MaybeLocal<v8::Value> QuicCryptoContext::cipher_version() const {
- return crypto::GetCipherVersion(session()->env(), ssl_);
-}
-
-const char* QuicCryptoContext::servername() const {
- return crypto::GetServerName(ssl_.get());
-}
-
-const char* QuicCryptoContext::hello_alpn() const {
- return crypto::GetClientHelloALPN(ssl_);
-}
-
-const char* QuicCryptoContext::hello_servername() const {
- return crypto::GetClientHelloServerName(ssl_);
-}
-
-v8::MaybeLocal<v8::Object> QuicCryptoContext::ephemeral_key() const {
- return crypto::GetEphemeralKey(session()->env(), ssl_);
-}
-
-v8::MaybeLocal<v8::Value> QuicCryptoContext::peer_cert(bool abbreviated) const {
- return crypto::GetPeerCert(
- session()->env(),
- ssl_,
- abbreviated,
- session()->is_server());
-}
-
-v8::MaybeLocal<v8::Value> QuicCryptoContext::cert() const {
- return crypto::GetCert(session()->env(), ssl_);
-}
-
-std::string QuicCryptoContext::selected_alpn() const {
- const unsigned char* alpn_buf = nullptr;
- unsigned int alpnlen;
- SSL_get0_alpn_selected(ssl_.get(), &alpn_buf, &alpnlen);
- return alpnlen ?
- std::string(reinterpret_cast<const char*>(alpn_buf), alpnlen) :
- std::string();
-}
-
-bool QuicCryptoContext::early_data() const {
- return
- (is_early_data() &&
- SSL_get_early_data_status(ssl_.get()) == SSL_EARLY_DATA_ACCEPTED) ||
- SSL_get_max_early_data(ssl_.get()) == 0xffffffffUL;
-}
-
-void QuicCryptoContext::set_tls_alert(int err) {
- Debug(session(), "TLS Alert [%d]: %s", err, SSL_alert_type_string_long(err));
- session_->set_last_error(QuicError(QUIC_ERROR_CRYPTO, err));
-}
-
-QuicApplication::QuicApplication(QuicSession* session) : session_(session) {}
-
-void QuicApplication::set_stream_fin(int64_t stream_id) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- CHECK(stream);
- stream->set_fin_sent();
-}
-
-std::unique_ptr<QuicPacket> QuicApplication::CreateStreamDataPacket() {
- return QuicPacket::Create(
- "stream data",
- session()->max_packet_length());
-}
-
-Environment* QuicApplication::env() const {
- return session()->env();
-}
-
-// Extends the stream-level flow control by the given number of bytes.
-void QuicSession::ExtendStreamOffset(int64_t stream_id, size_t amount) {
- Debug(this, "Extending max stream %" PRId64 " offset by %" PRId64 " bytes",
- stream_id, amount);
- ngtcp2_conn_extend_max_stream_offset(
- connection(),
- stream_id,
- amount);
-}
-
-// Extends the connection-level flow control for the entire session by
-// the given number of bytes.
-void QuicSession::ExtendOffset(size_t amount) {
- Debug(this, "Extending session offset by %" PRId64 " bytes", amount);
- ngtcp2_conn_extend_max_offset(connection(), amount);
-}
-
-// Copies the local transport params into the given struct for serialization.
-void QuicSession::GetLocalTransportParams(ngtcp2_transport_params* params) {
- CHECK(!is_destroyed());
- ngtcp2_conn_get_local_transport_params(connection(), params);
-}
-
-// Gets the QUIC version negotiated for this QuicSession
-uint32_t QuicSession::negotiated_version() const {
- CHECK(!is_destroyed());
- return ngtcp2_conn_get_negotiated_version(connection());
-}
-
-bool QuicSession::is_handshake_completed() const {
- DCHECK(!is_destroyed());
- return ngtcp2_conn_get_handshake_completed(connection());
-}
-
-void QuicSession::ShutdownStream(int64_t stream_id, uint64_t code) {
- if (is_in_closing_period() ||
- is_in_draining_period() ||
- is_silent_closing()) {
- return; // Nothing to do because we can't send any frames.
- }
- SendSessionScope send_scope(this);
- ngtcp2_conn_shutdown_stream(connection(), stream_id, 0);
-}
-
-// When a QuicSession hits the idle timeout, it is to be silently and
-// immediately closed without attempting to send any additional data to
-// the peer. All existing streams are abandoned and closed.
-void QuicSession::OnIdleTimeout() {
- if (!is_destroyed()) {
- if (state_->idle_timeout == 1) {
- Debug(this, "Idle timeout");
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- return;
- }
- state_->idle_timeout = 1;
- UpdateClosingTimer();
- }
-}
-
-QuicCID QuicSession::dcid() const {
- return QuicCID(ngtcp2_conn_get_dcid(connection()));
-}
-
-void QuicSession::CheckAllocatedSize(size_t previous_size) const {
- CHECK_GE(current_ngtcp2_memory_, previous_size);
-}
-
-void QuicSession::IncreaseAllocatedSize(size_t size) {
- current_ngtcp2_memory_ += size;
-}
-
-void QuicSession::DecreaseAllocatedSize(size_t size) {
- current_ngtcp2_memory_ -= size;
-}
-
-uint64_t QuicSession::max_data_left() const {
- return ngtcp2_conn_get_max_data_left(connection());
-}
-
-uint64_t QuicSession::max_local_streams_uni() const {
- return ngtcp2_conn_get_max_local_streams_uni(connection());
-}
-
-void QuicSession::set_last_error(QuicError error) {
- last_error_ = error;
-}
-
-void QuicSession::set_last_error(int32_t family, uint64_t code) {
- set_last_error({ family, code });
-}
-
-void QuicSession::set_last_error(int32_t family, int code) {
- set_last_error({ family, code });
-}
-
-bool QuicSession::is_in_closing_period() const {
- return ngtcp2_conn_is_in_closing_period(connection());
-}
-
-bool QuicSession::is_in_draining_period() const {
- return ngtcp2_conn_is_in_draining_period(connection());
-}
-
-bool QuicSession::HasStream(int64_t id) const {
- return streams_.find(id) != std::end(streams_);
-}
-
-bool QuicSession::allow_early_data() const {
- // TODO(@jasnell): For now, we always allow early data.
- // Later there will be reasons we do not want to allow
- // it, such as lack of available system resources.
- return true;
-}
-
-void QuicSession::SetSessionTicketAppData(
- const SessionTicketAppData& app_data) {
- application_->SetSessionTicketAppData(app_data);
-}
-
-SessionTicketAppData::Status QuicSession::GetSessionTicketAppData(
- const SessionTicketAppData& app_data,
- SessionTicketAppData::Flag flag) {
- return application_->GetSessionTicketAppData(app_data, flag);
-}
-
-bool QuicSession::is_server() const {
- return crypto_context_->side() == NGTCP2_CRYPTO_SIDE_SERVER;
-}
-
-void QuicSession::StartGracefulClose() {
- set_graceful_closing();
- RecordTimestamp(&QuicSessionStats::closing_at);
-}
-
-// The connection ID Strategy is a function that generates
-// connection ID values. By default these are generated randomly.
-void QuicSession::set_connection_id_strategy(ConnectionIDStrategy strategy) {
- CHECK_NOT_NULL(strategy);
- connection_id_strategy_ = strategy;
-}
-
-bool QuicSession::is_unable_to_send_packets() {
- return NgCallbackScope::InNgCallbackScope(this) ||
- is_destroyed() ||
- is_in_draining_period() ||
- (is_server() && is_in_closing_period()) ||
- socket() == nullptr;
-}
-
-void QuicSession::set_preferred_address_strategy(
- PreferredAddressStrategy strategy) {
- preferred_address_strategy_ = strategy;
-}
-
-QuicSocket* QuicSession::socket() const {
- return socket_.get();
-}
-
-// Indicates that the stream is blocked from transmitting any
-// data. The specific handling of this is application specific.
-// By default, we keep track of statistics but leave it up to
-// the application to perform specific handling.
-void QuicSession::StreamDataBlocked(int64_t stream_id) {
- IncrementStat(&QuicSessionStats::block_count);
- listener_->OnStreamBlocked(stream_id);
-}
-
-// When a server advertises a preferred address in its initial
-// transport parameters, ngtcp2 on the client side will trigger
-// the OnSelectPreferredAdddress callback which will call this.
-// The paddr argument contains the advertised preferred address.
-// If the new address is going to be used, it needs to be copied
-// over to dest, otherwise dest is left alone. There are two
-// possible strategies that we currently support via user
-// configuration: use the preferred address or ignore it.
-void QuicSession::SelectPreferredAddress(
- const PreferredAddress& preferred_address) {
- CHECK(!is_server());
- preferred_address_strategy_(this, preferred_address);
-}
-
-// This variant of SendPacket is used by QuicApplication
-// instances to transmit a packet and update the network
-// path used at the same time.
-bool QuicSession::SendPacket(
- std::unique_ptr<QuicPacket> packet,
- const ngtcp2_path_storage& path) {
- UpdateEndpoint(path.path);
- return SendPacket(std::move(packet));
-}
-
-// Set the transport parameters received from the remote peer
-void QuicSession::set_remote_transport_params() {
- DCHECK(!is_destroyed());
- ngtcp2_conn_get_remote_transport_params(connection(), &transport_params_);
- set_transport_params_set();
-}
-
-// Submits information headers only if the selected application
-// supports headers.
-bool QuicSession::SubmitInformation(
- int64_t stream_id,
- v8::Local<v8::Array> headers) {
- return application_->SubmitInformation(stream_id, headers);
-}
-
-// Submits initial headers only if the selected application
-// supports headers. For http3, for instance, this is the
-// method used to submit both request and response headers.
-bool QuicSession::SubmitHeaders(
- int64_t stream_id,
- v8::Local<v8::Array> headers,
- uint32_t flags) {
- return application_->SubmitHeaders(stream_id, headers, flags);
-}
-
-// Submits trailing headers only if the selected application
-// supports headers.
-bool QuicSession::SubmitTrailers(
- int64_t stream_id,
- v8::Local<v8::Array> headers) {
- return application_->SubmitTrailers(stream_id, headers);
-}
-
-// Submits a new push stream
-BaseObjectPtr<QuicStream> QuicSession::SubmitPush(
- int64_t stream_id,
- v8::Local<v8::Array> headers) {
- return application_->SubmitPush(stream_id, headers);
-}
-
-} // namespace quic
-} // namespace node
-
-#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_SESSION_INL_H_
diff --git a/src/quic/node_quic_session.cc b/src/quic/node_quic_session.cc
deleted file mode 100644
index fce6b658a4..0000000000
--- a/src/quic/node_quic_session.cc
+++ /dev/null
@@ -1,3963 +0,0 @@
-#include "node_quic_session-inl.h" // NOLINT(build/include)
-#include "aliased_buffer.h"
-#include "aliased_struct-inl.h"
-#include "allocated_buffer-inl.h"
-#include "async_wrap-inl.h"
-#include "debug_utils-inl.h"
-#include "env-inl.h"
-#include "crypto/crypto_common.h"
-#include "ngtcp2/ngtcp2.h"
-#include "nghttp3/nghttp3.h" // NGHTTP3_ALPN_H3
-#include "ngtcp2/ngtcp2_crypto.h"
-#include "ngtcp2/ngtcp2_crypto_openssl.h"
-#include "node.h"
-#include "node_buffer.h"
-#include "node_crypto.h"
-#include "node_errors.h"
-#include "node_internals.h"
-#include "node_http_common-inl.h"
-#include "node_mem-inl.h"
-#include "node_process.h"
-#include "node_quic_buffer-inl.h"
-#include "node_quic_crypto.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_stream-inl.h"
-#include "node_quic_util-inl.h"
-#include "node_quic_default_application.h"
-#include "node_quic_http3_application.h"
-#include "node_sockaddr-inl.h"
-#include "stream_base-inl.h"
-#include "v8.h"
-#include "uv.h"
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-#include <string>
-#include <utility>
-
-namespace node {
-
-using crypto::EntropySource;
-using crypto::SecureContext;
-
-using v8::Array;
-using v8::ArrayBufferView;
-using v8::Context;
-using v8::FunctionCallbackInfo;
-using v8::FunctionTemplate;
-using v8::HandleScope;
-using v8::Integer;
-using v8::Local;
-using v8::Number;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::PropertyAttribute;
-using v8::String;
-using v8::Undefined;
-using v8::Value;
-
-using TryCatchScope = node::errors::TryCatchScope;
-
-namespace quic {
-
-QuicCallbackScope::QuicCallbackScope(QuicSession* session)
- : session_(session),
- private_(new InternalCallbackScope(
- session->env(),
- session->object(),
- {
- session->get_async_id(),
- session->get_trigger_async_id()
- })),
- try_catch_(session->env()->isolate()) {
- try_catch_.SetVerbose(true);
-}
-
-QuicCallbackScope::~QuicCallbackScope() {
- Environment* env = session_->env();
- if (UNLIKELY(try_catch_.HasCaught())) {
- session_->crypto_context()->set_in_client_hello(false);
- session_->crypto_context()->set_in_ocsp_request(false);
- if (!try_catch_.HasTerminated() && env->can_call_into_js()) {
- session_->set_last_error({
- QUIC_ERROR_SESSION,
- uint64_t{NGTCP2_INTERNAL_ERROR}
- });
- session_->Close();
- CHECK(session_->is_destroyed());
- }
- private_->MarkAsFailed();
- }
-}
-
-typedef ssize_t(*ngtcp2_close_fn)(
- ngtcp2_conn* conn,
- ngtcp2_path* path,
- uint8_t* dest,
- size_t destlen,
- uint64_t error_code,
- ngtcp2_tstamp ts);
-
-namespace {
-void SetConfig(QuicState* quic_state, int idx, uint64_t* val) {
- AliasedFloat64Array& buffer = quic_state->quicsessionconfig_buffer;
- uint64_t flags = static_cast<uint64_t>(buffer[IDX_QUIC_SESSION_CONFIG_COUNT]);
- if (flags & (1ULL << idx))
- *val = static_cast<uint64_t>(buffer[idx]);
-}
-
-// Forwards detailed(verbose) debugging information from ngtcp2. Enabled using
-// the NODE_DEBUG_NATIVE=NGTCP2_DEBUG category.
-void Ngtcp2DebugLog(void* user_data, const char* fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- std::string format(fmt, strlen(fmt) + 1);
- format[strlen(fmt)] = '\n';
- // Debug() does not work with the va_list here. So we use vfprintf
- // directly instead. Ngtcp2DebugLog is only enabled when the debug
- // category is enabled.
- vfprintf(stderr, format.c_str(), ap);
- va_end(ap);
-}
-
-void CopyPreferredAddress(
- uint8_t* dest,
- size_t destlen,
- uint16_t* port,
- const sockaddr* addr) {
- const sockaddr_in* src = reinterpret_cast<const sockaddr_in*>(addr);
- memcpy(dest, &src->sin_addr, destlen);
- *port = SocketAddress::GetPort(addr);
-}
-
-ngtcp2_close_fn SelectCloseFn(uint32_t family) {
- return family == QUIC_ERROR_APPLICATION ?
- ngtcp2_conn_write_application_close :
- ngtcp2_conn_write_connection_close;
-}
-
-} // namespace
-
-std::string QuicSession::RemoteTransportParamsDebug::ToString() const {
- ngtcp2_transport_params params;
- ngtcp2_conn_get_remote_transport_params(session->connection(), &params);
- std::string out = "Remote Transport Params:\n";
- out += " Ack Delay Exponent: " +
- std::to_string(params.ack_delay_exponent) + "\n";
- out += " Active Connection ID Limit: " +
- std::to_string(params.active_connection_id_limit) + "\n";
- out += " Disable Active Migration: " +
- std::string(params.disable_active_migration ? "Yes" : "No") + "\n";
- out += " Initial Max Data: " +
- std::to_string(params.initial_max_data) + "\n";
- out += " Initial Max Stream Data Bidi Local: " +
- std::to_string(params.initial_max_stream_data_bidi_local) + "\n";
- out += " Initial Max Stream Data Bidi Remote: " +
- std::to_string(params.initial_max_stream_data_bidi_remote) + "\n";
- out += " Initial Max Stream Data Uni: " +
- std::to_string(params.initial_max_stream_data_uni) + "\n";
- out += " Initial Max Streams Bidi: " +
- std::to_string(params.initial_max_streams_bidi) + "\n";
- out += " Initial Max Streams Uni: " +
- std::to_string(params.initial_max_streams_uni) + "\n";
- out += " Max Ack Delay: " +
- std::to_string(params.max_ack_delay) + "\n";
- out += " Max Idle Timeout: " +
- std::to_string(params.max_idle_timeout) + "\n";
- out += " Max Packet Size: " +
- std::to_string(params.max_udp_payload_size) + "\n";
-
- if (!session->is_server()) {
- if (params.retry_scid_present) {
- QuicCID cid(params.original_dcid);
- QuicCID retry(params.retry_scid);
- out += " Original Connection ID: " + cid.ToString() + "\n";
- out += " Retry SCID: " + retry.ToString() + "\n";
- } else {
- out += " Original Connection ID: N/A \n";
- }
-
- if (params.preferred_address_present) {
- out += " Preferred Address Present: Yes\n";
- // TODO(@jasnell): Serialize the IPv4 and IPv6 address options
- } else {
- out += " Preferred Address Present: No\n";
- }
-
- if (params.stateless_reset_token_present) {
- StatelessResetToken token(params.stateless_reset_token);
- out += " Stateless Reset Token: " + token.ToString() + "\n";
- } else {
- out += " Stateless Reset Token: N/A";
- }
- }
- return out;
-}
-
-void QuicSessionConfig::ResetToDefaults(QuicState* quic_state) {
- ngtcp2_settings_default(this);
- initial_ts = uv_hrtime();
- // Detailed(verbose) logging provided by ngtcp2 is only enabled
- // when the NODE_DEBUG_NATIVE=NGTCP2_DEBUG category is used.
- if (UNLIKELY(quic_state->env()->enabled_debug_list()->enabled(
- DebugCategory::NGTCP2_DEBUG))) {
- log_printf = Ngtcp2DebugLog;
- }
- transport_params.active_connection_id_limit =
- DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
- transport_params.initial_max_stream_data_bidi_local =
- DEFAULT_MAX_STREAM_DATA_BIDI_LOCAL;
- transport_params.initial_max_stream_data_bidi_remote =
- DEFAULT_MAX_STREAM_DATA_BIDI_REMOTE;
- transport_params.initial_max_stream_data_uni =
- DEFAULT_MAX_STREAM_DATA_UNI;
- transport_params.initial_max_streams_bidi =
- DEFAULT_MAX_STREAMS_BIDI;
- transport_params.initial_max_streams_uni =
- DEFAULT_MAX_STREAMS_UNI;
- transport_params.initial_max_data = DEFAULT_MAX_DATA;
- transport_params.max_idle_timeout = DEFAULT_MAX_IDLE_TIMEOUT;
- transport_params.max_udp_payload_size =
- NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE;
- transport_params.max_ack_delay =
- NGTCP2_DEFAULT_MAX_ACK_DELAY;
- transport_params.disable_active_migration = 0;
- transport_params.preferred_address_present = 0;
- transport_params.stateless_reset_token_present = 0;
- cc_algo = NGTCP2_CC_ALGO_RENO;
-}
-
-// Sets the QuicSessionConfig using an AliasedBuffer for efficiency.
-void QuicSessionConfig::Set(
- QuicState* quic_state,
- const sockaddr* preferred_addr) {
- ResetToDefaults(quic_state);
- SetConfig(quic_state, IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT,
- &transport_params.active_connection_id_limit);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL,
- &transport_params.initial_max_stream_data_bidi_local);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_REMOTE,
- &transport_params.initial_max_stream_data_bidi_remote);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI,
- &transport_params.initial_max_stream_data_uni);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_DATA,
- &transport_params.initial_max_data);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_STREAMS_BIDI,
- &transport_params.initial_max_streams_bidi);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_STREAMS_UNI,
- &transport_params.initial_max_streams_uni);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT,
- &transport_params.max_idle_timeout);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE,
- &transport_params.max_udp_payload_size);
- SetConfig(quic_state, IDX_QUIC_SESSION_MAX_ACK_DELAY,
- &transport_params.max_ack_delay);
- SetConfig(quic_state,
- IDX_QUIC_SESSION_CC_ALGO,
- reinterpret_cast<uint64_t *>(&cc_algo));
-
- transport_params.max_idle_timeout =
- transport_params.max_idle_timeout * 1000000000;
-
- // TODO(@jasnell): QUIC allows both IPv4 and IPv6 addresses to be
- // specified. Here we're specifying one or the other. Need to
- // determine if that's what we want or should we support both.
- //
- // TODO(@jasnell): Currently, this is specified as a single value
- // that is used for all connections. In the future, it may be
- // necessary to determine the preferred address based on the
- // remote address. The trick, however, is that the preferred
- // address must be selected before the QuicSession is created,
- // before the handshake can be started. That is, it may need
- // to be an optional callback on QuicSocket. That would incur
- // a performance penalty so we'd really have to be sure of the
- // utility.
- if (preferred_addr != nullptr) {
- transport_params.preferred_address_present = 1;
- switch (preferred_addr->sa_family) {
- case AF_INET: {
- CopyPreferredAddress(
- transport_params.preferred_address.ipv4_addr,
- sizeof(transport_params.preferred_address.ipv4_addr),
- &transport_params.preferred_address.ipv4_port,
- preferred_addr);
- break;
- }
- case AF_INET6: {
- CopyPreferredAddress(
- transport_params.preferred_address.ipv6_addr,
- sizeof(transport_params.preferred_address.ipv6_addr),
- &transport_params.preferred_address.ipv6_port,
- preferred_addr);
- break;
- }
- default:
- UNREACHABLE();
- }
- }
-}
-
-void QuicSessionListener::OnKeylog(const char* line, size_t len) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnKeylog(line, len);
-}
-
-void QuicSessionListener::OnClientHello(
- const char* alpn,
- const char* server_name) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnClientHello(alpn, server_name);
-}
-
-QuicSessionListener::~QuicSessionListener() {
- if (session_)
- session_->RemoveListener(this);
-}
-
-void QuicSessionListener::OnCert(const char* server_name) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnCert(server_name);
-}
-
-void QuicSessionListener::OnOCSP(Local<Value> ocsp) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnOCSP(ocsp);
-}
-
-void QuicSessionListener::OnStreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnStreamHeaders(stream_id, kind, headers, push_id);
-}
-
-void QuicSessionListener::OnStreamClose(
- int64_t stream_id,
- uint64_t app_error_code) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnStreamClose(stream_id, app_error_code);
-}
-
-void QuicSessionListener::OnStreamReset(
- int64_t stream_id,
- uint64_t app_error_code) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnStreamReset(stream_id, app_error_code);
-}
-
-void QuicSessionListener::OnSessionClose(QuicError error, int flags) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnSessionClose(error, flags);
-}
-
-void QuicSessionListener::OnStreamReady(BaseObjectPtr<QuicStream> stream) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnStreamReady(stream);
-}
-
-void QuicSessionListener::OnHandshakeCompleted() {
- if (previous_listener_ != nullptr)
- previous_listener_->OnHandshakeCompleted();
-}
-
-void QuicSessionListener::OnPathValidation(
- ngtcp2_path_validation_result res,
- const sockaddr* local,
- const sockaddr* remote) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnPathValidation(res, local, remote);
-}
-
-void QuicSessionListener::OnSessionTicket(int size, SSL_SESSION* session) {
- if (previous_listener_ != nullptr) {
- previous_listener_->OnSessionTicket(size, session);
- }
-}
-
-void QuicSessionListener::OnStreamBlocked(int64_t stream_id) {
- if (previous_listener_ != nullptr) {
- previous_listener_->OnStreamBlocked(stream_id);
- }
-}
-
-void QuicSessionListener::OnUsePreferredAddress(
- int family,
- const PreferredAddress& preferred_address) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnUsePreferredAddress(family, preferred_address);
-}
-
-void QuicSessionListener::OnVersionNegotiation(
- uint32_t supported_version,
- const uint32_t* versions,
- size_t vcnt) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnVersionNegotiation(supported_version, versions, vcnt);
-}
-
-void QuicSessionListener::OnQLog(QLogStream* qlog_stream) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnQLog(qlog_stream);
-}
-
-void JSQuicSessionListener::OnKeylog(const char* line, size_t len) {
- Environment* env = session()->env();
-
- HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> line_buf;
- if (!Buffer::Copy(env, line, 1 + len).ToLocal(&line_buf))
- return;
-
- char* data = Buffer::Data(line_buf);
- data[len] = '\n';
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
- USE(env->quic_on_session_keylog_function()->Call(
- env->context(),
- session()->object(),
- 1,
- &line_buf));
-}
-
-void JSQuicSessionListener::OnStreamBlocked(int64_t stream_id) {
- Environment* env = session()->env();
-
- HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- USE(env->quic_on_stream_blocked_function()->Call(
- env->context(),
- stream->object(),
- 0, nullptr));
-}
-
-void JSQuicSessionListener::OnClientHello(
- const char* alpn,
- const char* server_name) {
-
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- // Why this instead of using MakeCallback? We need to catch any
- // errors that happen both when preparing the arguments and
- // invoking the callback so that we can properly signal a failure
- // to the peer.
- QuicCallbackScope cb_scope(session());
-
- Local<Array> ciphers;
- Local<Value> alpn_string = Undefined(env->isolate());
- Local<Value> servername = Undefined(env->isolate());
-
- if (!session()->crypto_context()->hello_ciphers().ToLocal(&ciphers) ||
- (alpn != nullptr &&
- !String::NewFromUtf8(
- env->isolate(),
- alpn).ToLocal(&alpn_string)) ||
- (server_name != nullptr &&
- !String::NewFromUtf8(
- env->isolate(),
- server_name).ToLocal(&servername))) {
- return;
- }
-
- Local<Value> argv[] = {
- alpn_string,
- servername,
- ciphers
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
- USE(env->quic_on_session_client_hello_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnCert(const char* server_name) {
- Environment* env = session()->env();
- HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> servername = Undefined(env->isolate());
- if (UNLIKELY(server_name != nullptr &&
- !String::NewFromUtf8(
- env->isolate(),
- server_name,
- v8::NewStringType::kNormal,
- strlen(server_name)).ToLocal(&servername))) {
- return;
- }
-
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_session_cert_function()->Call(
- env->context(),
- session()->object(),
- 1, &servername));
-}
-
-void JSQuicSessionListener::OnStreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
- MaybeStackBuffer<Local<Value>, 16> head(headers.size());
- size_t n = 0;
-
- QuicCallbackScope cb_scope(session());
-
- for (const auto& header : headers) {
- Local<Value> pair[2];
-
- if (UNLIKELY(!header->GetName(session()->application()).ToLocal(&pair[0])))
- return;
-
- if (UNLIKELY(!header->GetValue(session()->application()).ToLocal(&pair[1])))
- return;
-
- head[n++] = Array::New(env->isolate(), pair, arraysize(pair));
- }
-
- Local<Value> argv[] = {
- Number::New(env->isolate(), static_cast<double>(stream_id)),
- Array::New(env->isolate(), head.out(), n),
- Integer::New(env->isolate(), kind),
- Undefined(env->isolate())
- };
-
- if (kind == QUICSTREAM_HEADERS_KIND_PUSH)
- argv[3] = Number::New(env->isolate(), static_cast<double>(push_id));
-
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_stream_headers_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnOCSP(Local<Value> ocsp) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
- QuicCallbackScope cb_scope(session());
- BaseObjectPtr<QuicSession> ptr(session());
- USE(env->quic_on_session_status_function()->Call(
- env->context(),
- session()->object(),
- 1, &ocsp));
-}
-
-void JSQuicSessionListener::OnStreamClose(
- int64_t stream_id,
- uint64_t app_error_code) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- Number::New(env->isolate(), static_cast<double>(stream_id)),
- Number::New(env->isolate(), static_cast<double>(app_error_code))
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_stream_close_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnStreamReset(
- int64_t stream_id,
- uint64_t app_error_code) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- Number::New(env->isolate(), static_cast<double>(stream_id)),
- Number::New(env->isolate(), static_cast<double>(app_error_code))
- };
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_stream_reset_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnSessionClose(QuicError error, int flags) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- Number::New(env->isolate(), static_cast<double>(error.code)),
- Integer::New(env->isolate(), error.family),
- flags & SESSION_CLOSE_FLAG_SILENT
- ? v8::True(env->isolate())
- : v8::False(env->isolate()),
- flags & SESSION_CLOSE_FLAG_STATELESS_RESET
- ? v8::True(env->isolate())
- : v8::False(env->isolate())
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
- USE(env->quic_on_session_close_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnStreamReady(BaseObjectPtr<QuicStream> stream) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- stream->object(),
- Number::New(env->isolate(), static_cast<double>(stream->id())),
- Number::New(env->isolate(), static_cast<double>(stream->push_id()))
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_stream_ready_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnHandshakeCompleted() {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCryptoContext* ctx = session()->crypto_context();
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> servername = Undefined(env->isolate());
- Local<Value> validationErrorReason = v8::Null(env->isolate());
- Local<Value> validationErrorCode = v8::Null(env->isolate());
- Local<Value> cipher_name;
- Local<Value> cipher_version;
-
- const char* hostname = ctx->servername();
- if (hostname != nullptr &&
- !String::NewFromUtf8(env->isolate(), hostname).ToLocal(&servername)) {
- return;
- }
-
- if (!ctx->cipher_name().ToLocal(&cipher_name) ||
- !ctx->cipher_version().ToLocal(&cipher_version)) {
- return;
- }
-
- int err = ctx->VerifyPeerIdentity();
- if (err != X509_V_OK &&
- (!crypto::GetValidationErrorReason(env, err)
- .ToLocal(&validationErrorReason) ||
- !crypto::GetValidationErrorCode(env, err)
- .ToLocal(&validationErrorCode))) {
- return;
- }
-
- Local<Value> argv[] = {
- servername,
- GetALPNProtocol(*session()),
- cipher_name,
- cipher_version,
- Integer::New(env->isolate(), session()->max_pktlen_),
- validationErrorReason,
- validationErrorCode,
- session()->crypto_context()->early_data() ?
- v8::True(env->isolate()) :
- v8::False(env->isolate())
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_session_handshake_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnPathValidation(
- ngtcp2_path_validation_result res,
- const sockaddr* local,
- const sockaddr* remote) {
- // This is a fairly expensive operation because both the local and
- // remote addresses have to converted into JavaScript objects. We
- // only do this if a pathValidation handler is registered.
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Local<Context> context = env->context();
- Context::Scope context_scope(context);
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- Integer::New(env->isolate(), res),
- AddressToJS(env, local),
- AddressToJS(env, remote)
- };
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_session_path_validation_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnSessionTicket(int size, SSL_SESSION* sess) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
-
- QuicCallbackScope cb_scope(session());
-
- Local<Value> argv[] = {
- v8::Undefined(env->isolate()),
- v8::Undefined(env->isolate())
- };
-
- if (size > 0) {
- AllocatedBuffer session_ticket =
- AllocatedBuffer::AllocateManaged(env, size);
- unsigned char* session_data =
- reinterpret_cast<unsigned char*>(session_ticket.data());
- memset(session_data, 0, size);
- if (i2d_SSL_SESSION(sess, &session_data) > 0 &&
- !session_ticket.ToBuffer().ToLocal(&argv[0])) {
- return;
- }
- }
-
- if (session()->is_transport_params_set() &&
- !Buffer::Copy(env,
- reinterpret_cast<const char*>(&session()->transport_params_),
- sizeof(session()->transport_params_)).ToLocal(&argv[1])) {
- return;
- }
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_session_ticket_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnUsePreferredAddress(
- int family,
- const PreferredAddress& preferred_address) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Local<Context> context = env->context();
- Context::Scope context_scope(context);
-
- QuicCallbackScope cb_scope(session());
-
- std::string hostname = family == AF_INET ?
- preferred_address.ipv4_address():
- preferred_address.ipv6_address();
- uint16_t port =
- family == AF_INET ?
- preferred_address.ipv4_port() :
- preferred_address.ipv6_port();
-
- Local<Value> argv[] = {
- OneByteString(env->isolate(), hostname.c_str()),
- Integer::NewFromUnsigned(env->isolate(), port),
- Integer::New(env->isolate(), family)
- };
-
- BaseObjectPtr<QuicSession> ptr(session());
-
- USE(env->quic_on_session_use_preferred_address_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnVersionNegotiation(
- uint32_t supported_version,
- const uint32_t* vers,
- size_t vcnt) {
- Environment* env = session()->env();
- HandleScope scope(env->isolate());
- Local<Context> context = env->context();
- Context::Scope context_scope(context);
-
- QuicCallbackScope cb_scope(session());
-
- MaybeStackBuffer<Local<Value>, 4> versions(vcnt);
- for (size_t n = 0; n < vcnt; n++)
- versions[n] = Integer::New(env->isolate(), vers[n]);
-
- // Currently, we only support one version of QUIC but in
- // the future that may change. The callback below passes
- // an array back to the JavaScript side to future-proof.
- Local<Value> supported =
- Integer::New(env->isolate(), supported_version);
-
- Local<Value> argv[] = {
- Integer::New(env->isolate(), NGTCP2_PROTO_VER),
- Array::New(env->isolate(), versions.out(), vcnt),
- Array::New(env->isolate(), &supported, 1)
- };
-
- // Grab a shared pointer to this to prevent the QuicSession
- // from being freed while the MakeCallback is running.
- BaseObjectPtr<QuicSession> ptr(session());
- USE(env->quic_on_session_version_negotiation_function()->Call(
- env->context(),
- session()->object(),
- arraysize(argv),
- argv));
-}
-
-void JSQuicSessionListener::OnQLog(QLogStream* qlog_stream) {
- CHECK_NOT_NULL(qlog_stream);
- Environment* env = session()->env();
- HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
- QuicCallbackScope cb_scope(session());
- Local<Value> obj = qlog_stream->object();
- USE(env->quic_on_session_qlog_function()->Call(
- env->context(),
- session()->object(),
- 1, &obj));
-}
-
-// Generates a new random connection ID.
-void QuicSession::RandomConnectionIDStrategy(
- QuicSession* session,
- ngtcp2_cid* cid,
- size_t cidlen) {
- // CID min and max length is determined by the QUIC specification.
- CHECK_LE(cidlen, NGTCP2_MAX_CIDLEN);
- CHECK_GE(cidlen, NGTCP2_MIN_CIDLEN);
- cid->datalen = cidlen;
- // cidlen shouldn't ever be zero here but just in case that
- // behavior changes in ngtcp2 in the future...
- if (LIKELY(cidlen > 0))
- EntropySource(cid->data, cidlen);
-}
-
-// Check required capabilities were not excluded from the OpenSSL build:
-// - OPENSSL_NO_SSL_TRACE excludes SSL_trace()
-// - OPENSSL_NO_STDIO excludes BIO_new_fp()
-// HAVE_SSL_TRACE is available on the internal tcp_wrap binding for the tests.
-#if defined(OPENSSL_NO_SSL_TRACE) || defined(OPENSSL_NO_STDIO)
-# define HAVE_SSL_TRACE 0
-#else
-# define HAVE_SSL_TRACE 1
-#endif
-
-QuicCryptoContext::~QuicCryptoContext() {
- // Free any remaining crypto handshake data (if any)
- Cancel();
-}
-
-void QuicCryptoContext::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("initial_crypto", handshake_[0]);
- tracker->TrackField("handshake_crypto", handshake_[1]);
- tracker->TrackField("app_crypto", handshake_[2]);
- tracker->TrackField("ocsp_response", ocsp_response_);
-}
-
-bool QuicCryptoContext::SetSecrets(
- ngtcp2_crypto_level level,
- const uint8_t* rx_secret,
- const uint8_t* tx_secret,
- size_t secretlen) {
-
- static constexpr int kCryptoKeylen = 64;
- static constexpr int kCryptoIvlen = 64;
- static constexpr char kQuicClientEarlyTrafficSecret[] =
- "QUIC_CLIENT_EARLY_TRAFFIC_SECRET";
- static constexpr char kQuicClientHandshakeTrafficSecret[] =
- "QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET";
- static constexpr char kQuicClientTrafficSecret0[] =
- "QUIC_CLIENT_TRAFFIC_SECRET_0";
- static constexpr char kQuicServerHandshakeTrafficSecret[] =
- "QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET";
- static constexpr char kQuicServerTrafficSecret[] =
- "QUIC_SERVER_TRAFFIC_SECRET_0";
-
- uint8_t rx_key[kCryptoKeylen];
- uint8_t rx_hp[kCryptoKeylen];
- uint8_t tx_key[kCryptoKeylen];
- uint8_t tx_hp[kCryptoKeylen];
- uint8_t rx_iv[kCryptoIvlen];
- uint8_t tx_iv[kCryptoIvlen];
-
- if (NGTCP2_ERR(ngtcp2_crypto_derive_and_install_rx_key(
- session()->connection(),
- rx_key,
- rx_iv,
- rx_hp,
- level,
- rx_secret,
- secretlen))) {
- return false;
- }
-
- if (NGTCP2_ERR(ngtcp2_crypto_derive_and_install_tx_key(
- session()->connection(),
- tx_key,
- tx_iv,
- tx_hp,
- level,
- tx_secret,
- secretlen))) {
- return false;
- }
-
- switch (level) {
- case NGTCP2_CRYPTO_LEVEL_EARLY:
- crypto::LogSecret(
- ssl_,
- kQuicClientEarlyTrafficSecret,
- rx_secret,
- secretlen);
- break;
- case NGTCP2_CRYPTO_LEVEL_HANDSHAKE:
- crypto::LogSecret(
- ssl_,
- kQuicClientHandshakeTrafficSecret,
- rx_secret,
- secretlen);
- crypto::LogSecret(
- ssl_,
- kQuicServerHandshakeTrafficSecret,
- tx_secret,
- secretlen);
- break;
- case NGTCP2_CRYPTO_LEVEL_APP:
- crypto::LogSecret(
- ssl_,
- kQuicClientTrafficSecret0,
- rx_secret,
- secretlen);
- crypto::LogSecret(
- ssl_,
- kQuicServerTrafficSecret,
- tx_secret,
- secretlen);
- break;
- default:
- UNREACHABLE();
- }
-
- return true;
-}
-
-void QuicCryptoContext::AcknowledgeCryptoData(
- ngtcp2_crypto_level level,
- uint64_t datalen) {
- // It is possible for the QuicSession to have been destroyed but not yet
- // deconstructed. In such cases, we want to ignore the callback as there
- // is nothing to do but wait for further cleanup to happen.
- if (UNLIKELY(session_->is_destroyed()))
- return;
- Debug(session(),
- "Acknowledging %" PRIu64 " crypto bytes for %s level",
- datalen,
- crypto_level_name(level));
-
- // Consumes (frees) the given number of bytes in the handshake buffer.
- handshake_[level].Consume(static_cast<size_t>(datalen));
-
- // Update the statistics for the handshake, allowing us to track
- // how long the handshake is taking to be acknowledged. A malicious
- // peer could potentially force the QuicSession to hold on to
- // crypto data for a long time by not sending an acknowledgement.
- // The histogram will allow us to track the time periods between
- // acknowlegements.
- session()->RecordAck(&QuicSessionStats::handshake_acked_at);
-}
-
-void QuicCryptoContext::EnableTrace() {
-#if HAVE_SSL_TRACE
- if (!bio_trace_) {
- bio_trace_.reset(BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT));
- SSL_set_msg_callback(
- ssl_.get(),
- [](int write_p,
- int version,
- int content_type,
- const void* buf,
- size_t len,
- SSL* ssl,
- void* arg) -> void {
- crypto::MarkPopErrorOnReturn mark_pop_error_on_return;
- SSL_trace(write_p, version, content_type, buf, len, ssl, arg);
- });
- SSL_set_msg_callback_arg(ssl_.get(), bio_trace_.get());
- }
-#endif
-}
-
-// If a 'clientHello' event listener is registered on the JavaScript
-// QuicServerSession object, the STATE_CLIENT_HELLO_ENABLED state
-// will be set and the OnClientHello will cause the 'clientHello'
-// event to be emitted.
-//
-// The 'clientHello' callback will be given it's own callback function
-// that must be called when the client has completed handling the event.
-// The handshake will not continue until it is called.
-//
-// The intent here is to allow user code the ability to modify or
-// replace the SecurityContext based on the server name, ALPN, or
-// other handshake characteristics.
-//
-// The user can also set a 'cert' event handler that will be called
-// when the peer certificate is received, allowing additional tweaks
-// and verifications to be performed.
-int QuicCryptoContext::OnClientHello() {
- if (LIKELY(session_->state_->client_hello_enabled == 0))
- return 0;
-
- TLSCallbackScope callback_scope(this);
-
- if (is_in_client_hello())
- return -1;
- set_in_client_hello();
-
- QuicCryptoContext* ctx = session_->crypto_context();
- session_->listener()->OnClientHello(
- ctx->hello_alpn(),
- ctx->hello_servername());
-
- // Returning -1 here will keep the TLS handshake paused until the
- // client hello callback is invoked. Returning 0 means that the
- // handshake is ready to proceed. When the OnClientHello callback
- // is called above, it may be resolved synchronously or asynchronously.
- // In case it is resolved synchronously, we need the check below.
- return is_in_client_hello() ? -1 : 0;
-}
-
-// The OnCert callback provides an opportunity to prompt the server to
-// perform on OCSP request on behalf of the client (when the client
-// requests it). If there is a listener for the 'OCSPRequest' event
-// on the JavaScript side, the IDX_QUIC_SESSION_STATE_CERT_ENABLED
-// session state slot will equal 1, which will cause the callback to
-// be invoked. The callback will be given a reference to a JavaScript
-// function that must be called in order for the TLS handshake to
-// continue.
-int QuicCryptoContext::OnOCSP() {
- if (LIKELY(session_->state_->ocsp_enabled == 0)) {
- Debug(session(), "No OCSPRequest handler registered");
- return 1;
- }
-
- if (!session_->is_server())
- return 1;
-
- Debug(session(), "Client is requesting an OCSP Response");
- TLSCallbackScope callback_scope(this);
-
- // As in node_crypto.cc, this is not an error, but does suspend the
- // handshake to continue when OnOCSP is complete.
- if (is_in_ocsp_request())
- return -1;
- set_in_ocsp_request();
-
- session_->listener()->OnCert(session_->crypto_context()->servername());
-
- // Returning -1 here means that we are still waiting for the OCSP
- // request to be completed. When the OnCert handler is invoked
- // above, it can be resolve synchronously or asynchonously. If
- // resolved synchronously, we need the check below.
- return is_in_ocsp_request() ? -1 : 1;
-}
-
-void QuicCryptoContext::OnClientHelloDone(
- BaseObjectPtr<SecureContext> context) {
- Debug(session(),
- "ClientHello completed. Context Provided? %s\n",
- context ? "Yes" : "No");
-
- // Continue the TLS handshake when this function exits
- // otherwise it will stall and fail.
- TLSHandshakeScope handshake_scope(
- this,
- [&]() { set_in_client_hello(false); });
-
- // Disable the callback at this point so we don't loop continuously
- session_->state_->client_hello_enabled = 0;
-
- if (context) {
- int err = crypto::UseSNIContext(ssl_, context);
- if (!err) {
- unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
- return !err ?
- THROW_ERR_QUIC_FAILURE_SETTING_SNI_CONTEXT(session_->env()) :
- crypto::ThrowCryptoError(session_->env(), err);
- }
- secure_context_ = context;
- }
-}
-
-// The OnCertDone function is called by the QuicSessionOnCertDone
-// function when usercode is done handling the OCSPRequest event.
-void QuicCryptoContext::OnOCSPDone(Local<Value> ocsp_response) {
- Debug(session(),
- "OCSPRequest completed. Response Provided? %s",
- ocsp_response->IsArrayBufferView() ? "Yes" : "No");
- // Continue the TLS handshake when this function exits
- // otherwise it will stall and fail.
- TLSHandshakeScope handshake_scope(
- this,
- [&]() { set_in_ocsp_request(false); });
-
- // Disable the callback at this point so we don't loop continuously
- session_->state_->ocsp_enabled = 0;
-
- if (ocsp_response->IsArrayBufferView()) {
- ocsp_response_.Reset(
- session_->env()->isolate(),
- ocsp_response.As<ArrayBufferView>());
- }
-}
-
-// At this point in time, the TLS handshake secrets have been
-// generated by openssl for this end of the connection and are
-// ready to be used. Within this function, we need to install
-// the secrets into the ngtcp2 connection object, store the
-// remote transport parameters, and begin initialization of
-// the QuicApplication that was selected.
-bool QuicCryptoContext::OnSecrets(
- ngtcp2_crypto_level level,
- const uint8_t* rx_secret,
- const uint8_t* tx_secret,
- size_t secretlen) {
-
- Debug(session(),
- "Received secrets for %s crypto level",
- crypto_level_name(level));
-
- if (!SetSecrets(level, rx_secret, tx_secret, secretlen))
- return false;
-
- if (level == NGTCP2_CRYPTO_LEVEL_APP) {
- session_->set_remote_transport_params();
- if (!session()->InitApplication())
- return false;
- }
-
- return true;
-}
-
-// When the client has requested OSCP, this function will be called to provide
-// the OSCP response. The OnCert() callback should have already been called
-// by this point if any data is to be provided. If it hasn't, and ocsp_response_
-// is empty, no OCSP response will be sent.
-int QuicCryptoContext::OnTLSStatus() {
- Environment* env = session_->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
- switch (side_) {
- case NGTCP2_CRYPTO_SIDE_SERVER: {
- if (ocsp_response_.IsEmpty()) {
- Debug(session(), "There is no OCSP response");
- return SSL_TLSEXT_ERR_NOACK;
- }
-
- Local<ArrayBufferView> obj =
- PersistentToLocal::Default(
- env->isolate(),
- ocsp_response_);
- size_t len = obj->ByteLength();
-
- unsigned char* data = crypto::MallocOpenSSL<unsigned char>(len);
- obj->CopyContents(data, len);
-
- Debug(session(), "There is an OCSP response of %d bytes", len);
-
- if (!SSL_set_tlsext_status_ocsp_resp(ssl_.get(), data, len))
- OPENSSL_free(data);
-
- ocsp_response_.Reset();
-
- return SSL_TLSEXT_ERR_OK;
- }
- case NGTCP2_CRYPTO_SIDE_CLIENT: {
- // Only invoke the callback if the ocsp handler is actually set
- if (LIKELY(session_->state_->ocsp_enabled == 0))
- return 1;
- Local<Value> res;
- if (ocsp_response().ToLocal(&res))
- session_->listener()->OnOCSP(res);
- return 1;
- }
- default:
- UNREACHABLE();
- }
-}
-
-// Called by ngtcp2 when a chunk of peer TLS handshake data is received.
-// For every chunk, we move the TLS handshake further along until it
-// is complete.
-int QuicCryptoContext::Receive(
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen) {
- if (UNLIKELY(session_->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- // Statistics are collected so we can monitor how long the
- // handshake is taking to operate and complete.
- if (session_->GetStat(&QuicSessionStats::handshake_start_at) == 0)
- session_->RecordTimestamp(&QuicSessionStats::handshake_start_at);
- session_->RecordTimestamp(&QuicSessionStats::handshake_continue_at);
-
- Debug(session(), "Receiving %d bytes of crypto data", datalen);
-
- // Internally, this passes the handshake data off to openssl
- // for processing. The handshake may or may not complete.
- int ret = ngtcp2_crypto_read_write_crypto_data(
- session_->connection(),
- crypto_level,
- data,
- datalen);
- switch (ret) {
- case 0:
- return 0;
- // In either of following cases, the handshake is being
- // paused waiting for user code to take action (for instance
- // OCSP requests or client hello modification)
- case NGTCP2_CRYPTO_ERR_TLS_WANT_X509_LOOKUP:
- Debug(session(), "TLS handshake wants X509 Lookup");
- return 0;
- case NGTCP2_CRYPTO_ERR_TLS_WANT_CLIENT_HELLO_CB:
- Debug(session(), "TLS handshake wants client hello callback");
- return 0;
- default:
- return ret;
- }
-}
-
-// Triggers key update to begin. This will fail and return false
-// if either a previous key update is in progress and has not been
-// confirmed or if the initial handshake has not yet been confirmed.
-bool QuicCryptoContext::InitiateKeyUpdate() {
- if (UNLIKELY(session_->is_destroyed()))
- return false;
-
- // There's no user code that should be able to run while UpdateKey
- // is running, but we need to gate on it just to be safe.
- auto leave = OnScopeLeave([&]() { set_in_key_update(false); });
- CHECK(!is_in_key_update());
- set_in_key_update();
- Debug(session(), "Initiating Key Update");
-
- session_->IncrementStat(&QuicSessionStats::keyupdate_count);
-
- return ngtcp2_conn_initiate_key_update(
- session_->connection(),
- uv_hrtime()) == 0;
-}
-
-int QuicCryptoContext::VerifyPeerIdentity() {
- return crypto::VerifyPeerCertificate(ssl_);
-}
-
-// Write outbound TLS handshake data into the ngtcp2 connection
-// to prepare it to be serialized. The outbound data must be
-// stored in the handshake_ until it is acknowledged by the
-// remote peer. It's important to keep in mind that there is
-// a potential security risk here -- that is, a malicious peer
-// can cause the local session to keep sent handshake data in
-// memory by failing to acknowledge it or slowly acknowledging
-// it. We currently do not track how much data is being buffered
-// here but we do record statistics on how long the handshake
-// data is foreced to be kept in memory.
-void QuicCryptoContext::WriteHandshake(
- ngtcp2_crypto_level level,
- const uint8_t* data,
- size_t datalen) {
- Debug(session(),
- "Writing %d bytes of %s handshake data.",
- datalen,
- crypto_level_name(level));
- std::unique_ptr<QuicBufferChunk> buffer =
- std::make_unique<QuicBufferChunk>(datalen);
- memcpy(buffer->out(), data, datalen);
- session_->RecordTimestamp(&QuicSessionStats::handshake_send_at);
- CHECK_EQ(
- ngtcp2_conn_submit_crypto_data(
- session_->connection(),
- level,
- buffer->out(),
- datalen), 0);
- handshake_[level].Push(std::move(buffer));
-}
-
-void QuicApplication::Acknowledge(
- int64_t stream_id,
- uint64_t offset,
- size_t datalen) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (LIKELY(stream)) {
- stream->Acknowledge(offset, datalen);
- ResumeStream(stream_id);
- }
-}
-
-bool QuicApplication::SendPendingData() {
- // The maximum number of packets to send per call
- static constexpr size_t kMaxPackets = 16;
- QuicPathStorage path;
- std::unique_ptr<QuicPacket> packet;
- uint8_t* pos = nullptr;
- size_t packets_sent = 0;
- int err;
-
- for (;;) {
- ssize_t ndatalen;
- StreamData stream_data;
- err = GetStreamData(&stream_data);
- if (err < 0) {
- session()->set_last_error(QUIC_ERROR_APPLICATION, err);
- return false;
- }
-
- // If stream_data.id is -1, then we're not serializing any data for any
- // specific stream. We still need to process QUIC session packets tho.
- if (stream_data.id > -1)
- Debug(session(), "Serializing packets for stream id %" PRId64,
- stream_data.id);
- else
- Debug(session(), "Serializing session packets");
-
- // If the packet was sent previously, then packet will have been reset.
- if (!packet) {
- packet = CreateStreamDataPacket();
- pos = packet->data();
- }
-
- ssize_t nwrite = WriteVStream(&path, pos, &ndatalen, stream_data);
-
- if (nwrite <= 0) {
- switch (nwrite) {
- case 0:
- goto congestion_limited;
- case NGTCP2_ERR_PKT_NUM_EXHAUSTED:
- // There is a finite number of packets that can be sent
- // per connection. Once those are exhausted, there's
- // absolutely nothing we can do except immediately
- // and silently tear down the QuicSession. This has
- // to be silent because we can't even send a
- // CONNECTION_CLOSE since even those require a
- // packet number.
- session()->Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- return false;
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
- session()->StreamDataBlocked(stream_data.id);
- if (session()->max_data_left() == 0)
- goto congestion_limited;
- // Fall through
- case NGTCP2_ERR_STREAM_SHUT_WR:
- if (UNLIKELY(!BlockStream(stream_data.id)))
- return false;
- continue;
- case NGTCP2_ERR_STREAM_NOT_FOUND:
- continue;
- case NGTCP2_ERR_WRITE_MORE:
- CHECK_GT(ndatalen, 0);
- CHECK(StreamCommit(&stream_data, ndatalen));
- pos += ndatalen;
- continue;
- }
- session()->set_last_error(QUIC_ERROR_SESSION, static_cast<int>(nwrite));
- return false;
- }
-
- pos += nwrite;
-
- if (ndatalen >= 0)
- CHECK(StreamCommit(&stream_data, ndatalen));
-
- Debug(session(), "Sending %" PRIu64 " bytes in serialized packet", nwrite);
- packet->set_length(nwrite);
- if (!session()->SendPacket(std::move(packet), path))
- return false;
- packet.reset();
- pos = nullptr;
- MaybeSetFin(stream_data);
- if (++packets_sent == kMaxPackets)
- break;
- }
- return true;
-
-congestion_limited:
- // We are either congestion limited or done.
- if (pos - packet->data()) {
- // Some data was serialized into the packet. We need to send it.
- packet->set_length(pos - packet->data());
- Debug(session(), "Congestion limited, but %" PRIu64 " bytes pending",
- packet->length());
- if (!session()->SendPacket(std::move(packet), path))
- return false;
- }
- return true;
-}
-
-ssize_t QuicApplication::WriteVStream(
- QuicPathStorage* path,
- uint8_t* buf,
- ssize_t* ndatalen,
- const StreamData& stream_data) {
- CHECK_LE(stream_data.count, kMaxVectorCount);
-
- uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_NONE;
- if (stream_data.remaining > 0)
- flags |= NGTCP2_WRITE_STREAM_FLAG_MORE;
- if (stream_data.fin)
- flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
-
- return ngtcp2_conn_writev_stream(
- session()->connection(),
- &path->path,
- buf,
- session()->max_packet_length(),
- ndatalen,
- flags,
- stream_data.id,
- stream_data.buf,
- stream_data.count,
- uv_hrtime());
-}
-
-void QuicApplication::MaybeSetFin(const StreamData& stream_data) {
- if (ShouldSetFin(stream_data))
- set_stream_fin(stream_data.id);
-}
-
-void QuicApplication::StreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id) {
- session()->listener()->OnStreamHeaders(stream_id, kind, headers, push_id);
-}
-
-void QuicApplication::StreamClose(
- int64_t stream_id,
- uint64_t app_error_code) {
- BaseObjectPtr<QuicStream> stream = session()->FindStream(stream_id);
- if (stream) {
- CHECK(!stream->is_destroyed()); // Should not be possible
- stream->set_destroyed();
- stream->CancelPendingWrites();
- session()->RemoveStream(stream_id);
- session()->listener()->OnStreamClose(stream_id, app_error_code);
- }
-}
-
-void QuicApplication::StreamReset(
- int64_t stream_id,
- uint64_t app_error_code) {
- session()->listener()->OnStreamReset(stream_id, app_error_code);
-}
-
-// Determines which QuicApplication variant the QuicSession will be using
-// based on the alpn configured for the application. For now, this is
-// determined through configuration when tghe QuicSession is created
-// and is not negotiable. In the future, we may allow it to be negotiated.
-QuicApplication* QuicSession::SelectApplication(QuicSession* session) {
- std::string alpn = session->alpn();
- if (alpn == NGHTTP3_ALPN_H3) {
- Debug(this, "Selecting HTTP/3 Application");
- return new Http3Application(session);
- }
- // In the future, we may end up supporting additional
- // QUIC protocols. As they are added, extend the cases
- // here to create and return them.
-
- Debug(this, "Selecting Default Application");
- return new DefaultApplication(session);
-}
-
-// Server QuicSession Constructor
-QuicSession::QuicSession(
- QuicSocket* socket,
- const QuicSessionConfig& config,
- Local<Object> wrap,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- const std::string& alpn,
- uint32_t options,
- QlogMode qlog)
- : QuicSession(
- NGTCP2_CRYPTO_SIDE_SERVER,
- socket,
- wrap,
- socket->server_secure_context(),
- AsyncWrap::PROVIDER_QUICSERVERSESSION,
- alpn,
- std::string(""), // empty hostname. not used on server side
- dcid,
- options,
- nullptr) {
- // The config is copied by assignment in the call below.
- InitServer(config, local_addr, remote_addr, dcid, scid, ocid, version, qlog);
-}
-
-// Client QuicSession Constructor
-QuicSession::QuicSession(
- QuicSocket* socket,
- v8::Local<v8::Object> wrap,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- BaseObjectPtr<SecureContext> secure_context,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- Local<Value> dcid,
- PreferredAddressStrategy preferred_address_strategy,
- const std::string& alpn,
- const std::string& hostname,
- uint32_t options,
- QlogMode qlog)
- : QuicSession(
- NGTCP2_CRYPTO_SIDE_CLIENT,
- socket,
- wrap,
- secure_context,
- AsyncWrap::PROVIDER_QUICCLIENTSESSION,
- alpn,
- hostname,
- QuicCID(),
- options,
- preferred_address_strategy) {
- set_wrapped();
- InitClient(
- local_addr,
- remote_addr,
- early_transport_params,
- std::move(early_session_ticket),
- dcid,
- qlog);
-}
-
-// QuicSession is an abstract base class that defines the code used by both
-// server and client sessions.
-QuicSession::QuicSession(
- ngtcp2_crypto_side side,
- QuicSocket* socket,
- Local<Object> wrap,
- BaseObjectPtr<SecureContext> secure_context,
- AsyncWrap::ProviderType provider_type,
- const std::string& alpn,
- const std::string& hostname,
- const QuicCID& dcid,
- uint32_t options,
- PreferredAddressStrategy preferred_address_strategy)
- : AsyncWrap(socket->env(), wrap, provider_type),
- StatsBase(socket->env(), wrap,
- HistogramOptions::ACK |
- HistogramOptions::RATE),
- alloc_info_(MakeAllocator()),
- socket_(socket),
- alpn_(alpn),
- hostname_(hostname),
- idle_(socket->env(), [this]() { OnIdleTimeout(); }),
- retransmit_(socket->env(), [this]() { OnRetransmitTimeout(); }),
- dcid_(dcid),
- state_(env()->isolate()),
- quic_state_(socket->quic_state()) {
- PushListener(&default_listener_);
- set_connection_id_strategy(RandomConnectionIDStrategy);
- set_preferred_address_strategy(preferred_address_strategy);
- crypto_context_ = std::make_unique<QuicCryptoContext>(
-
- this,
- secure_context,
- side,
- options);
- application_.reset(SelectApplication(this));
-
- wrap->DefineOwnProperty(
- env()->context(),
- env()->state_string(),
- state_.GetArrayBuffer(),
- PropertyAttribute::ReadOnly).Check();
-
- idle_.Unref();
- retransmit_.Unref();
-
- // TODO(@jasnell): memory accounting
- // env_->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize);
-}
-
-QuicSession::~QuicSession() {
- CHECK(!NgCallbackScope::InNgCallbackScope(this));
-
- // The next write should be the final one
- if (qlog_stream_)
- qlog_stream_->End();
-
- QuicSessionListener* listener_ = listener();
- if (listener_ == listener())
- RemoveListener(listener_);
-
- // Stop and free the idle and retransmission timers if they are active.
- // In a clean shutdown, using Close(), these will have already been
- // stopped, but if Close() was not called and we're being destroyed
- // in GC, for instance, we need to make sure they get stopped here.
- idle_.Stop();
- retransmit_.Stop();
-
- DebugStats();
-}
-
-template <typename Fn>
-void QuicSessionStatsTraits::ToString(const QuicSession& ptr, Fn&& add_field) {
-#define V(_n, name, label) \
- add_field(label, ptr.GetStat(&QuicSessionStats::name));
- SESSION_STATS(V)
-#undef V
-}
-
-void QuicSession::PushListener(QuicSessionListener* listener) {
- CHECK_NOT_NULL(listener);
- CHECK(!listener->session_);
-
- listener->previous_listener_ = listener_;
- listener->session_.reset(this);
-
- listener_ = listener;
-}
-
-void QuicSession::RemoveListener(QuicSessionListener* listener) {
- CHECK_NOT_NULL(listener);
-
- QuicSessionListener* previous;
- QuicSessionListener* current;
-
- for (current = listener_, previous = nullptr;
- /* No loop condition because we want a crash if listener is not found */
- ; previous = current, current = current->previous_listener_) {
- CHECK_NOT_NULL(current);
- if (current == listener) {
- if (previous != nullptr)
- previous->previous_listener_ = current->previous_listener_;
- else
- listener_ = listener->previous_listener_;
- break;
- }
- }
-
- listener->session_.reset();
- listener->previous_listener_ = nullptr;
-}
-
-// The diagnostic_name is used in Debug output.
-std::string QuicSession::diagnostic_name() const {
- return std::string("QuicSession ") +
- (is_server() ? "Server" : "Client") +
- " (" + alpn().substr(1) + ", " +
- std::to_string(static_cast<int64_t>(get_async_id())) + ")";
-}
-
-// Locate the QuicStream with the given id or return nullptr
-BaseObjectPtr<QuicStream> QuicSession::FindStream(int64_t id) const {
- auto it = streams_.find(id);
- return it == std::end(streams_) ? BaseObjectPtr<QuicStream>() : it->second;
-}
-
-// Invoked when ngtcp2 receives an acknowledgement for stream data.
-void QuicSession::AckedStreamDataOffset(
- int64_t stream_id,
- uint64_t offset,
- uint64_t datalen) {
- Debug(this,
- "Received acknowledgement for %" PRIu64
- " bytes of stream %" PRId64 " data",
- datalen, stream_id);
-
- application_->AcknowledgeStreamData(
- stream_id,
- offset,
- static_cast<size_t>(datalen));
-}
-
-// Attaches the session to the given QuicSocket. The complexity
-// here is that any CID's associated with the session have to
-// be associated with the new QuicSocket.
-void QuicSession::AddToSocket(QuicSocket* socket) {
- CHECK_NOT_NULL(socket);
- Debug(this, "Adding QuicSession to %s", socket->diagnostic_name());
- socket->AddSession(scid_, BaseObjectPtr<QuicSession>(this));
- switch (crypto_context_->side()) {
- case NGTCP2_CRYPTO_SIDE_SERVER: {
- socket->AssociateCID(dcid_, scid_);
- socket->AssociateCID(pscid_, scid_);
- break;
- }
- case NGTCP2_CRYPTO_SIDE_CLIENT: {
- std::vector<ngtcp2_cid> cids(ngtcp2_conn_get_num_scid(connection()));
- ngtcp2_conn_get_scid(connection(), cids.data());
- for (const ngtcp2_cid& cid : cids) {
- socket->AssociateCID(QuicCID(&cid), scid_);
- }
- break;
- }
- default:
- UNREACHABLE();
- }
-
- std::vector<ngtcp2_cid_token> tokens(
- ngtcp2_conn_get_num_active_dcid(connection()));
- ngtcp2_conn_get_active_dcid(connection(), tokens.data());
- for (const ngtcp2_cid_token& token : tokens) {
- if (token.token_present) {
- socket->AssociateStatelessResetToken(
- StatelessResetToken(token.token),
- BaseObjectPtr<QuicSession>(this));
- }
- }
-}
-
-// Add the given QuicStream to this QuicSession's collection of streams. All
-// streams added must be removed before the QuicSession instance is freed.
-void QuicSession::AddStream(BaseObjectPtr<QuicStream> stream) {
- DCHECK(!is_graceful_closing());
- Debug(this, "Adding stream %" PRId64 " to session", stream->id());
- streams_.emplace(stream->id(), stream);
-
- // Update tracking statistics for the number of streams associated with
- // this session.
- switch (stream->origin()) {
- case QuicStreamOrigin::QUIC_STREAM_CLIENT:
- if (is_server())
- IncrementStat(&QuicSessionStats::streams_in_count);
- else
- IncrementStat(&QuicSessionStats::streams_out_count);
- break;
- case QuicStreamOrigin::QUIC_STREAM_SERVER:
- if (is_server())
- IncrementStat(&QuicSessionStats::streams_out_count);
- else
- IncrementStat(&QuicSessionStats::streams_in_count);
- }
- IncrementStat(&QuicSessionStats::streams_out_count);
- switch (stream->direction()) {
- case QuicStreamDirection::QUIC_STREAM_BIRECTIONAL:
- IncrementStat(&QuicSessionStats::bidi_stream_count);
- break;
- case QuicStreamDirection::QUIC_STREAM_UNIDIRECTIONAL:
- IncrementStat(&QuicSessionStats::uni_stream_count);
- break;
- }
-}
-
-// Creates a new stream object and passes it off to the javascript side.
-// This has to be called from within a handlescope/contextscope.
-BaseObjectPtr<QuicStream> QuicSession::CreateStream(int64_t stream_id) {
- CHECK(!is_destroyed());
- CHECK(!is_graceful_closing());
- CHECK(!is_closing());
-
- BaseObjectPtr<QuicStream> stream = QuicStream::New(this, stream_id);
- CHECK(stream);
- listener()->OnStreamReady(stream);
- return stream;
-}
-
-// Initiate a shutdown of the QuicSession.
-void QuicSession::Close(int close_flags) {
- if (is_destroyed())
- return;
- bool silent = close_flags & QuicSessionListener::SESSION_CLOSE_FLAG_SILENT;
- bool stateless_reset = is_stateless_reset();
-
- // If we're not running within a ngtcp2 callback scope, schedule
- // a CONNECTION_CLOSE to be sent when Close exits. If we are
- // within a ngtcp2 callback scope, sending the CONNECTION_CLOSE
- // will be deferred.
- ConnectionCloseScope close_scope(this, silent);
-
- // Once Close has been called, we cannot re-enter
- if (UNLIKELY(is_closing()))
- return;
-
- set_closing();
- set_silent_closing(silent);
-
- if (stateless_reset && silent)
- close_flags |= QuicSessionListener::SESSION_CLOSE_FLAG_STATELESS_RESET;
-
- QuicError error = last_error();
- Debug(this, "Closing with code %" PRIu64
- " (family: %s, silent: %s, stateless reset: %s)",
- error.code,
- error.family_name(),
- silent ? "Y" : "N",
- stateless_reset ? "Y" : "N");
-
- // Ensure that the QuicSession is not freed at least until after we
- // exit this scope.
- BaseObjectPtr<QuicSession> ptr(this);
-
- // If the QuicSession has been wrapped by a JS object, we have to
- // notify the JavaScript side that the session is being closed.
- // If it hasn't yet been wrapped, we can skip the call and and
- // go straight to destroy.
- if (is_wrapped())
- listener()->OnSessionClose(error, close_flags);
- else
- Destroy();
-}
-
-// Mark the QuicSession instance destroyed. This will either be invoked
-// synchronously within the callstack of the QuicSession::Close() method
-// or not. If it is invoked within QuicSession::Close(), the
-// QuicSession::Close() will handle sending the CONNECTION_CLOSE
-// frame.
-void QuicSession::Destroy() {
- if (is_destroyed())
- return;
-
- Debug(this, "Destroying the QuicSession");
-
- // Mark the session destroyed.
- set_destroyed();
- set_closing(false);
- set_graceful_closing(false);
-
- // TODO(@jasnell): Allow overriding the close code
-
- // If we're not already in a ConnectionCloseScope, schedule
- // sending a CONNECTION_CLOSE when destroy exits. If we are
- // running within an ngtcp2 callback scope, sending the
- // CONNECTION_CLOSE will be deferred.
- ConnectionCloseScope close_scope(this, is_silent_closing());
-
- // All existing streams should have already been destroyed
- CHECK(streams_.empty());
-
- // Stop and free the idle and retransmission timers if they are active.
- idle_.Stop();
- retransmit_.Stop();
-
- // The QuicSession instances are kept alive using
- // BaseObjectPtr. The only persistent BaseObjectPtr
- // is the map in the associated QuicSocket. Removing
- // the QuicSession from the QuicSocket will free
- // that pointer, allowing the QuicSession to be
- // deconstructed once the stack unwinds and any
- // remaining BaseObjectPtr<QuicSession> instances
- // fall out of scope.
- RemoveFromSocket();
-}
-
-// Generates and associates a new connection ID for this QuicSession.
-// ngtcp2 will call this multiple times at the start of a new connection
-// in order to build a pool of available CIDs.
-void QuicSession::GetNewConnectionID(
- ngtcp2_cid* cid,
- uint8_t* token,
- size_t cidlen) {
- CHECK_NOT_NULL(connection_id_strategy_);
- connection_id_strategy_(this, cid, cidlen);
- QuicCID cid_(cid);
- StatelessResetToken(token, socket()->session_reset_secret(), cid_);
- socket()->AssociateCID(cid_, scid_);
-}
-
-void QuicSession::HandleError() {
- if (is_destroyed())
- return;
-
- // If the QuicSession is a server, send a CONNECTION_CLOSE. In either
- // case, the closing timer will be set and the QuicSession will be
- // destroyed.
- if (is_server())
- SendConnectionClose();
- else
- UpdateClosingTimer();
-}
-
-// The the retransmit libuv timer fires, it will call OnRetransmitTimeout,
-// which determines whether or not we need to retransmit data to
-// to packet loss or ack delay.
-void QuicSession::OnRetransmitTimeout() {
- if (is_destroyed())
- return;
- uint64_t now = uv_hrtime();
-
- if (ngtcp2_conn_loss_detection_expiry(connection()) <= now) {
- Debug(this, "Retransmitting due to loss detection");
- IncrementStat(&QuicSessionStats::loss_retransmit_count);
- }
-
- if (ngtcp2_conn_ack_delay_expiry(connection()) <= now) {
- Debug(this, "Retransmitting due to ack delay");
- IncrementStat(&QuicSessionStats::ack_delay_retransmit_count);
- }
-
- int rv = ngtcp2_conn_handle_expiry(connection(), now);
- if (rv != 0) {
- Debug(this, "Error handling retransmit timeout: %s", ngtcp2_strerror(rv));
- set_last_error(QUIC_ERROR_SESSION, rv);
- HandleError();
- }
-
- SendPendingData();
-}
-
-bool QuicSession::OpenBidirectionalStream(int64_t* stream_id) {
- DCHECK(!is_destroyed());
- DCHECK(!is_closing());
- DCHECK(!is_graceful_closing());
- return ngtcp2_conn_open_bidi_stream(connection(), stream_id, nullptr) == 0;
-}
-
-bool QuicSession::OpenUnidirectionalStream(int64_t* stream_id) {
- DCHECK(!is_destroyed());
- DCHECK(!is_closing());
- DCHECK(!is_graceful_closing());
- return ngtcp2_conn_open_uni_stream(connection(), stream_id, nullptr) == 0;
-}
-
-// When ngtcp2 receives a successful response to a PATH_CHALLENGE,
-// it will trigger the OnPathValidation callback which will, in turn
-// invoke this. There's really nothing to do here but update stats and
-// and optionally notify the javascript side if there is a handler registered.
-// Notifying the JavaScript side is purely informational.
-void QuicSession::PathValidation(
- const ngtcp2_path* path,
- ngtcp2_path_validation_result res) {
- if (res == NGTCP2_PATH_VALIDATION_RESULT_SUCCESS) {
- IncrementStat(&QuicSessionStats::path_validation_success_count);
- } else {
- IncrementStat(&QuicSessionStats::path_validation_failure_count);
- }
-
- // Only emit the callback if there is a handler for the pathValidation
- // event on the JavaScript QuicSession object.
- if (UNLIKELY(state_->path_validated_enabled == 1)) {
- listener_->OnPathValidation(
- res,
- reinterpret_cast<const sockaddr*>(path->local.addr),
- reinterpret_cast<const sockaddr*>(path->remote.addr));
- }
-}
-
-// Calling Ping will trigger the ngtcp2_conn to serialize any
-// packets it currently has pending along with a probe frame
-// that should keep the connection alive. This is a fire and
-// forget and any errors that may occur will be ignored. The
-// idle_timeout and retransmit timers will be updated. If Ping
-// is called while processing an ngtcp2 callback, or if the
-// closing or draining period has started, this is a non-op.
-void QuicSession::Ping() {
- if (NgCallbackScope::InNgCallbackScope(this) ||
- is_destroyed() ||
- is_closing() ||
- is_in_closing_period() ||
- is_in_draining_period()) {
- return;
- }
- // TODO(@jasnell): We might want to revisit whether to handle
- // errors right here. For now, we're ignoring them with the
- // intent of capturing them elsewhere.
- WritePackets("ping");
- UpdateIdleTimer();
- ScheduleRetransmit();
-}
-
-// When the QuicSocket receives a QUIC packet, it is forwarded on to here
-// for processing.
-bool QuicSession::Receive(
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) {
-
- CHECK(!is_destroyed());
-
- Debug(this, "Receiving QUIC packet");
- IncrementStat(&QuicSessionStats::bytes_received, nread);
-
- if (is_in_closing_period() && is_server()) {
- Debug(this, "Packet received while in closing period");
- IncrementConnectionCloseAttempts();
- // For server QuicSession instances, we serialize the connection close
- // packet once but may sent it multiple times. If the client keeps
- // transmitting, then the connection close may have gotten lost.
- // We don't want to send the connection close in response to
- // every received packet, however, so we use an exponential
- // backoff, increasing the ratio of packets received to connection
- // close frame sent with every one we send.
- if (UNLIKELY(ShouldAttemptConnectionClose() &&
- !SendConnectionClose())) {
- Debug(this, "Failure sending another connection close");
- return false;
- }
- }
-
- {
- // These are within a scope to ensure that the InternalCallbackScope
- // and HandleScope are both exited before continuing on with the
- // function. This allows any nextTicks and queued tasks to be processed
- // before we continue.
- auto update_stats = OnScopeLeave([&](){
- UpdateDataStats();
- });
- HandleScope handle_scope(env()->isolate());
- InternalCallbackScope callback_scope(this);
- remote_address_ = remote_addr;
- QuicPath path(local_addr, remote_address_);
- if (!ReceivePacket(&path, data, nread)) {
- HandleError();
- return false;
- }
- }
-
- // Only send pending data if we haven't entered draining mode.
- // We enter the draining period when a CONNECTION_CLOSE has been
- // received from the remote peer.
- if (is_in_draining_period()) {
- Debug(this, "In draining period after processing packet");
- // If processing the packet puts us into draining period, there's
- // absolutely nothing left for us to do except silently close
- // and destroy this QuicSession, which we do by updating the
- // closing timer.
- GetConnectionCloseInfo();
- UpdateClosingTimer();
- return true;
- }
-
- if (!is_destroyed())
- UpdateIdleTimer();
- SendPendingData();
- Debug(this, "Successfully processed received packet");
- return true;
-}
-
-// Performs intake processing on a received QUIC packet. The received
-// data is passed on to ngtcp2 for parsing and processing. ngtcp2 will,
-// in turn, invoke a series of callbacks to handle the received packet.
-bool QuicSession::ReceivePacket(
- ngtcp2_path* path,
- const uint8_t* data,
- ssize_t nread) {
- CHECK(!is_destroyed());
-
- uint64_t now = uv_hrtime();
- SetStat(&QuicSessionStats::received_at, now);
- int err = ngtcp2_conn_read_pkt(connection(), path, data, nread, now);
- if (err < 0) {
- switch (err) {
- case NGTCP2_ERR_CALLBACK_FAILURE:
- case NGTCP2_ERR_DRAINING:
- case NGTCP2_ERR_RECV_VERSION_NEGOTIATION:
- break;
- case NGTCP2_ERR_RETRY:
- // This should only ever happen on the server
- CHECK(is_server());
- socket()->SendRetry(scid_, dcid_, local_address_, remote_address_);
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- break;
- case NGTCP2_ERR_DROP_CONN:
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- break;
- default:
- set_last_error(QUIC_ERROR_SESSION, err);
- return false;
- }
- }
-
- // If the QuicSession has been destroyed but it is not
- // in the closing period, a CONNECTION_CLOSE has not yet
- // been sent to the peer. Let's attempt to send one. This
- // will have the effect of setting the idle timer to the
- // closing/draining period, after which the QuicSession
- // will be destroyed.
- if (is_destroyed() && !is_in_closing_period()) {
- Debug(this, "Session was destroyed while processing the packet");
- return SendConnectionClose();
- }
-
- return true;
-}
-
-// Called by ngtcp2 when a chunk of stream data has been received. If
-// the stream does not yet exist, it is created, then the data is
-// forwarded on.
-bool QuicSession::ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) {
- auto leave = OnScopeLeave([&]() {
- // Unconditionally extend the flow control window for the entire
- // session but not for the individual Stream.
- ExtendOffset(datalen);
- });
-
- return application_->ReceiveStreamData(
- flags,
- stream_id,
- data,
- datalen,
- offset);
-}
-
-// Removes the QuicSession from the current socket. This is
-// done with when the session is being destroyed or being
-// migrated to another QuicSocket. It is important to keep in mind
-// that the QuicSocket uses a BaseObjectPtr for the QuicSession.
-// If the session is removed and there are no other references held,
-// the session object will be destroyed automatically.
-void QuicSession::RemoveFromSocket() {
- CHECK(socket_);
- Debug(this, "Removing QuicSession from %s", socket_->diagnostic_name());
- if (is_server()) {
- socket_->DisassociateCID(dcid_);
- socket_->DisassociateCID(pscid_);
- }
-
- std::vector<ngtcp2_cid> cids(ngtcp2_conn_get_num_scid(connection()));
- std::vector<ngtcp2_cid_token> tokens(
- ngtcp2_conn_get_num_active_dcid(connection()));
- ngtcp2_conn_get_scid(connection(), cids.data());
- ngtcp2_conn_get_active_dcid(connection(), tokens.data());
-
- for (const ngtcp2_cid& cid : cids)
- socket_->DisassociateCID(QuicCID(&cid));
-
- for (const ngtcp2_cid_token& token : tokens) {
- if (token.token_present) {
- socket_->DisassociateStatelessResetToken(
- StatelessResetToken(token.token));
- }
- }
-
- Debug(this, "Removed from the QuicSocket");
- BaseObjectPtr<QuicSocket> socket = std::move(socket_);
- socket->RemoveSession(scid_, remote_address_);
-}
-
-// Removes the given stream from the QuicSession. All streams must
-// be removed before the QuicSession is destroyed.
-void QuicSession::RemoveStream(int64_t stream_id) {
- Debug(this, "Removing stream %" PRId64, stream_id);
-
- // ngtcp2 does not extend the max streams count automatically
- // except in very specific conditions, none of which apply
- // once we've gotten this far. We need to manually extend when
- // a remote peer initiated stream is removed.
- if (!is_in_draining_period() &&
- !is_in_closing_period() &&
- !is_silent_closing() &&
- !ngtcp2_conn_is_local_stream(connection_.get(), stream_id)) {
- if (ngtcp2_is_bidi_stream(stream_id))
- ngtcp2_conn_extend_max_streams_bidi(connection_.get(), 1);
- else
- ngtcp2_conn_extend_max_streams_uni(connection_.get(), 1);
- }
-
- // This will have the side effect of destroying the QuicStream
- // instance.
- streams_.erase(stream_id);
-}
-
-// The retransmit timer allows us to trigger retransmission
-// of packets in case they are considered lost. The exact amount
-// of time is determined internally by ngtcp2 according to the
-// guidelines established by the QUIC spec but we use a libuv
-// timer to actually monitor.
-void QuicSession::ScheduleRetransmit() {
- uint64_t now = uv_hrtime();
- uint64_t expiry = ngtcp2_conn_get_expiry(connection());
- // now and expiry are in nanoseconds, interval is milliseconds
- uint64_t interval = (expiry < now) ? 1 : (expiry - now) / 1000000UL;
- // If interval ends up being 0, the repeating timer won't be
- // scheduled, so set it to 1 instead.
- if (interval == 0) interval = 1;
- Debug(this, "Scheduling the retransmit timer for %" PRIu64, interval);
- UpdateRetransmitTimer(interval);
-}
-
-bool QuicSession::InitApplication() {
- Debug(this, "Initializing application handler for ALPN %s",
- alpn().c_str() + 1);
- return application_->Initialize();
-}
-
-// Captures the error code and family information from a received
-// connection close frame.
-void QuicSession::GetConnectionCloseInfo() {
- ngtcp2_connection_close_error_code close_code;
- ngtcp2_conn_get_connection_close_error_code(connection(), &close_code);
- set_last_error(QuicError(close_code));
-}
-
-// The HandshakeCompleted function is called by ngtcp2 once it
-// determines that the TLS Handshake is done. The only thing we
-// need to do at this point is let the javascript side know.
-void QuicSession::HandshakeCompleted() {
- RemoteTransportParamsDebug transport_params(this);
- Debug(this, "Handshake is completed. %s", transport_params);
- RecordTimestamp(&QuicSessionStats::handshake_completed_at);
- if (is_server()) HandshakeConfirmed();
- listener()->OnHandshakeCompleted();
-}
-
-void QuicSession::HandshakeConfirmed() {
- Debug(this, "Handshake is confirmed");
- RecordTimestamp(&QuicSessionStats::handshake_confirmed_at);
- state_->handshake_confirmed = 1;
-}
-
-// Every QUIC session has a remote address and local address.
-// Those endpoints can change through the lifetime of a connection,
-// so whenever a packet is successfully processed, or when a
-// response is to be sent, we have to keep track of the path
-// and update as we go.
-void QuicSession::UpdateEndpoint(const ngtcp2_path& path) {
- remote_address_.Update(path.remote.addr, path.remote.addrlen);
- local_address_.Update(path.local.addr, path.local.addrlen);
-
- // If the updated remote address is IPv6, set the flow label
- if (remote_address_.family() == AF_INET6) {
- // TODO(@jasnell): Currently, this reuses the session reset secret.
- // That may or may not be a good idea, we need to verify and may
- // need to have a distinct secret for flow labels.
- uint32_t flow_label =
- GenerateFlowLabel(
- local_address_,
- remote_address_,
- scid_,
- socket()->session_reset_secret(),
- NGTCP2_STATELESS_RESET_TOKENLEN);
- remote_address_.set_flow_label(flow_label);
- }
-}
-
-// Called by the OnVersionNegotiation callback when a version
-// negotiation frame has been received by the client. The sv
-// parameter is an array of versions supported by the remote peer.
-void QuicSession::VersionNegotiation(const uint32_t* sv, size_t nsv) {
- CHECK(!is_server());
- listener()->OnVersionNegotiation(NGTCP2_PROTO_VER, sv, nsv);
-}
-
-// The retransmit timer allows us to trigger retransmission
-// of packets in case they are considered lost. The exact amount
-// of time is determined internally by ngtcp2 according to the
-// guidelines established by the QUIC spec but we use a libuv
-// timer to actually monitor. Here we take the calculated timeout
-// and extend out the libuv timer.
-void QuicSession::UpdateRetransmitTimer(uint64_t timeout) {
- retransmit_.Update(timeout, timeout);
-}
-
-void QuicSession::IncrementConnectionCloseAttempts() {
- if (connection_close_attempts_ < kMaxSizeT)
- connection_close_attempts_++;
-}
-
-bool QuicSession::ShouldAttemptConnectionClose() {
- if (connection_close_attempts_ == connection_close_limit_) {
- if (connection_close_limit_ * 2 <= kMaxSizeT)
- connection_close_limit_ *= 2;
- else
- connection_close_limit_ = kMaxSizeT;
- return true;
- }
- return false;
-}
-
-// Transmits either a protocol or application connection
-// close to the peer. The choice of which is send is
-// based on the current value of last_error_.
-bool QuicSession::SendConnectionClose() {
- CHECK(!NgCallbackScope::InNgCallbackScope(this));
-
- // Do not send any frames at all if we're in the draining period
- // or in the middle of a silent close
- if (is_in_draining_period() || is_silent_closing())
- return true;
-
- // The specific handling of connection close varies for client
- // and server QuicSession instances. For servers, we will
- // serialize the connection close once but may end up transmitting
- // it multiple times; whereas for clients, we will serialize it
- // once and send once only.
- QuicError error = last_error();
- Debug(this, "Sending connection close with code: %" PRIu64 " (family: %s)",
- error.code, error.family_name());
-
- UpdateClosingTimer();
-
- // If initial keys have not yet been installed, use the alternative
- // ImmediateConnectionClose to send a stateless connection close to
- // the peer.
- if (crypto_context()->write_crypto_level() ==
- NGTCP2_CRYPTO_LEVEL_INITIAL) {
- socket()->ImmediateConnectionClose(
- dcid(),
- scid_,
- local_address_,
- remote_address_,
- error.code);
- return true;
- }
-
- switch (crypto_context_->side()) {
- case NGTCP2_CRYPTO_SIDE_SERVER: {
- if (!is_in_closing_period() && !StartClosingPeriod()) {
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- return false;
- }
- CHECK_GT(conn_closebuf_->length(), 0);
- return SendPacket(QuicPacket::Copy(conn_closebuf_));
- }
- case NGTCP2_CRYPTO_SIDE_CLIENT: {
- auto packet = QuicPacket::Create("client connection close");
-
- ssize_t nwrite =
- SelectCloseFn(error.family)(
- connection(),
- nullptr,
- packet->data(),
- max_pktlen_,
- error.code,
- uv_hrtime());
- if (UNLIKELY(nwrite < 0)) {
- Debug(this, "Error writing connection close: %d", nwrite);
- set_last_error(QUIC_ERROR_SESSION, static_cast<int>(nwrite));
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- return false;
- }
- packet->set_length(nwrite);
- return SendPacket(std::move(packet));
- }
- default:
- UNREACHABLE();
- }
-}
-
-void QuicSession::IgnorePreferredAddressStrategy(
- QuicSession* session,
- const PreferredAddress& preferred_address) {
- Debug(session, "Ignoring server preferred address");
-}
-
-void QuicSession::UsePreferredAddressStrategy(
- QuicSession* session,
- const PreferredAddress& preferred_address) {
- int family = session->socket()->local_address().family();
- if (preferred_address.Use(family)) {
- Debug(session, "Using server preferred address");
- // Emit only if the QuicSession has a usePreferredAddress handler
- // on the JavaScript side.
- if (UNLIKELY(session->state_->use_preferred_address_enabled == 1)) {
- session->listener()->OnUsePreferredAddress(family, preferred_address);
- }
- } else {
- // If Use returns false, the advertised preferred address does not
- // match the current local preferred endpoint IP version.
- Debug(session,
- "Not using server preferred address due to IP version mismatch");
- }
-}
-
-// Passes a serialized packet to the associated QuicSocket.
-bool QuicSession::SendPacket(std::unique_ptr<QuicPacket> packet) {
- CHECK(!is_in_draining_period());
-
- // There's nothing to send.
- if (packet->length() == 0)
- return true;
-
- IncrementStat(&QuicSessionStats::bytes_sent, packet->length());
- RecordTimestamp(&QuicSessionStats::sent_at);
-// ScheduleRetransmit();
-
- Debug(this, "Sending %" PRIu64 " bytes to %s from %s",
- packet->length(),
- remote_address_,
- local_address_);
-
- int err = socket()->SendPacket(
- local_address_,
- remote_address_,
- std::move(packet),
- BaseObjectPtr<QuicSession>(this));
-
- if (err != 0) {
- set_last_error(QUIC_ERROR_SESSION, err);
- return false;
- }
-
- return true;
-}
-
-// Sends any pending handshake or session packet data.
-void QuicSession::SendPendingData() {
- if (is_unable_to_send_packets())
- return;
-
- Debug(this, "Sending pending data");
- if (!application_->SendPendingData()) {
- Debug(this, "Error sending QUIC application data");
- HandleError();
- }
- ScheduleRetransmit();
-}
-
-// When completing the TLS handshake, the TLS session information
-// is provided to the QuicSession so that the session ticket and
-// the remote transport parameters can be captured to support 0RTT
-// session resumption.
-int QuicSession::set_session(SSL_SESSION* session) {
- CHECK(!is_server());
- CHECK(!is_destroyed());
- int size = i2d_SSL_SESSION(session, nullptr);
- if (size > SecureContext::kMaxSessionSize)
- return 0;
- listener_->OnSessionTicket(size, session);
- return 0;
-}
-
-// A client QuicSession can be migrated to a different QuicSocket instance.
-bool QuicSession::set_socket(QuicSocket* socket, bool nat_rebinding) {
- CHECK(!is_server());
- CHECK(!is_destroyed());
-
- if (is_graceful_closing())
- return false;
-
- if (socket == nullptr || socket == socket_.get())
- return true;
-
- Debug(this, "Migrating to %s", socket->diagnostic_name());
-
- // Ensure that we maintain a reference to keep this from being
- // destroyed while we are starting the migration.
- BaseObjectPtr<QuicSession> ptr(this);
-
- // Step 1: Remove the session from the current socket
- RemoveFromSocket();
-
- // Step 2: Add this Session to the given Socket
- AddToSocket(socket);
-
- // Step 3: Update the internal references and make sure
- // we are listening.
- socket_.reset(socket);
- socket->ReceiveStart();
-
- // Step 4: Update ngtcp2
- auto local_address = socket->local_address();
-
- // The nat_rebinding option here should rarely, if ever
- // be used in a real application. It is intended to serve
- // as a way of simulating a silent local address change,
- // such as when the NAT binding changes. Currently, Node.js
- // does not really have an effective way of detecting that.
- // Manual user code intervention to handle the migration
- // to the new QuicSocket is required, which should always
- // trigger path validation using the ngtcp2_conn_initiate_migration.
- if (LIKELY(!nat_rebinding)) {
- SendSessionScope send(this);
- QuicPath path(local_address, remote_address_);
- return ngtcp2_conn_initiate_migration(
- connection(),
- &path,
- uv_hrtime()) == 0;
- } else {
- ngtcp2_addr addr;
- ngtcp2_conn_set_local_addr(
- connection(),
- ngtcp2_addr_init(
- &addr,
- local_address.data(),
- local_address.length(),
- nullptr));
- }
-
- return true;
-}
-
-void QuicSession::ResumeStream(int64_t stream_id) {
- application()->ResumeStream(stream_id);
-}
-
-// Begin connection close by serializing the CONNECTION_CLOSE packet.
-// There are two variants: one to serialize an application close, the
-// other to serialize a protocol close. The frames are generally
-// identical with the exception of a bit in the header. On server
-// QuicSessions, we serialize the frame once and may retransmit it
-// multiple times. On client QuicSession instances, we only ever
-// serialize the connection close once.
-bool QuicSession::StartClosingPeriod() {
- if (is_destroyed())
- return false;
- if (is_in_closing_period())
- return true;
-
- QuicError error = last_error();
- Debug(this, "Closing period has started. Error %d", error.code);
-
- // Once the CONNECTION_CLOSE packet is written,
- // is_in_closing_period will return true.
- conn_closebuf_ = QuicPacket::Create("server connection close");
- ssize_t nwrite =
- SelectCloseFn(error.family)(
- connection(),
- nullptr,
- conn_closebuf_->data(),
- max_pktlen_,
- error.code,
- uv_hrtime());
- if (nwrite < 0) {
- set_last_error(QUIC_ERROR_SESSION, static_cast<int>(nwrite));
- return false;
- }
- conn_closebuf_->set_length(nwrite);
- return true;
-}
-
-// Called by ngtcp2 when a stream has been closed. If the stream does
-// not exist, the close is ignored.
-void QuicSession::StreamClose(int64_t stream_id, uint64_t app_error_code) {
- Debug(this, "Closing stream %" PRId64 " with code %" PRIu64,
- stream_id,
- app_error_code);
-
- application_->StreamClose(stream_id, app_error_code);
-}
-
-// Called when the QuicSession has received a RESET_STREAM frame from the
-// peer, indicating that it will no longer send additional frames for the
-// stream. If the stream is not yet known, reset is ignored. If the stream
-// has already received a STREAM frame with fin set, the stream reset is
-// ignored (the QUIC spec permits implementations to handle this situation
-// however they want.) If the stream has not yet received a STREAM frame
-// with the fin set, then the RESET_STREAM causes the readable side of the
-// stream to be abruptly closed and any additional stream frames that may
-// be received will be discarded if their offset is greater than final_size.
-// On the JavaScript side, receiving a C is undistinguishable from
-// a normal end-of-stream. No additional data events will be emitted, the
-// end event will be emitted, and the readable side of the duplex will be
-// closed.
-//
-// If the stream is still writable, no additional action is taken. If,
-// however, the writable side of the stream has been closed (or was never
-// open in the first place as in the case of peer-initiated unidirectional
-// streams), the reset will cause the stream to be immediately destroyed.
-void QuicSession::StreamReset(
- int64_t stream_id,
- uint64_t final_size,
- uint64_t app_error_code) {
- Debug(this,
- "Reset stream %" PRId64 " with code %" PRIu64
- " and final size %" PRIu64,
- stream_id,
- app_error_code,
- final_size);
-
- BaseObjectPtr<QuicStream> stream = FindStream(stream_id);
-
- if (stream) {
- stream->set_final_size(final_size);
- application_->StreamReset(stream_id, app_error_code);
- }
-}
-
-void QuicSession::UpdateConnectionID(
- int type,
- const QuicCID& cid,
- const StatelessResetToken& token) {
- switch (type) {
- case NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE:
- socket_->AssociateStatelessResetToken(
- token,
- BaseObjectPtr<QuicSession>(this));
- break;
- case NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE:
- socket_->DisassociateStatelessResetToken(token);
- break;
- }
-}
-
-// Updates the idle timer timeout. If the idle timer fires, the connection
-// will be silently closed. It is important to update this as activity
-// occurs to keep the idle timer from firing.
-void QuicSession::UpdateIdleTimer() {
- if (is_closing_timer_enabled())
- return;
- uint64_t now = uv_hrtime();
- uint64_t expiry = ngtcp2_conn_get_idle_expiry(connection());
- // nano to millis
- uint64_t timeout = expiry > now ? (expiry - now) / 1000000ULL : 1;
- if (timeout == 0) timeout = 1;
- Debug(this, "Updating idle timeout to %" PRIu64, timeout);
- idle_.Update(timeout, timeout);
-}
-
-void QuicSession::UpdateClosingTimer() {
- set_closing_timer_enabled(true);
- uint64_t timeout =
- is_server() ? (ngtcp2_conn_get_pto(connection()) / 1000000ULL) * 3 : 0;
- Debug(this, "Setting closing timeout to %" PRIu64, timeout);
- retransmit_.Stop();
- idle_.Update(timeout, 0);
- idle_.Ref();
-}
-
-// Write any packets current pending for the ngtcp2 connection based on
-// the current state of the QuicSession. If the QuicSession is in the
-// closing period, only CONNECTION_CLOSE packets may be written. If the
-// QuicSession is in the draining period, no packets may be written.
-//
-// Packets are flushed to the underlying QuicSocket uv_udp_t as soon
-// as they are written. The WritePackets method may cause zero or more
-// packets to be serialized.
-//
-// If there are any acks or retransmissions pending, those will be
-// serialized at this point as well. However, WritePackets does not
-// serialize stream data that is being sent initially.
-bool QuicSession::WritePackets(const char* diagnostic_label) {
- CHECK(!NgCallbackScope::InNgCallbackScope(this));
-
- // During either the draining or closing period,
- // we are not permitted to send any additional packets.
- if (is_in_draining_period() || is_in_closing_period())
- return true;
-
- // Otherwise, serialize and send pending frames
- QuicPathStorage path;
- for (;;) {
- auto packet = QuicPacket::Create(diagnostic_label, max_pktlen_);
- // ngtcp2_conn_write_pkt will fill the created QuicPacket up
- // as much as possible, and then should be called repeatedly
- // until it returns 0 or fatally errors. On each call, it
- // will return the number of bytes encoded into the packet.
- ssize_t nwrite =
- ngtcp2_conn_write_pkt(
- connection(),
- &path.path,
- packet->data(),
- max_pktlen_,
- uv_hrtime());
-
- if (nwrite <= 0) {
- switch (nwrite) {
- case 0:
- // There was nothing to write.
- return true;
- case NGTCP2_ERR_PKT_NUM_EXHAUSTED:
- // There is a finite number of packets that can be sent
- // per connection. Once those are exhausted, there's
- // absolutely nothing we can do except immediately
- // and silently tear down the QuicSession. This has
- // to be silent because we can't even send a
- // CONNECTION_CLOSE since even those require a
- // packet number.
- Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
- return false;
- default:
- set_last_error(QUIC_ERROR_SESSION, static_cast<int>(nwrite));
- return false;
- }
- }
-
- packet->set_length(nwrite);
- UpdateEndpoint(path.path);
- UpdateDataStats();
-
- if (!SendPacket(std::move(packet)))
- return false;
- }
-}
-
-void QuicSession::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("crypto_context", crypto_context_.get());
- tracker->TrackField("alpn", alpn_);
- tracker->TrackField("hostname", hostname_);
- tracker->TrackField("idle", idle_);
- tracker->TrackField("retransmit", retransmit_);
- tracker->TrackField("streams", streams_);
- tracker->TrackFieldWithSize("current_ngtcp2_memory", current_ngtcp2_memory_);
- tracker->TrackField("conn_closebuf", conn_closebuf_);
- tracker->TrackField("application", application_);
- tracker->TrackField("quic_state", quic_state_);
- tracker->TrackField("qlog_stream", qlog_stream_);
- StatsBase::StatsMemoryInfo(tracker);
-}
-
-void QuicSession::ExtendMaxStreamsBidi(uint64_t max_streams) {
- state_->max_streams_bidi = max_streams;
-}
-
-void QuicSession::ExtendMaxStreamsUni(uint64_t max_streams) {
- state_->max_streams_uni = max_streams;
-}
-
-void QuicSession::ExtendMaxStreamsRemoteUni(uint64_t max_streams) {
- Debug(this, "Extend remote max unidirectional streams: %" PRIu64,
- max_streams);
- application_->ExtendMaxStreamsRemoteUni(max_streams);
-}
-
-void QuicSession::ExtendMaxStreamsRemoteBidi(uint64_t max_streams) {
- Debug(this, "Extend remote max bidirectional streams: %" PRIu64,
- max_streams);
- application_->ExtendMaxStreamsRemoteBidi(max_streams);
-}
-
-void QuicSession::ExtendMaxStreamData(int64_t stream_id, uint64_t max_data) {
- Debug(this,
- "Extending max stream %" PRId64 " data to %" PRIu64,
- stream_id, max_data);
- application_->ExtendMaxStreamData(stream_id, max_data);
-}
-
-// Static function to create a new server QuicSession instance
-BaseObjectPtr<QuicSession> QuicSession::CreateServer(
- QuicSocket* socket,
- const QuicSessionConfig& config,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- const std::string& alpn,
- uint32_t options,
- QlogMode qlog) {
- Local<Object> obj;
- if (!socket->env()
- ->quicserversession_instance_template()
- ->NewInstance(socket->env()->context()).ToLocal(&obj)) {
- return {};
- }
- BaseObjectPtr<QuicSession> session =
- MakeDetachedBaseObject<QuicSession>(
- socket,
- config,
- obj,
- local_addr,
- remote_addr,
- dcid,
- scid,
- ocid,
- version,
- alpn,
- options,
- qlog);
-
- session->AddToSocket(socket);
- return session;
-}
-
-// Initializes a newly created server QuicSession.
-void QuicSession::InitServer(
- QuicSessionConfig config,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- QlogMode qlog) {
-
- CHECK_NULL(connection_);
-
- ExtendMaxStreamsBidi(DEFAULT_MAX_STREAMS_BIDI);
- ExtendMaxStreamsUni(DEFAULT_MAX_STREAMS_UNI);
-
- local_address_ = local_addr;
- remote_address_ = remote_addr;
- max_pktlen_ = GetMaxPktLen(remote_addr);
-
- config.set_original_connection_id(ocid, scid);
-
- connection_id_strategy_(this, scid_.cid(), kScidLen);
-
- config.GenerateStatelessResetToken(this, scid_);
- config.GeneratePreferredAddressToken(connection_id_strategy_, this, &pscid_);
-
- QuicPath path(local_addr, remote_address_);
-
- // NOLINTNEXTLINE(readability/pointer_notation)
- if (qlog == QlogMode::kEnabled) config.set_qlog({ *ocid, OnQlogWrite });
-
- ngtcp2_conn* conn;
- CHECK_EQ(
- ngtcp2_conn_server_new(
- &conn,
- dcid.cid(),
- scid_.cid(),
- &path,
- version,
- &callbacks[crypto_context_->side()],
- &config,
- &alloc_info_,
- static_cast<QuicSession*>(this)), 0);
-
- connection_.reset(conn);
-
- crypto_context_->Initialize();
- UpdateDataStats();
- UpdateIdleTimer();
-}
-
-namespace {
-void QuicSessionOnClientHelloDone(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- Local<FunctionTemplate> cons = env->secure_context_constructor_template();
- SecureContext* context = nullptr;
- if (args[0]->IsObject() && cons->HasInstance(args[0]))
- context = Unwrap<SecureContext>(args[0].As<Object>());
- session->crypto_context()->OnClientHelloDone(
- BaseObjectPtr<SecureContext>(context));
-}
-
-void QuicSessionOnCertDone(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- session->crypto_context()->OnOCSPDone(args[0]);
-}
-} // namespace
-
-
-// Data stats are used to allow user code to keep track of important
-// statistics such as amount of data in flight through the lifetime
-// of a connection.
-void QuicSession::UpdateDataStats() {
- if (is_destroyed())
- return;
- state_->max_data_left = ngtcp2_conn_get_max_data_left(connection());
-
- ngtcp2_conn_stat stat;
- ngtcp2_conn_get_conn_stat(connection(), &stat);
-
- SetStat(&QuicSessionStats::latest_rtt, stat.latest_rtt);
- SetStat(&QuicSessionStats::min_rtt, stat.min_rtt);
- SetStat(&QuicSessionStats::smoothed_rtt, stat.smoothed_rtt);
- SetStat(&QuicSessionStats::receive_rate, stat.recv_rate_sec);
- SetStat(&QuicSessionStats::send_rate, stat.delivery_rate_sec);
- SetStat(&QuicSessionStats::cwnd, stat.cwnd);
-
- state_->bytes_in_flight = stat.bytes_in_flight;
- // The max_bytes_in_flight is a highwater mark that can be used
- // in performance analysis operations.
- if (stat.bytes_in_flight > GetStat(&QuicSessionStats::max_bytes_in_flight))
- SetStat(&QuicSessionStats::max_bytes_in_flight, stat.bytes_in_flight);
-}
-
-// Static method for creating a new client QuicSession instance.
-BaseObjectPtr<QuicSession> QuicSession::CreateClient(
- QuicSocket* socket,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- BaseObjectPtr<SecureContext> secure_context,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- Local<Value> dcid,
- PreferredAddressStrategy preferred_address_strategy,
- const std::string& alpn,
- const std::string& hostname,
- uint32_t options,
- QlogMode qlog) {
- Local<Object> obj;
- if (!socket->env()
- ->quicclientsession_instance_template()
- ->NewInstance(socket->env()->context()).ToLocal(&obj)) {
- return {};
- }
-
- BaseObjectPtr<QuicSession> session =
- MakeDetachedBaseObject<QuicSession>(
- socket,
- obj,
- local_addr,
- remote_addr,
- secure_context,
- early_transport_params,
- std::move(early_session_ticket),
- dcid,
- preferred_address_strategy,
- alpn,
- hostname,
- options,
- qlog);
-
- session->AddToSocket(socket);
-
- return session;
-}
-
-// Initialize a newly created client QuicSession.
-// The early_transport_params and session_ticket are optional to
-// perform a 0RTT resumption of a prior session.
-// The dcid_value parameter is optional to allow user code the
-// ability to provide an explicit dcid (this should be rare)
-void QuicSession::InitClient(
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- Local<Value> dcid_value,
- QlogMode qlog) {
- CHECK_NULL(connection_);
-
- local_address_ = local_addr;
- remote_address_ = remote_addr;
- Debug(this, "Initializing connection from %s to %s",
- local_address_,
- remote_address_);
-
- // The maximum packet length is determined largely
- // by the IP version (IPv4 vs IPv6). Packet sizes
- // should be limited to the maximum MTU necessary to
- // prevent IP fragmentation.
- max_pktlen_ = GetMaxPktLen(remote_address_);
-
- QuicSessionConfig config(quic_state());
- ExtendMaxStreamsBidi(DEFAULT_MAX_STREAMS_BIDI);
- ExtendMaxStreamsUni(DEFAULT_MAX_STREAMS_UNI);
-
- connection_id_strategy_(this, scid_.cid(), NGTCP2_MAX_CIDLEN);
-
- ngtcp2_cid dcid;
- if (dcid_value->IsArrayBufferView()) {
- ArrayBufferViewContents<uint8_t> sbuf(
- dcid_value.As<ArrayBufferView>());
- CHECK_LE(sbuf.length(), NGTCP2_MAX_CIDLEN);
- CHECK_GE(sbuf.length(), NGTCP2_MIN_CIDLEN);
- memcpy(dcid.data, sbuf.data(), sbuf.length());
- dcid.datalen = sbuf.length();
- } else {
- connection_id_strategy_(this, &dcid, NGTCP2_MAX_CIDLEN);
- }
-
- QuicPath path(local_address_, remote_address_);
-
- if (qlog == QlogMode::kEnabled) config.set_qlog({ dcid, OnQlogWrite });
-
- ngtcp2_conn* conn;
- CHECK_EQ(
- ngtcp2_conn_client_new(
- &conn,
- &dcid,
- scid_.cid(),
- &path,
- NGTCP2_PROTO_VER,
- &callbacks[crypto_context_->side()],
- &config,
- &alloc_info_,
- static_cast<QuicSession*>(this)), 0);
-
-
- connection_.reset(conn);
-
- crypto_context_->Initialize();
-
- if (early_transport_params != nullptr)
- ngtcp2_conn_set_early_remote_transport_params(conn, early_transport_params);
- crypto_context_->set_session(std::move(early_session_ticket));
-
- UpdateIdleTimer();
- UpdateDataStats();
-}
-
-// Static ngtcp2 callbacks are registered when ngtcp2 when a new ngtcp2_conn is
-// created. These are static functions that, for the most part, simply defer to
-// a QuicSession instance that is passed through as user_data.
-
-// Called by ngtcp2 for both client and server connections when
-// TLS handshake data has been received and needs to be processed.
-// This will be called multiple times during the TLS handshake
-// process and may be called during key updates.
-int QuicSession::OnReceiveCryptoData(
- ngtcp2_conn* conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- int ret = session->crypto_context()->Receive(
- crypto_level,
- offset,
- data,
- datalen);
- return ret == 0 ? 0 : NGTCP2_ERR_CALLBACK_FAILURE;
-}
-
-// Called by ngtcp2 for both client and server connections
-// when a request to extend the maximum number of bidirectional
-// streams has been received.
-int QuicSession::OnExtendMaxStreamsBidi(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->ExtendMaxStreamsBidi(max_streams);
- return 0;
-}
-
-// Called by ngtcp2 for both client and server connections
-// when a request to extend the maximum number of unidirectional
-// streams has been received
-int QuicSession::OnExtendMaxStreamsUni(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->ExtendMaxStreamsUni(max_streams);
- return 0;
-}
-
-// Triggered by ngtcp2 when the local peer has received an
-// indication from the remote peer indicating that additional
-// unidirectional streams may be sent. The max_streams parameter
-// identifies the highest unidirectional stream ID that may be
-// opened.
-int QuicSession::OnExtendMaxStreamsRemoteUni(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->ExtendMaxStreamsRemoteUni(max_streams);
- return 0;
-}
-
-// Triggered by ngtcp2 when the local peer has received an
-// indication from the remote peer indicating that additional
-// bidirectional streams may be sent. The max_streams parameter
-// identifies the highest bidirectional stream ID that may be
-// opened.
-int QuicSession::OnExtendMaxStreamsRemoteBidi(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->ExtendMaxStreamsRemoteUni(max_streams);
- return 0;
-}
-
-// Triggered by ngtcp2 when the local peer has received a flow
-// control signal from the remote peer indicating that additional
-// data can be sent. The max_data parameter identifies the maximum
-// data offset that may be sent. That is, a value of 99 means that
-// out of a stream of 1000 bytes, only the first 100 may be sent.
-// (offsets 0 through 99).
-int QuicSession::OnExtendMaxStreamData(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t max_data,
- void* user_data,
- void* stream_user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->ExtendMaxStreamData(stream_id, max_data);
- return 0;
-}
-
-int QuicSession::OnConnectionIDStatus(
- ngtcp2_conn* conn,
- int type,
- uint64_t seq,
- const ngtcp2_cid* cid,
- const uint8_t* token,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- if (token != nullptr) {
- QuicCID qcid(cid);
- Debug(session, "Updating connection ID %s with reset token", qcid);
- session->UpdateConnectionID(type, qcid, StatelessResetToken(token));
- }
- return 0;
-}
-
-// Called by ngtcp2 for both client and server connections
-// when ngtcp2 has determined that the TLS handshake has
-// been completed. It is important to understand that this
-// is only an indication of the local peer's handshake state.
-// The remote peer might not yet have completed its part
-// of the handshake.
-int QuicSession::OnHandshakeCompleted(
- ngtcp2_conn* conn,
- void* user_data) {
-
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->HandshakeCompleted();
- return 0;
-}
-
-// Called by ngtcp2 for clients when the handshake has been
-// confirmed. Confirmation occurs *after* handshake completion.
-int QuicSession::OnHandshakeConfirmed(
- ngtcp2_conn* conn,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->HandshakeConfirmed();
- return 0;
-}
-
-// Called by ngtcp2 when a chunk of stream data has been received.
-// Currently, ngtcp2 ensures that this callback is always called
-// with an offset parameter strictly larger than the previous call's
-// offset + datalen (that is, data will never be delivered out of
-// order). That behavior may change in the future but only via a
-// configuration option.
-int QuicSession::OnReceiveStreamData(
- ngtcp2_conn* conn,
- uint32_t flags,
- int64_t stream_id,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen,
- void* user_data,
- void* stream_user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- return session->ReceiveStreamData(
- flags,
- stream_id,
- data,
- datalen,
- offset) ? 0 : NGTCP2_ERR_CALLBACK_FAILURE;
-}
-
-// Called by ngtcp2 when a new stream has been opened
-int QuicSession::OnStreamOpen(
- ngtcp2_conn* conn,
- int64_t stream_id,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- // We currently do not do anything with this callback.
- // QuicStream instances are created implicitly once the
- // first chunk of stream data is received.
-
- return 0;
-}
-
-// Called by ngtcp2 when an acknowledgement for a chunk of
-// TLS handshake data has been received by the remote peer.
-// This is only an indication that data was received, not that
-// it was successfully processed. Acknowledgements are a key
-// part of the QUIC reliability mechanism.
-int QuicSession::OnAckedCryptoOffset(
- ngtcp2_conn* conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- uint64_t datalen,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->crypto_context()->AcknowledgeCryptoData(crypto_level, datalen);
- return 0;
-}
-
-// Called by ngtcp2 when an acknowledgement for a chunk of
-// stream data has been received successfully by the remote peer.
-// This is only an indication that data was received, not that
-// it was successfully processed. Acknowledgements are a key
-// part of the QUIC reliability mechanism.
-int QuicSession::OnAckedStreamDataOffset(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t offset,
- uint64_t datalen,
- void* user_data,
- void* stream_user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->AckedStreamDataOffset(stream_id, offset, datalen);
- return 0;
-}
-
-// Called by ngtcp2 for a client connection when the server
-// has indicated a preferred address in the transport
-// params.
-// For now, there are two modes: we can accept the preferred address
-// or we can reject it. Later, we may want to implement a callback
-// to ask the user if they want to accept the preferred address or
-// not.
-int QuicSession::OnSelectPreferredAddress(
- ngtcp2_conn* conn,
- ngtcp2_addr* dest,
- const ngtcp2_preferred_addr* paddr,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
-
- // The paddr parameter contains the server advertised preferred
- // address. The dest parameter contains the address that is
- // actually being used. If the preferred address is selected,
- // then the contents of paddr are copied over to dest. It is
- // important to remember that SelectPreferredAddress should
- // return true regardless of whether the preferred address was
- // selected or not. It should only return false if there was
- // an actual failure processing things. Note, however, that
- // even in such a failure, we debug log and ignore it.
- // If the preferred address is not selected, dest remains
- // unchanged.
- PreferredAddress preferred_address(session->env(), dest, paddr);
- session->SelectPreferredAddress(preferred_address);
- return 0;
-}
-
-// Called by ngtcp2 when a stream has been closed.
-int QuicSession::OnStreamClose(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* user_data,
- void* stream_user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->StreamClose(stream_id, app_error_code);
- return 0;
-}
-
-// Stream reset means the remote peer will no longer send data
-// on the identified stream. It is essentially a premature close.
-// The final_size parameter is important here in that it identifies
-// exactly how much data the *remote peer* is aware that it sent.
-// If there are lost packets, then the local peer's idea of the final
-// size might not match.
-int QuicSession::OnStreamReset(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t final_size,
- uint64_t app_error_code,
- void* user_data,
- void* stream_user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->StreamReset(stream_id, final_size, app_error_code);
- return 0;
-}
-
-// Called by ngtcp2 when it needs to generate some random data.
-// We currently do not use it, but the ngtcp2_rand_ctx identifies
-// why the random data is necessary. When ctx is equal to
-// NGTCP2_RAND_CTX_NONE, it typically means the random data
-// is being used during the TLS handshake. When ctx is equal to
-// NGTCP2_RAND_CTX_PATH_CHALLENGE, the random data is being
-// used to construct a PATH_CHALLENGE. These *might* need more
-// secure and robust random number generation given the
-// sensitivity of PATH_CHALLENGE operations (an attacker
-// could use a compromised PATH_CHALLENGE to trick an endpoint
-// into redirecting traffic).
-//
-// The ngtcp2_rand_ctx tells us what the random data is used for.
-// Currently, there is only one use. In the future, we'll want to
-// explore whether we want to handle the different cases uses.
-int QuicSession::OnRand(
- uint8_t* dest,
- size_t destlen,
- ngtcp2_rand_ctx ctx) {
- EntropySource(dest, destlen);
- return 0;
-}
-
-// When a new client connection is established, ngtcp2 will call
-// this multiple times to generate a pool of connection IDs to use.
-int QuicSession::OnGetNewConnectionID(
- ngtcp2_conn* conn,
- ngtcp2_cid* cid,
- uint8_t* token,
- size_t cidlen,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- CHECK(!NgCallbackScope::InNgCallbackScope(session));
- session->GetNewConnectionID(cid, token, cidlen);
- return 0;
-}
-
-// When a connection is closed, ngtcp2 will call this multiple
-// times to retire connection IDs. It's also possible for this
-// to be called at times throughout the lifecycle of the connection
-// to remove a CID from the availability pool.
-int QuicSession::OnRemoveConnectionID(
- ngtcp2_conn* conn,
- const ngtcp2_cid* cid,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- if (session->is_server())
- session->socket()->DisassociateCID(QuicCID(cid));
- return 0;
-}
-
-// Called by ngtcp2 to perform path validation. Path validation
-// is necessary to ensure that a packet is originating from the
-// expected source. If the res parameter indicates success, it
-// means that the path specified has been verified as being
-// valid.
-//
-// Validity here means only that there has been a successful
-// exchange of PATH_CHALLENGE information between the peers.
-// It's critical to understand that the validity of a path
-// can change at any timee so this is only an indication of
-// validity at a specific point in time.
-int QuicSession::OnPathValidation(
- ngtcp2_conn* conn,
- const ngtcp2_path* path,
- ngtcp2_path_validation_result res,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->PathValidation(path, res);
- return 0;
-}
-
-// Triggered by ngtcp2 when a version negotiation is received.
-// What this means is that the remote peer does not support the
-// QUIC version requested. The only thing we can do here (per
-// the QUIC specification) is silently discard the connection
-// and notify the JavaScript side that a different version of
-// QUIC should be used. The sv parameter does list the QUIC
-// versions advertised as supported by the remote peer.
-int QuicSession::OnVersionNegotiation(
- ngtcp2_conn* conn,
- const ngtcp2_pkt_hd* hd,
- const uint32_t* sv,
- size_t nsv,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- QuicSession::NgCallbackScope callback_scope(session);
- session->VersionNegotiation(sv, nsv);
- return 0;
-}
-
-// Triggered by ngtcp2 when a stateless reset is received. What this
-// means is that the remote peer might recognize the CID but has lost
-// all state necessary to successfully process it. The only thing we
-// can do is silently close the connection. For server sessions, this
-// means all session state is shut down and discarded, even on the
-// JavaScript side. For client sessions, we discard session state at
-// the C++ layer but -- at least in the future -- we can retain some
-// state at the JavaScript level to allow for automatic session
-// resumption.
-int QuicSession::OnStatelessReset(
- ngtcp2_conn* conn,
- const ngtcp2_pkt_stateless_reset* sr,
- void* user_data) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
-
- if (UNLIKELY(session->is_destroyed()))
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- session->set_stateless_reset();
- return 0;
-}
-
-const ngtcp2_conn_callbacks QuicSession::callbacks[2] = {
- // NGTCP2_CRYPTO_SIDE_CLIENT
- {
- ngtcp2_crypto_client_initial_cb,
- nullptr,
- OnReceiveCryptoData,
- OnHandshakeCompleted,
- OnVersionNegotiation,
- ngtcp2_crypto_encrypt_cb,
- ngtcp2_crypto_decrypt_cb,
- ngtcp2_crypto_hp_mask_cb,
- OnReceiveStreamData,
- OnAckedCryptoOffset,
- OnAckedStreamDataOffset,
- OnStreamOpen,
- OnStreamClose,
- OnStatelessReset,
- ngtcp2_crypto_recv_retry_cb,
- OnExtendMaxStreamsBidi,
- OnExtendMaxStreamsUni,
- OnRand,
- OnGetNewConnectionID,
- OnRemoveConnectionID,
- ngtcp2_crypto_update_key_cb,
- OnPathValidation,
- OnSelectPreferredAddress,
- OnStreamReset,
- OnExtendMaxStreamsRemoteBidi,
- OnExtendMaxStreamsRemoteUni,
- OnExtendMaxStreamData,
- OnConnectionIDStatus,
- OnHandshakeConfirmed,
- nullptr, // recv_new_token
- ngtcp2_crypto_delete_crypto_aead_ctx_cb,
- ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
- },
- // NGTCP2_CRYPTO_SIDE_SERVER
- {
- nullptr,
- ngtcp2_crypto_recv_client_initial_cb,
- OnReceiveCryptoData,
- OnHandshakeCompleted,
- nullptr, // recv_version_negotiation
- ngtcp2_crypto_encrypt_cb,
- ngtcp2_crypto_decrypt_cb,
- ngtcp2_crypto_hp_mask_cb,
- OnReceiveStreamData,
- OnAckedCryptoOffset,
- OnAckedStreamDataOffset,
- OnStreamOpen,
- OnStreamClose,
- OnStatelessReset,
- nullptr, // recv_retry
- nullptr, // extend_max_streams_bidi
- nullptr, // extend_max_streams_uni
- OnRand,
- OnGetNewConnectionID,
- OnRemoveConnectionID,
- ngtcp2_crypto_update_key_cb,
- OnPathValidation,
- nullptr, // select_preferred_addr
- OnStreamReset,
- OnExtendMaxStreamsRemoteBidi,
- OnExtendMaxStreamsRemoteUni,
- OnExtendMaxStreamData,
- OnConnectionIDStatus,
- nullptr, // handshake_confirmed
- nullptr, // recv_new_token
- ngtcp2_crypto_delete_crypto_aead_ctx_cb,
- ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
- }
-};
-
-BaseObjectPtr<QLogStream> QuicSession::qlog_stream() {
- if (!qlog_stream_) {
- CHECK(qlog_stream_ = QLogStream::Create(env()));
- listener_->OnQLog(qlog_stream_.get());
- }
- return qlog_stream_;
-}
-
-void QuicSession::OnQlogWrite(
- void* user_data,
- uint32_t flags,
- const void* data,
- size_t len) {
- QuicSession* session = static_cast<QuicSession*>(user_data);
- Environment* env = session->env();
-
- // Fun fact... ngtcp2 does not emit the final qlog statement until the
- // ngtcp2_conn object is destroyed. Ideally, destroying is explicit,
- // but sometimes the QuicSession object can be garbage collected without
- // being explicitly destroyed. During those times, we cannot call out
- // to JavaScript. Because we don't know for sure if we're in in a GC
- // when this is called, it is safer to just defer writes to immediate.
- BaseObjectPtr<QLogStream> ptr = session->qlog_stream();
- std::vector<uint8_t> buffer(len);
- memcpy(buffer.data(), data, len);
- env->SetImmediate([ptr = std::move(ptr),
- buffer = std::move(buffer),
- flags](Environment*) {
- ptr->Emit(buffer.data(), buffer.size(), flags);
- });
-}
-
-BaseObjectPtr<QLogStream> QLogStream::Create(Environment* env) {
- HandleScope scope(env->isolate());
-
- // TODO(@jasnell): There is identical code in heap_utils for the
- // HeapSnapshotStream. We can consolidate the two.
- if (env->qlogoutputstream_constructor_template().IsEmpty()) {
- // Create FunctionTemplate for QLogStream
- Local<FunctionTemplate> os = FunctionTemplate::New(env->isolate());
- os->Inherit(AsyncWrap::GetConstructorTemplate(env));
- Local<ObjectTemplate> ost = os->InstanceTemplate();
- ost->SetInternalFieldCount(StreamBase::kInternalFieldCount);
- os->SetClassName(
- FIXED_ONE_BYTE_STRING(env->isolate(), "QLogStream"));
- StreamBase::AddMethods(env, os);
- env->set_qlogoutputstream_constructor_template(ost);
- }
-
- Local<Object> obj;
- if (!env->qlogoutputstream_constructor_template()
- ->NewInstance(env->context())
- .ToLocal(&obj)) {
- return {};
- }
-
- return MakeBaseObject<QLogStream>(env, obj);
-}
-
-QLogStream::QLogStream(Environment* env, v8::Local<Object> obj)
- : AsyncWrap(env, obj, AsyncWrap::PROVIDER_QLOGSTREAM),
- StreamBase(env) {
- MakeWeak();
- StreamBase::AttachToObject(GetObject());
-}
-
-void QLogStream::Emit(const uint8_t* data, size_t len, uint32_t flags) {
- size_t remaining = len;
- while (remaining != 0) {
- uv_buf_t buf = EmitAlloc(len);
- ssize_t avail = std::min<size_t>(remaining, buf.len);
- memcpy(buf.base, data, avail);
- remaining -= avail;
- data += avail;
- EmitRead(avail, buf);
- }
-
- if (ended_ && flags & NGTCP2_QLOG_WRITE_FLAG_FIN)
- EmitRead(UV_EOF);
-}
-
-int QLogStream::DoShutdown(ShutdownWrap* req_wrap) {
- UNREACHABLE();
-}
-
-int QLogStream::DoWrite(
- WriteWrap* w,
- uv_buf_t* bufs,
- size_t count,
- uv_stream_t* send_handle) {
- UNREACHABLE();
-}
-
-bool QLogStream::IsAlive() { return true; }
-bool QLogStream::IsClosing() { return false; }
-
-// JavaScript API
-
-namespace {
-void QuicSessionSetSocket(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- CHECK(args[0]->IsObject());
- ASSIGN_OR_RETURN_UNWRAP(&socket, args[0].As<Object>());
- args.GetReturnValue().Set(session->set_socket(socket, args[1]->IsTrue()));
-}
-
-// GracefulClose flips a flag that prevents new local streams
-// from being opened and new remote streams from being received. It is
-// important to note that this does *NOT* send a CONNECTION_CLOSE packet
-// to the peer. Existing streams are permitted to close gracefully.
-void QuicSessionGracefulClose(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- session->StartGracefulClose();
-}
-
-// Destroying the QuicSession will trigger sending of a CONNECTION_CLOSE
-// packet, after which the QuicSession will be immediately torn down.
-void QuicSessionDestroy(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- session->set_last_error(QuicError(env, args[0], args[1]));
- session->Destroy();
-}
-
-void QuicSessionGetEphemeralKeyInfo(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- Local<Object> ret;
- if (session->crypto_context()->ephemeral_key().ToLocal(&ret))
- args.GetReturnValue().Set(ret);
-}
-
-void QuicSessionGetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- Local<Value> ret;
- if (session->crypto_context()->peer_cert(!args[0]->IsTrue()).ToLocal(&ret))
- args.GetReturnValue().Set(ret);
-}
-
-void QuicSessionGetRemoteAddress(
- const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- Environment* env = session->env();
- CHECK(args[0]->IsObject());
- args.GetReturnValue().Set(
- session->remote_address().ToJS(env, args[0].As<Object>()));
-}
-
-void QuicSessionGetCertificate(
- const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- Local<Value> ret;
- if (session->crypto_context()->cert().ToLocal(&ret))
- args.GetReturnValue().Set(ret);
-}
-
-void QuicSessionPing(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- session->Ping();
-}
-
-// Triggers a silent close of a QuicSession. This is currently only used
-// (and should ever only be used) for testing purposes...
-void QuicSessionSilentClose(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
- ProcessEmitWarning(
- session->env(),
- "Forcing silent close of QuicSession for testing purposes only");
- session->Close(QuicSessionListener::SESSION_CLOSE_FLAG_SILENT);
-}
-
-// This is used purely for testing.
-void QuicSessionRemoveFromSocket(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- session->RemoveFromSocket();
-}
-
-void QuicSessionUpdateKey(const FunctionCallbackInfo<Value>& args) {
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
- // Initiating a key update may fail if it is done too early (either
- // before the TLS handshake has been confirmed or while a previous
- // key update is being processed). When it fails, InitiateKeyUpdate()
- // will return false.
- args.GetReturnValue().Set(session->crypto_context()->InitiateKeyUpdate());
-}
-
-// When a client wishes to resume a prior TLS session, it must specify both
-// the remember transport parameters and remembered TLS session ticket. Those
-// will each be provided as a TypedArray. The DecodeTransportParams and
-// DecodeSessionTicket functions handle those. If the argument is undefined,
-// then resumption is not used.
-
-bool DecodeTransportParams(
- Local<Value> value,
- ngtcp2_transport_params* params) {
- if (value->IsUndefined())
- return false;
- CHECK(value->IsArrayBufferView());
- ArrayBufferViewContents<uint8_t> sbuf(value.As<ArrayBufferView>());
- if (sbuf.length() != sizeof(ngtcp2_transport_params))
- return false;
- memcpy(params, sbuf.data(), sizeof(ngtcp2_transport_params));
- return true;
-}
-
-crypto::SSLSessionPointer DecodeSessionTicket(Local<Value> value) {
- if (value->IsUndefined())
- return {};
- CHECK(value->IsArrayBufferView());
- ArrayBufferViewContents<unsigned char> sbuf(value.As<ArrayBufferView>());
- return crypto::GetTLSSession(sbuf.data(), sbuf.length());
-}
-
-void NewQuicClientSession(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
-
- QuicSocket* socket;
- int32_t family;
- uint32_t port;
- SecureContext* sc;
- SocketAddress remote_addr;
- int32_t preferred_address_policy;
- PreferredAddressStrategy preferred_address_strategy;
- uint32_t options = QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY;
- std::string alpn(NGHTTP3_ALPN_H3);
-
- enum ARG_IDX : int {
- SOCKET,
- TYPE,
- IP,
- PORT,
- SECURE_CONTEXT,
- SNI,
- REMOTE_TRANSPORT_PARAMS,
- SESSION_TICKET,
- DCID,
- PREFERRED_ADDRESS_POLICY,
- ALPN,
- OPTIONS,
- QLOG
- };
-
- CHECK(args[ARG_IDX::SOCKET]->IsObject());
- CHECK(args[ARG_IDX::SECURE_CONTEXT]->IsObject());
- CHECK(args[ARG_IDX::IP]->IsString());
- CHECK(args[ARG_IDX::ALPN]->IsString());
- CHECK(args[ARG_IDX::TYPE]->Int32Value(env->context()).To(&family));
- CHECK(args[ARG_IDX::PORT]->Uint32Value(env->context()).To(&port));
- CHECK(args[ARG_IDX::OPTIONS]->Uint32Value(env->context()).To(&options));
- if (!args[ARG_IDX::SNI]->IsUndefined())
- CHECK(args[ARG_IDX::SNI]->IsString());
-
- ASSIGN_OR_RETURN_UNWRAP(&socket, args[ARG_IDX::SOCKET].As<Object>());
- ASSIGN_OR_RETURN_UNWRAP(&sc, args[ARG_IDX::SECURE_CONTEXT].As<Object>());
-
- CHECK(args[ARG_IDX::PREFERRED_ADDRESS_POLICY]->Int32Value(
- env->context()).To(&preferred_address_policy));
- switch (preferred_address_policy) {
- case QUIC_PREFERRED_ADDRESS_USE:
- preferred_address_strategy = QuicSession::UsePreferredAddressStrategy;
- break;
- default:
- preferred_address_strategy = QuicSession::IgnorePreferredAddressStrategy;
- }
-
- node::Utf8Value address(env->isolate(), args[ARG_IDX::IP]);
- node::Utf8Value servername(env->isolate(), args[ARG_IDX::SNI]);
-
- if (!SocketAddress::New(family, *address, port, &remote_addr))
- return args.GetReturnValue().Set(ERR_FAILED_TO_CREATE_SESSION);
-
- // ALPN is a string prefixed by the length, followed by values
- Utf8Value val(env->isolate(), args[ARG_IDX::ALPN]);
- alpn = val.length();
- alpn += *val;
-
- crypto::SSLSessionPointer early_session_ticket =
- DecodeSessionTicket(args[ARG_IDX::SESSION_TICKET]);
- ngtcp2_transport_params early_transport_params;
- bool has_early_transport_params =
- DecodeTransportParams(
- args[ARG_IDX::REMOTE_TRANSPORT_PARAMS],
- &early_transport_params);
-
- socket->ReceiveStart();
-
- BaseObjectPtr<QuicSession> session =
- QuicSession::CreateClient(
- socket,
- socket->local_address(),
- remote_addr,
- BaseObjectPtr<SecureContext>(sc),
- has_early_transport_params ? &early_transport_params : nullptr,
- std::move(early_session_ticket),
- args[ARG_IDX::DCID],
- preferred_address_strategy,
- alpn,
- std::string(*servername),
- options,
- args[ARG_IDX::QLOG]->IsTrue() ?
- QlogMode::kEnabled :
- QlogMode::kDisabled);
- session->SendPendingData();
- if (session->is_destroyed())
- return args.GetReturnValue().Set(ERR_FAILED_TO_CREATE_SESSION);
-
- args.GetReturnValue().Set(session->object());
-}
-
-// Add methods that are shared by both client and server QuicSessions
-void AddMethods(Environment* env, Local<FunctionTemplate> session) {
- env->SetProtoMethod(session, "destroy", QuicSessionDestroy);
- env->SetProtoMethod(session, "getRemoteAddress", QuicSessionGetRemoteAddress);
- env->SetProtoMethod(session, "getCertificate", QuicSessionGetCertificate);
- env->SetProtoMethod(session, "getPeerCertificate",
- QuicSessionGetPeerCertificate);
- env->SetProtoMethod(session, "gracefulClose", QuicSessionGracefulClose);
- env->SetProtoMethod(session, "updateKey", QuicSessionUpdateKey);
- env->SetProtoMethod(session, "ping", QuicSessionPing);
- env->SetProtoMethod(session, "removeFromSocket", QuicSessionRemoveFromSocket);
- env->SetProtoMethod(session, "onClientHelloDone",
- QuicSessionOnClientHelloDone);
- env->SetProtoMethod(session, "onCertDone", QuicSessionOnCertDone);
-}
-} // namespace
-
-void QuicSession::Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context) {
- {
- Local<String> class_name =
- FIXED_ONE_BYTE_STRING(env->isolate(), "QuicServerSession");
- Local<FunctionTemplate> session = FunctionTemplate::New(env->isolate());
- session->SetClassName(class_name);
- session->Inherit(AsyncWrap::GetConstructorTemplate(env));
- Local<ObjectTemplate> sessiont = session->InstanceTemplate();
- sessiont->SetInternalFieldCount(QuicSession::kInternalFieldCount);
- sessiont->Set(env->owner_symbol(), Null(env->isolate()));
- AddMethods(env, session);
- env->set_quicserversession_instance_template(sessiont);
- }
-
- {
- Local<String> class_name =
- FIXED_ONE_BYTE_STRING(env->isolate(), "QuicClientSession");
- Local<FunctionTemplate> session = FunctionTemplate::New(env->isolate());
- session->SetClassName(class_name);
- session->Inherit(AsyncWrap::GetConstructorTemplate(env));
- Local<ObjectTemplate> sessiont = session->InstanceTemplate();
- sessiont->SetInternalFieldCount(QuicSession::kInternalFieldCount);
- sessiont->Set(env->owner_symbol(), Null(env->isolate()));
- AddMethods(env, session);
- env->SetProtoMethod(session,
- "getEphemeralKeyInfo",
- QuicSessionGetEphemeralKeyInfo);
- env->SetProtoMethod(session,
- "setSocket",
- QuicSessionSetSocket);
- env->set_quicclientsession_instance_template(sessiont);
-
- env->SetMethod(target, "createClientSession", NewQuicClientSession);
- env->SetMethod(target, "silentCloseSession", QuicSessionSilentClose);
- }
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_session.h b/src/quic/node_quic_session.h
deleted file mode 100644
index 10e16cc268..0000000000
--- a/src/quic/node_quic_session.h
+++ /dev/null
@@ -1,1531 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_SESSION_H_
-#define SRC_QUIC_NODE_QUIC_SESSION_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "aliased_buffer.h"
-#include "aliased_struct.h"
-#include "async_wrap.h"
-#include "env.h"
-#include "handle_wrap.h"
-#include "node.h"
-#include "node_crypto.h"
-#include "node_http_common.h"
-#include "node_mem.h"
-#include "node_quic_state.h"
-#include "node_quic_buffer-inl.h"
-#include "node_quic_crypto.h"
-#include "node_quic_util.h"
-#include "node_sockaddr.h"
-#include "stream_base.h"
-#include "timer_wrap.h"
-#include "v8.h"
-#include "uv.h"
-
-#include <ngtcp2/ngtcp2.h>
-#include <ngtcp2/ngtcp2_crypto.h>
-#include <nghttp3/nghttp3.h>
-#include <openssl/ssl.h>
-
-#include <unordered_map>
-#include <string>
-#include <vector>
-
-namespace node {
-namespace quic {
-
-using ConnectionPointer = DeleteFnPtr<ngtcp2_conn, ngtcp2_conn_del>;
-
-class QuicApplication;
-class QuicPacket;
-class QuicSocket;
-class QuicStream;
-
-using QuicHeader = NgHeaderBase<QuicApplication>;
-
-using StreamsMap = std::unordered_map<int64_t, BaseObjectPtr<QuicStream>>;
-
-enum class QlogMode {
- kDisabled,
- kEnabled
-};
-
-typedef void(*ConnectionIDStrategy)(
- QuicSession* session,
- ngtcp2_cid* cid,
- size_t cidlen);
-
-typedef void(*PreferredAddressStrategy)(
- QuicSession* session,
- const PreferredAddress& preferred_address);
-
-// The QuicSessionConfig class holds the initial transport parameters and
-// configuration options set by the JavaScript side when either a
-// client or server QuicSession is created. Instances are
-// stack created and use a combination of an AliasedBuffer to pass
-// the numeric settings quickly (see node_quic_state.h) and passed
-// in non-numeric settings (e.g. preferred_addr).
-class QuicSessionConfig final : public ngtcp2_settings {
- public:
- QuicSessionConfig() = default;
-
- explicit QuicSessionConfig(QuicState* quic_state) {
- Set(quic_state);
- }
-
- QuicSessionConfig(const QuicSessionConfig& config) {
- initial_ts = uv_hrtime();
- initial_rtt = config.initial_rtt;
- transport_params = config.transport_params;
- max_udp_payload_size = config.max_udp_payload_size;
- cc_algo = config.cc_algo;
- cc = config.cc;
- qlog = config.qlog;
- log_printf = config.log_printf;
- token = config.token;
- }
-
- void ResetToDefaults(QuicState* quic_state);
-
- // QuicSessionConfig::Set() pulls values out of the AliasedBuffer
- // defined in node_quic_state.h and stores the values in settings_.
- // If preferred_addr is not nullptr, it is copied into the
- // settings_.preferred_addr field
- void Set(QuicState* quic_state,
- const struct sockaddr* preferred_addr = nullptr);
-
- inline void set_original_connection_id(
- const QuicCID& ocid,
- const QuicCID& scid);
-
- // Generates the stateless reset token for the settings_
- inline void GenerateStatelessResetToken(
- QuicSession* session,
- const QuicCID& cid);
-
- // If the preferred address is set, generates the associated tokens
- inline void GeneratePreferredAddressToken(
- ConnectionIDStrategy connection_id_strategy,
- QuicSession* session,
- QuicCID* pscid);
-
- inline void set_qlog(const ngtcp2_qlog_settings& qlog);
-};
-
-// Options to alter the behavior of various functions on the
-// server QuicSession. These are set on the QuicSocket when
-// the listen() function is called and are passed to the
-// constructor of the server QuicSession.
-enum QuicServerSessionOptions : uint32_t {
- // When set, instructs the server QuicSession to reject
- // client authentication certs that cannot be verified.
- QUICSERVERSESSION_OPTION_REJECT_UNAUTHORIZED = 0x1,
-
- // When set, instructs the server QuicSession to request
- // a client authentication cert
- QUICSERVERSESSION_OPTION_REQUEST_CERT = 0x2
-};
-
-// Options to alter the behavior of various functions on the
-// client QuicSession. These are set on the client QuicSession
-// constructor.
-enum QuicClientSessionOptions : uint32_t {
- // When set, instructs the client QuicSession to include an
- // OCSP request in the initial TLS handshake
- QUICCLIENTSESSION_OPTION_REQUEST_OCSP = 0x1,
-
- // When set, instructs the client QuicSession to verify the
- // hostname identity. This is required by QUIC and enabled
- // by default. We allow disabling it only for debugging
- // purposes.
- QUICCLIENTSESSION_OPTION_VERIFY_HOSTNAME_IDENTITY = 0x2,
-
- // When set, instructs the client QuicSession to perform
- // additional checks on TLS session resumption.
- QUICCLIENTSESSION_OPTION_RESUME = 0x4
-};
-
-#define QUICSESSION_SHARED_STATE(V) \
- V(KEYLOG_ENABLED, keylog_enabled, uint8_t) \
- V(CLIENT_HELLO_ENABLED, client_hello_enabled, uint8_t) \
- V(OCSP_ENABLED, ocsp_enabled, uint8_t) \
- V(PATH_VALIDATED_ENABLED, path_validated_enabled, uint8_t) \
- V(USE_PREFERRED_ADDRESS_ENABLED, use_preferred_address_enabled, uint8_t) \
- V(HANDSHAKE_CONFIRMED, handshake_confirmed, uint8_t) \
- V(IDLE_TIMEOUT, idle_timeout, uint8_t) \
- V(MAX_STREAMS_BIDI, max_streams_bidi, uint64_t) \
- V(MAX_STREAMS_UNI, max_streams_uni, uint64_t) \
- V(MAX_DATA_LEFT, max_data_left, uint64_t) \
- V(BYTES_IN_FLIGHT, bytes_in_flight, uint64_t)
-
-#define V(_, name, type) type name;
-struct QuicSessionState {
- QUICSESSION_SHARED_STATE(V)
-};
-#undef V
-
-#define V(id, name, _) \
- IDX_QUICSESSION_STATE_##id = offsetof(QuicSessionState, name),
-enum QuicSessionStateFields {
- QUICSESSION_SHARED_STATE(V)
- IDX_QUICSESSION_STATE_END
-};
-#undef V
-
-#define SESSION_STATS(V) \
- V(CREATED_AT, created_at, "Created At") \
- V(HANDSHAKE_START_AT, handshake_start_at, "Handshake Started") \
- V(HANDSHAKE_SEND_AT, handshake_send_at, "Handshke Last Sent") \
- V(HANDSHAKE_CONTINUE_AT, handshake_continue_at, "Handshke Continued") \
- V(HANDSHAKE_COMPLETED_AT, handshake_completed_at, "Handshake Completed") \
- V(HANDSHAKE_CONFIRMED_AT, handshake_confirmed_at, "Handshake Confirmed") \
- V(HANDSHAKE_ACKED_AT, handshake_acked_at, "Handshake Last Acknowledged") \
- V(SENT_AT, sent_at, "Last Sent At") \
- V(RECEIVED_AT, received_at, "Last Received At") \
- V(CLOSING_AT, closing_at, "Closing") \
- V(DESTROYED_AT, destroyed_at, "Destroyed At") \
- V(BYTES_RECEIVED, bytes_received, "Bytes Received") \
- V(BYTES_SENT, bytes_sent, "Bytes Sent") \
- V(BIDI_STREAM_COUNT, bidi_stream_count, "Bidi Stream Count") \
- V(UNI_STREAM_COUNT, uni_stream_count, "Uni Stream Count") \
- V(STREAMS_IN_COUNT, streams_in_count, "Streams In Count") \
- V(STREAMS_OUT_COUNT, streams_out_count, "Streams Out Count") \
- V(KEYUPDATE_COUNT, keyupdate_count, "Key Update Count") \
- V(LOSS_RETRANSMIT_COUNT, loss_retransmit_count, "Loss Retransmit Count") \
- V(ACK_DELAY_RETRANSMIT_COUNT, \
- ack_delay_retransmit_count, \
- "Ack Delay Retransmit Count") \
- V(PATH_VALIDATION_SUCCESS_COUNT, \
- path_validation_success_count, \
- "Path Validation Success Count") \
- V(PATH_VALIDATION_FAILURE_COUNT, \
- path_validation_failure_count, \
- "Path Validation Failure Count") \
- V(MAX_BYTES_IN_FLIGHT, max_bytes_in_flight, "Max Bytes In Flight") \
- V(BLOCK_COUNT, block_count, "Block Count") \
- V(MIN_RTT, min_rtt, "Minimum RTT") \
- V(LATEST_RTT, latest_rtt, "Latest RTT") \
- V(SMOOTHED_RTT, smoothed_rtt, "Smoothed RTT") \
- V(CWND, cwnd, "Cwnd") \
- V(RECEIVE_RATE, receive_rate, "Receive Rate / Sec") \
- V(SEND_RATE, send_rate, "Send Rate Sec") \
-
-#define V(name, _, __) IDX_QUIC_SESSION_STATS_##name,
-enum QuicSessionStatsIdx : int {
- SESSION_STATS(V)
- IDX_QUIC_SESSION_STATS_COUNT
-};
-#undef V
-
-#define V(_, name, __) uint64_t name;
-struct QuicSessionStats {
- SESSION_STATS(V)
-};
-#undef V
-
-struct QuicSessionStatsTraits {
- using Stats = QuicSessionStats;
- using Base = QuicSession;
-
- template <typename Fn>
- static void ToString(const Base& ptr, Fn&& add_field);
-};
-
-class QLogStream final : public AsyncWrap,
- public StreamBase {
- public:
- static BaseObjectPtr<QLogStream> Create(Environment* env);
-
- QLogStream(Environment* env, v8::Local<v8::Object> obj);
-
- void Emit(const uint8_t* data, size_t len, uint32_t flags);
-
- void End() { ended_ = true; }
-
- int ReadStart() override { return 0; }
- int ReadStop() override { return 0; }
- int DoShutdown(ShutdownWrap* req_wrap) override;
- int DoWrite(WriteWrap* w,
- uv_buf_t* bufs,
- size_t count,
- uv_stream_t* send_handle) override;
- bool IsAlive() override;
- bool IsClosing() override;
- AsyncWrap* GetAsyncWrap() override { return this; }
-
- SET_NO_MEMORY_INFO();
- SET_MEMORY_INFO_NAME(QLogStream);
- SET_SELF_SIZE(QLogStream);
-
- private:
- bool ended_ = false;
-};
-
-class QuicSessionListener {
- public:
- enum SessionCloseFlags {
- SESSION_CLOSE_FLAG_NONE,
- SESSION_CLOSE_FLAG_SILENT,
- SESSION_CLOSE_FLAG_STATELESS_RESET
- };
-
- virtual ~QuicSessionListener();
-
- virtual void OnKeylog(const char* str, size_t size);
- virtual void OnClientHello(
- const char* alpn,
- const char* server_name);
- virtual void OnCert(const char* server_name);
- virtual void OnOCSP(v8::Local<v8::Value> ocsp);
- virtual void OnStreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id);
- virtual void OnStreamClose(
- int64_t stream_id,
- uint64_t app_error_code);
- virtual void OnStreamReset(
- int64_t stream_id,
- uint64_t app_error_code);
- virtual void OnSessionClose(
- QuicError error,
- int flags = SESSION_CLOSE_FLAG_NONE);
- virtual void OnStreamReady(BaseObjectPtr<QuicStream> stream);
- virtual void OnHandshakeCompleted();
- virtual void OnPathValidation(
- ngtcp2_path_validation_result res,
- const sockaddr* local,
- const sockaddr* remote);
- virtual void OnUsePreferredAddress(
- int family,
- const PreferredAddress& preferred_address);
- virtual void OnSessionTicket(int size, SSL_SESSION* session);
- virtual void OnStreamBlocked(int64_t stream_id);
- virtual void OnVersionNegotiation(
- uint32_t supported_version,
- const uint32_t* versions,
- size_t vcnt);
- virtual void OnQLog(QLogStream* qlog_stream);
-
- QuicSession* session() const { return session_.get(); }
-
- private:
- BaseObjectWeakPtr<QuicSession> session_;
- QuicSessionListener* previous_listener_ = nullptr;
- friend class QuicSession;
-};
-
-class JSQuicSessionListener final : public QuicSessionListener {
- public:
- void OnKeylog(const char* str, size_t size) override;
- void OnClientHello(
- const char* alpn,
- const char* server_name) override;
- void OnCert(const char* server_name) override;
- void OnOCSP(v8::Local<v8::Value> ocsp) override;
- void OnStreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id) override;
- void OnStreamClose(
- int64_t stream_id,
- uint64_t app_error_code) override;
- void OnStreamReset(
- int64_t stream_id,
- uint64_t app_error_code) override;
- void OnSessionClose(
- QuicError error,
- int flags = SESSION_CLOSE_FLAG_NONE) override;
- void OnStreamReady(BaseObjectPtr<QuicStream> stream) override;
- void OnHandshakeCompleted() override;
- void OnPathValidation(
- ngtcp2_path_validation_result res,
- const sockaddr* local,
- const sockaddr* remote) override;
- void OnSessionTicket(int size, SSL_SESSION* session) override;
- void OnUsePreferredAddress(
- int family,
- const PreferredAddress& preferred_address) override;
- void OnStreamBlocked(int64_t stream_id) override;
- void OnVersionNegotiation(
- uint32_t supported_version,
- const uint32_t* versions,
- size_t vcnt) override;
- void OnQLog(QLogStream* qlog_stream) override;
-
- private:
- friend class QuicSession;
-};
-
-#define QUICCRYPTOCONTEXT_FLAGS(V) \
- V(IN_TLS_CALLBACK, in_tls_callback) \
- V(IN_KEY_UPDATE, in_key_update) \
- V(IN_OCSP_RESPONSE, in_ocsp_request) \
- V(IN_CLIENT_HELLO, in_client_hello) \
- V(EARLY_DATA, early_data)
-
-// The QuicCryptoContext class encapsulates all of the crypto/TLS
-// handshake details on behalf of a QuicSession.
-class QuicCryptoContext final : public MemoryRetainer {
- public:
- inline QuicCryptoContext(
- QuicSession* session,
- BaseObjectPtr<crypto::SecureContext> secure_context,
- ngtcp2_crypto_side side,
- uint32_t options);
-
- ~QuicCryptoContext() override;
-
- inline uint64_t Cancel();
-
- // Outgoing crypto data must be retained in memory until it is
- // explicitly acknowledged. AcknowledgeCryptoData will be invoked
- // when ngtcp2 determines that it has received an acknowledgement
- // for crypto data at the specified level. This is our indication
- // that the data for that level can be released.
- void AcknowledgeCryptoData(ngtcp2_crypto_level level, uint64_t datalen);
-
- inline void Initialize();
-
- // Enables openssl's TLS tracing mechanism for this session only.
- void EnableTrace();
-
- // Returns the server's prepared OCSP response for transmission. This
- // is not used by client QuicSession instances.
- inline v8::MaybeLocal<v8::Value> ocsp_response() const;
-
- // Returns ngtcp2's understanding of the current inbound crypto level
- inline ngtcp2_crypto_level read_crypto_level() const;
-
- // Returns ngtcp2's understanding of the current outbound crypto level
- inline ngtcp2_crypto_level write_crypto_level() const;
-
- inline bool early_data() const;
-
- bool is_option_set(uint32_t option) const { return options_ & option; }
-
- // Emits a single keylog line to the JavaScript layer
- inline void Keylog(const char* line);
-
- int OnClientHello();
-
- void OnClientHelloDone(BaseObjectPtr<crypto::SecureContext> context);
-
- int OnOCSP();
-
- void OnOCSPDone(v8::Local<v8::Value> ocsp_response);
-
- bool OnSecrets(
- ngtcp2_crypto_level level,
- const uint8_t* rx_secret,
- const uint8_t* tx_secret,
- size_t secretlen);
-
- int OnTLSStatus();
-
- // Receives and processes TLS handshake details
- int Receive(
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen);
-
- // Resumes the TLS handshake following a client hello or
- // OCSP callback
- inline void ResumeHandshake();
-
- inline v8::MaybeLocal<v8::Value> cert() const;
- inline v8::MaybeLocal<v8::Value> cipher_name() const;
- inline v8::MaybeLocal<v8::Value> cipher_version() const;
- inline v8::MaybeLocal<v8::Object> ephemeral_key() const;
- inline const char* hello_alpn() const;
- inline v8::MaybeLocal<v8::Array> hello_ciphers() const;
- inline const char* hello_servername() const;
- inline v8::MaybeLocal<v8::Value> peer_cert(bool abbreviated) const;
- inline std::string selected_alpn() const;
- inline const char* servername() const;
-
- void set_option(uint32_t option, bool on = true) {
- if (on)
- options_ |= option;
- else
- options_ &= ~option;
- }
-
-#define V(id, name) \
- inline bool is_##name() const { \
- return flags_ & (1 << QUICCRYPTOCONTEXT_FLAG_##id); } \
- inline void set_##name(bool on = true) { \
- if (on) \
- flags_ |= (1 << QUICCRYPTOCONTEXT_FLAG_##id); \
- else \
- flags_ &= ~(1 << QUICCRYPTOCONTEXT_FLAG_##id); \
- }
- QUICCRYPTOCONTEXT_FLAGS(V)
-#undef V
-
- inline bool set_session(crypto::SSLSessionPointer session);
-
- inline void set_tls_alert(int err);
-
- ngtcp2_crypto_side side() const { return side_; }
-
- void WriteHandshake(
- ngtcp2_crypto_level level,
- const uint8_t* data,
- size_t datalen);
-
- bool InitiateKeyUpdate();
-
- int VerifyPeerIdentity();
-
- QuicSession* session() const { return session_.get(); }
-
- void MemoryInfo(MemoryTracker* tracker) const override;
-
- SET_MEMORY_INFO_NAME(QuicCryptoContext)
- SET_SELF_SIZE(QuicCryptoContext)
-
- private:
- bool SetSecrets(
- ngtcp2_crypto_level level,
- const uint8_t* rx_secret,
- const uint8_t* tx_secret,
- size_t secretlen);
-
- BaseObjectWeakPtr<QuicSession> session_;
- BaseObjectPtr<crypto::SecureContext> secure_context_;
- ngtcp2_crypto_side side_;
- crypto::SSLPointer ssl_;
- QuicBuffer handshake_[3];
- uint32_t options_;
- uint32_t flags_ = 0;
-
- v8::Global<v8::ArrayBufferView> ocsp_response_;
- crypto::BIOPointer bio_trace_;
-
-#define V(id, _) QUICCRYPTOCONTEXT_FLAG_##id,
- enum QuicCryptoContextFlags : uint32_t {
- QUICCRYPTOCONTEXT_FLAGS(V)
- QUICCRYPTOCONTEXT_FLAG_COUNT
- };
-#undef V
-
- class TLSCallbackScope {
- public:
- explicit TLSCallbackScope(QuicCryptoContext* context) :
- context_(context) {
- context_->set_in_tls_callback();
- }
-
- ~TLSCallbackScope() {
- context_->set_in_tls_callback(false);
- }
-
- static bool is_in_callback(QuicCryptoContext* context) {
- return context->is_in_tls_callback();
- }
-
- private:
- QuicCryptoContext* context_;
- };
-
- class TLSHandshakeScope {
- public:
- using DoneCB = std::function<void()>;
- TLSHandshakeScope(
- QuicCryptoContext* context,
- DoneCB done) :
- context_(context),
- done_(done) {}
-
- ~TLSHandshakeScope() {
- if (!is_handshake_suspended())
- return;
-
- done_();
- // Only continue the TLS handshake if we are not currently running
- // synchronously within the TLS handshake function. This can happen
- // when the callback function passed to the clientHello and cert
- // event handlers is called synchronously. If the function is called
- // asynchronously, then we have to manually continue the handshake.
- if (!TLSCallbackScope::is_in_callback(context_))
- context_->ResumeHandshake();
- }
-
- private:
- bool is_handshake_suspended() const {
- return context_->is_in_ocsp_request() || context_->is_in_client_hello();
- }
-
-
- QuicCryptoContext* context_;
- DoneCB done_;
- };
-
- friend class QuicSession;
-};
-
-// A QuicApplication encapsulates the specific details of
-// working with a specific QUIC application (e.g. http/3).
-class QuicApplication : public MemoryRetainer,
- public mem::NgLibMemoryManagerBase {
- public:
- inline explicit QuicApplication(QuicSession* session);
- virtual ~QuicApplication() = default;
-
- // The QuicSession will call Initialize as soon as the TLS
- // secrets have been set. See QuicCryptoContext::OnSecrets
- virtual bool Initialize() = 0;
-
- // QuicSession will forward all received stream data immediately
- // on to the QuicApplication. The only additional processing the
- // QuicSession does is to automatically adjust the QuicSession-level
- // flow control window. It is up to the QuicApplication to do
- // the same for the QuicStream-level flow control.
- //
- // flags are passed on directly from ngtcp2. The most important
- // of which here is NGTCP2_STREAM_DATA_FLAG_FIN, which indicates
- // that this is the final chunk of data that the peer will send
- // for this stream.
- //
- // It is also possible for the NGTCP2_STREAM_DATA_FLAG_0RTT flag
- // to be set, indicating that this chunk of data was received in
- // a 0RTT packet before the TLS handshake completed. This would
- // indicate that it is not as secure and could be replayed by
- // an attacker. We're not currently making use of that flag.
- virtual bool ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) = 0;
-
- virtual void AcknowledgeStreamData(
- int64_t stream_id,
- uint64_t offset,
- size_t datalen) {
- Acknowledge(stream_id, offset, datalen);
- }
-
- virtual bool BlockStream(int64_t id) { return true; }
-
- virtual void ExtendMaxStreamsRemoteUni(uint64_t max_streams) {}
-
- virtual void ExtendMaxStreamsRemoteBidi(uint64_t max_streams) {}
-
- virtual void ExtendMaxStreamData(int64_t stream_id, uint64_t max_data) {}
-
- virtual void ResumeStream(int64_t stream_id) {}
-
- // Different QUIC applications may set some application data in
- // the session ticket (e.g. http/3 would set server settings in the
- // application data). By default, there's nothing to set.
- virtual void SetSessionTicketAppData(const SessionTicketAppData& app_data) {}
-
- // Different QUIC applications may set some application data in
- // the session ticket (e.g. http/3 would set server settings in the
- // application data). By default, there's nothing to get.
- virtual SessionTicketAppData::Status GetSessionTicketAppData(
- const SessionTicketAppData& app_data,
- SessionTicketAppData::Flag flag) {
- return flag == SessionTicketAppData::Flag::STATUS_RENEW ?
- SessionTicketAppData::Status::TICKET_USE_RENEW :
- SessionTicketAppData::Status::TICKET_USE;
- }
-
- virtual void StreamHeaders(
- int64_t stream_id,
- int kind,
- const std::vector<std::unique_ptr<QuicHeader>>& headers,
- int64_t push_id = 0);
-
- virtual void StreamClose(
- int64_t stream_id,
- uint64_t app_error_code);
-
- virtual void StreamReset(
- int64_t stream_id,
- uint64_t app_error_code);
-
- virtual bool SubmitInformation(
- int64_t stream_id,
- v8::Local<v8::Array> headers) { return false; }
-
- virtual bool SubmitHeaders(
- int64_t stream_id,
- v8::Local<v8::Array> headers,
- uint32_t flags) { return false; }
-
- virtual bool SubmitTrailers(
- int64_t stream_id,
- v8::Local<v8::Array> headers) { return false; }
-
- virtual BaseObjectPtr<QuicStream> SubmitPush(
- int64_t stream_id,
- v8::Local<v8::Array> headers) {
- // By default, push streams are not supported
- // by an application.
- return {};
- }
-
- inline Environment* env() const;
-
- bool SendPendingData();
- size_t max_header_pairs() const { return max_header_pairs_; }
- size_t max_header_length() const { return max_header_length_; }
-
- protected:
- QuicSession* session() const { return session_.get(); }
- bool needs_init() const { return needs_init_; }
- void set_init_done() { needs_init_ = false; }
- inline void set_stream_fin(int64_t stream_id);
- void set_max_header_pairs(size_t max) { max_header_pairs_ = max; }
- void set_max_header_length(size_t max) { max_header_length_ = max; }
- inline std::unique_ptr<QuicPacket> CreateStreamDataPacket();
-
- struct StreamData {
- size_t count = 0;
- size_t remaining = 0;
- int64_t id = -1;
- int fin = 0;
- ngtcp2_vec data[kMaxVectorCount] {};
- ngtcp2_vec* buf = nullptr;
- BaseObjectPtr<QuicStream> stream;
- StreamData() { buf = data; }
- };
-
- void Acknowledge(
- int64_t stream_id,
- uint64_t offset,
- size_t datalen);
- virtual int GetStreamData(StreamData* data) = 0;
- virtual bool StreamCommit(StreamData* data, size_t datalen) = 0;
- virtual bool ShouldSetFin(const StreamData& data) = 0;
-
- ssize_t WriteVStream(
- QuicPathStorage* path,
- uint8_t* buf,
- ssize_t* ndatalen,
- const StreamData& stream_data);
-
- private:
- void MaybeSetFin(const StreamData& stream_data);
- BaseObjectWeakPtr<QuicSession> session_;
- bool needs_init_ = true;
- size_t max_header_pairs_ = 0;
- size_t max_header_length_ = 0;
-};
-
-// QUICSESSION_FLAGS are converted into is_{name}() and set_{name}(bool on)
-// accessors on the QuicSession class.
-#define QUICSESSION_FLAGS(V) \
- V(WRAPPED, wrapped) \
- V(CLOSING, closing) \
- V(GRACEFUL_CLOSING, graceful_closing) \
- V(DESTROYED, destroyed) \
- V(TRANSPORT_PARAMS_SET, transport_params_set) \
- V(NGTCP2_CALLBACK, in_ngtcp2_callback) \
- V(CONNECTION_CLOSE_SCOPE, in_connection_close_scope) \
- V(SILENT_CLOSE, silent_closing) \
- V(STATELESS_RESET, stateless_reset) \
- V(CLOSING_TIMER_ENABLED, closing_timer_enabled)
-
-// QUIC sessions are logical connections that exchange data
-// back and forth between peer endpoints via UDP. Every QuicSession
-// has an associated TLS context and all data transferred between
-// the peers is always encrypted. Unlike TLS over TCP, however,
-// The QuicSession uses a session identifier that is independent
-// of both the local *and* peer IP address, allowing a QuicSession
-// to persist across changes in the network (one of the key features
-// of QUIC). QUIC sessions also support 0RTT, implement error
-// correction mechanisms to recover from lost packets, and flow
-// control. In other words, there's quite a bit going on within
-// a QuicSession object.
-class QuicSession final : public AsyncWrap,
- public mem::NgLibMemoryManager<
- QuicSession,
- ngtcp2_mem>,
- public StatsBase<QuicSessionStatsTraits> {
- public:
- // The default preferred address strategy is to ignore it
- static void IgnorePreferredAddressStrategy(
- QuicSession* session,
- const PreferredAddress& preferred_address);
-
- static void UsePreferredAddressStrategy(
- QuicSession* session,
- const PreferredAddress& preferred_address);
-
- static void Initialize(
- Environment* env,
- v8::Local<v8::Object> target,
- v8::Local<v8::Context> context);
-
- static BaseObjectPtr<QuicSession> CreateServer(
- QuicSocket* socket,
- const QuicSessionConfig& config,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- const std::string& alpn = NGHTTP3_ALPN_H3,
- uint32_t options = 0,
- QlogMode qlog = QlogMode::kDisabled);
-
- static BaseObjectPtr<QuicSession> CreateClient(
- QuicSocket* socket,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- BaseObjectPtr<crypto::SecureContext> secure_context,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- v8::Local<v8::Value> dcid,
- PreferredAddressStrategy preferred_address_strategy =
- IgnorePreferredAddressStrategy,
- const std::string& alpn = NGHTTP3_ALPN_H3,
- const std::string& hostname = "",
- uint32_t options = 0,
- QlogMode qlog = QlogMode::kDisabled);
-
- static const int kInitialClientBufferLength = 4096;
-
- QuicSession(
- ngtcp2_crypto_side side,
- // The QuicSocket that created this session. Note that
- // it is possible to replace this socket later, after
- // the TLS handshake has completed. The QuicSession
- // should never assume that the socket will always
- // remain the same.
- QuicSocket* socket,
- v8::Local<v8::Object> wrap,
- BaseObjectPtr<crypto::SecureContext> secure_context,
- AsyncWrap::ProviderType provider_type,
- // QUIC is generally just a transport. The ALPN identifier
- // is used to specify the application protocol that is
- // layered on top. If not specified, this will default
- // to the HTTP/3 identifier. For QUIC, the alpn identifier
- // is always required.
- const std::string& alpn,
- const std::string& hostname,
- const QuicCID& dcid,
- uint32_t options = 0,
- PreferredAddressStrategy preferred_address_strategy =
- IgnorePreferredAddressStrategy);
-
- // Server Constructor
- QuicSession(
- QuicSocket* socket,
- const QuicSessionConfig& config,
- v8::Local<v8::Object> wrap,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- const std::string& alpn,
- uint32_t options,
- QlogMode qlog);
-
- // Client Constructor
- QuicSession(
- QuicSocket* socket,
- v8::Local<v8::Object> wrap,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- BaseObjectPtr<crypto::SecureContext> secure_context,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- v8::Local<v8::Value> dcid,
- PreferredAddressStrategy preferred_address_strategy,
- const std::string& alpn,
- const std::string& hostname,
- uint32_t options,
- QlogMode qlog);
-
- ~QuicSession() override;
-
- std::string diagnostic_name() const override;
-
- inline QuicCID dcid() const;
-
- QuicApplication* application() const { return application_.get(); }
-
- QuicCryptoContext* crypto_context() const { return crypto_context_.get(); }
-
- QuicSessionListener* listener() const { return listener_; }
-
- BaseObjectPtr<QuicStream> CreateStream(int64_t id);
-
- BaseObjectPtr<QuicStream> FindStream(int64_t id) const;
-
- inline bool HasStream(int64_t id) const;
-
- inline bool allow_early_data() const;
-
-#define V(id, name) \
- bool is_##name() const { return flags_ & (1 << QUICSESSION_FLAG_##id); } \
- void set_##name(bool on = true) { \
- if (on) \
- flags_ |= (1 << QUICSESSION_FLAG_##id); \
- else \
- flags_ &= ~(1 << QUICSESSION_FLAG_##id); \
- }
- QUICSESSION_FLAGS(V)
-#undef V
-
- // Returns true if the QuicSession has entered the
- // closing period after sending a CONNECTION_CLOSE.
- // While true, the QuicSession is only permitted to
- // transmit CONNECTION_CLOSE frames until either the
- // idle timeout period elapses or until the QuicSession
- // is explicitly destroyed.
- inline bool is_in_closing_period() const;
-
- // Returns true if the QuicSession has received a
- // CONNECTION_CLOSE frame from the peer. Once in
- // the draining period, the QuicSession is not
- // permitted to send any frames to the peer. The
- // QuicSession will be silently closed after either
- // the idle timeout period elapses or until the
- // QuicSession is explicitly destroyed.
- inline bool is_in_draining_period() const;
-
- inline bool is_server() const;
-
- // Starting a GracefulClose disables the ability to open or accept
- // new streams for this session. Existing streams are allowed to
- // close naturally on their own. Once called, the QuicSession will
- // be immediately closed once there are no remaining streams. Note
- // that no notification is given to the connecting peer that we're
- // in a graceful closing state. A CONNECTION_CLOSE will be sent only
- // once Close() is called.
- inline void StartGracefulClose();
-
- QuicError last_error() const { return last_error_; }
-
- size_t max_packet_length() const { return max_pktlen_; }
-
- BaseObjectPtr<QLogStream> qlog_stream();
-
- // Get the ALPN protocol identifier configured for this QuicSession.
- // For server sessions, this will be compared against the client requested
- // ALPN identifier to determine if there is a protocol match.
- const std::string& alpn() const { return alpn_; }
-
- // Get the hostname configured for this QuicSession. This is generally
- // only used by client sessions.
- const std::string& hostname() const { return hostname_; }
-
- // Returns the associated peer's address. Note that this
- // value can change over the lifetime of the QuicSession.
- // The fact that the session is not tied intrinsically to
- // a single address is one of the benefits of QUIC.
- const SocketAddress& remote_address() const { return remote_address_; }
-
- inline QuicSocket* socket() const;
-
- ngtcp2_conn* connection() const { return connection_.get(); }
-
- void AddStream(BaseObjectPtr<QuicStream> stream);
-
- void AddToSocket(QuicSocket* socket);
-
- // Immediately discards the state of the QuicSession
- // and renders the QuicSession instance completely
- // unusable.
- void Destroy();
-
- // Extends the QUIC stream flow control window. This is
- // called after received data has been consumed and we
- // want to allow the peer to send more data.
- inline void ExtendStreamOffset(int64_t stream_id, size_t amount);
-
- // Extends the QUIC session flow control window
- inline void ExtendOffset(size_t amount);
-
- // Retrieve the local transport parameters established for
- // this ngtcp2_conn
- inline void GetLocalTransportParams(ngtcp2_transport_params* params);
-
- // The QUIC version that has been negotiated for this session
- inline uint32_t negotiated_version() const;
-
- // True only if ngtcp2 considers the TLS handshake to be completed
- inline bool is_handshake_completed() const;
-
- // Checks to see if data needs to be retransmitted
- void OnRetransmitTimeout();
-
- // Called when the session has been determined to have been
- // idle for too long and needs to be torn down.
- inline void OnIdleTimeout();
-
- bool OpenBidirectionalStream(int64_t* stream_id);
-
- bool OpenUnidirectionalStream(int64_t* stream_id);
-
- // Ping causes the QuicSession to serialize any currently
- // pending frames in it's queue, including any necessary
- // PROBE packets. This is a best attempt, fire-and-forget
- // type of operation. There is no way to listen for a ping
- // response. The main intent of using Ping is to either keep
- // the connection from becoming idle or to update RTT stats.
- void Ping();
-
- // Receive and process a QUIC packet received from the peer
- bool Receive(
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags);
-
- // Receive a chunk of QUIC stream data received from the peer
- bool ReceiveStreamData(
- uint32_t flags,
- int64_t stream_id,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset);
-
- void RemoveStream(int64_t stream_id);
-
- void RemoveFromSocket();
-
- // Causes pending ngtcp2 frames to be serialized and sent
- void SendPendingData();
-
- inline void ShutdownStream(int64_t stream_id, uint64_t code);
-
- inline bool SendPacket(
- std::unique_ptr<QuicPacket> packet,
- const ngtcp2_path_storage& path);
-
- inline uint64_t max_data_left() const;
-
- inline uint64_t max_local_streams_uni() const;
-
- inline void set_last_error(
- QuicError error = {
- uint32_t{QUIC_ERROR_SESSION},
- uint64_t{NGTCP2_NO_ERROR}
- });
-
- inline void set_last_error(int32_t family, uint64_t error_code);
-
- inline void set_last_error(int32_t family, int error_code);
-
- inline void set_remote_transport_params();
-
- bool set_socket(QuicSocket* socket, bool nat_rebinding = false);
-
- int set_session(SSL_SESSION* session);
-
- const StreamsMap& streams() const { return streams_; }
-
- void ResumeStream(int64_t stream_id);
-
- // Submits informational headers to the QUIC Application
- // implementation. If headers are not supported, false
- // will be returned. Otherwise, returns true
- inline bool SubmitInformation(
- int64_t stream_id,
- v8::Local<v8::Array> headers);
-
- // Submits initial headers to the QUIC Application
- // implementation. If headers are not supported, false
- // will be returned. Otherwise, returns true
- inline bool SubmitHeaders(
- int64_t stream_id,
- v8::Local<v8::Array> headers,
- uint32_t flags);
-
- // Submits trailing headers to the QUIC Application
- // implementation. If headers are not supported, false
- // will be returned. Otherwise, returns true
- inline bool SubmitTrailers(
- int64_t stream_id,
- v8::Local<v8::Array> headers);
-
- inline BaseObjectPtr<QuicStream> SubmitPush(
- int64_t stream_id,
- v8::Local<v8::Array> headers);
-
- // Error handling for the QuicSession. client and server
- // instances will do different things here, but ultimately
- // an error means that the QuicSession
- // should be torn down.
- void HandleError();
-
- bool SendConnectionClose();
-
- bool IsResetToken(
- const QuicCID& cid,
- const uint8_t* data,
- size_t datalen);
-
- // Implementation for mem::NgLibMemoryManager
- inline void CheckAllocatedSize(size_t previous_size) const;
-
- inline void IncreaseAllocatedSize(size_t size);
-
- inline void DecreaseAllocatedSize(size_t size);
-
- // Initiate closing of the QuicSession. This will round trip
- // through JavaScript, causing all currently opened streams
- // to be closed. If the SESSION_CLOSE_FLAG_SILENT flag is
- // set, the connected peer will not be notified, otherwise
- // an attempt will be made to send a CONNECTION_CLOSE frame
- // to the peer. If Close is called while within the ngtcp2
- // callback scope, sending the CONNECTION_CLOSE will be
- // deferred until the ngtcp2 callback scope exits.
- void Close(
- int close_flags = QuicSessionListener::SESSION_CLOSE_FLAG_NONE);
-
- void PushListener(QuicSessionListener* listener);
-
- void RemoveListener(QuicSessionListener* listener);
-
- inline bool is_unable_to_send_packets();
-
- inline void set_connection_id_strategy(
- ConnectionIDStrategy strategy);
-
- inline void set_preferred_address_strategy(
- PreferredAddressStrategy strategy);
-
- inline void SetSessionTicketAppData(
- const SessionTicketAppData& app_data);
-
- inline SessionTicketAppData::Status GetSessionTicketAppData(
- const SessionTicketAppData& app_data,
- SessionTicketAppData::Flag flag);
-
- inline void SelectPreferredAddress(
- const PreferredAddress& preferred_address);
-
- // Report that the stream data is flow control blocked
- inline void StreamDataBlocked(int64_t stream_id);
-
- // SendSessionScope triggers SendPendingData() when not executing
- // within the context of an ngtcp2 callback. When within an ngtcp2
- // callback, SendPendingData will always be called when the callbacks
- // complete.
- class SendSessionScope final {
- public:
- explicit SendSessionScope(QuicSession* session)
- : session_(session) {
- CHECK(session_);
- }
-
- SendSessionScope(const SendSessionScope& other) = delete;
-
- ~SendSessionScope() {
- if (NgCallbackScope::InNgCallbackScope(session_.get()) ||
- session_->is_in_closing_period() ||
- session_->is_in_draining_period()) {
- return;
- }
- session_->SendPendingData();
- }
-
- private:
- BaseObjectPtr<QuicSession> session_;
- };
-
- // ConnectionCloseScope triggers sending a CONNECTION_CLOSE
- // when not executing within the context of an ngtcp2 callback
- // and the session is in the correct state.
- class ConnectionCloseScope final {
- public:
- ConnectionCloseScope(QuicSession* session, bool silent = false)
- : session_(session),
- silent_(silent) {
- CHECK(session_);
- // If we are already in a ConnectionCloseScope, ignore.
- if (session_->is_in_connection_close_scope())
- silent_ = true;
- else
- session_->set_in_connection_close_scope();
- }
-
- ConnectionCloseScope(const ConnectionCloseScope& other) = delete;
-
- ~ConnectionCloseScope() {
- if (silent_ ||
- NgCallbackScope::InNgCallbackScope(session_.get()) ||
- session_->is_in_closing_period() ||
- session_->is_in_draining_period()) {
- return;
- }
- session_->set_in_connection_close_scope(false);
- session_->SendConnectionClose();
- }
-
- private:
- BaseObjectPtr<QuicSession> session_;
- bool silent_ = false;
- };
-
- // Tracks whether or not we are currently within an ngtcp2 callback
- // function. Certain ngtcp2 APIs are not supposed to be called when
- // within a callback. We use this as a gate to check.
- class NgCallbackScope final {
- public:
- explicit NgCallbackScope(QuicSession* session) : session_(session) {
- CHECK(session_);
- CHECK(!InNgCallbackScope(session));
- session_->set_in_ngtcp2_callback();
- }
-
- NgCallbackScope(const NgCallbackScope& other) = delete;
-
- ~NgCallbackScope() {
- session_->set_in_ngtcp2_callback(false);
- }
-
- static bool InNgCallbackScope(QuicSession* session) {
- return session->is_in_ngtcp2_callback();
- }
-
- private:
- BaseObjectPtr<QuicSession> session_;
- };
-
- QuicState* quic_state() { return quic_state_.get(); }
-
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_MEMORY_INFO_NAME(QuicSession)
- SET_SELF_SIZE(QuicSession)
-
- private:
- static void RandomConnectionIDStrategy(
- QuicSession* session,
- ngtcp2_cid* cid,
- size_t cidlen);
-
- // Initialize the QuicSession as a server
- void InitServer(
- QuicSessionConfig config,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- const QuicCID& dcid,
- const QuicCID& scid,
- const QuicCID& ocid,
- uint32_t version,
- QlogMode qlog);
-
- // Initialize the QuicSession as a client
- void InitClient(
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- ngtcp2_transport_params* early_transport_params,
- crypto::SSLSessionPointer early_session_ticket,
- v8::Local<v8::Value> dcid,
- QlogMode qlog);
-
- bool InitApplication();
-
- void AckedStreamDataOffset(
- int64_t stream_id,
- uint64_t offset,
- uint64_t datalen);
-
- void ExtendMaxStreamData(int64_t stream_id, uint64_t max_data);
-
- void ExtendMaxStreams(bool bidi, uint64_t max_streams);
-
- void ExtendMaxStreamsUni(uint64_t max_streams);
-
- void ExtendMaxStreamsBidi(uint64_t max_streams);
-
- void ExtendMaxStreamsRemoteUni(uint64_t max_streams);
-
- void ExtendMaxStreamsRemoteBidi(uint64_t max_streams);
-
- void GetNewConnectionID(ngtcp2_cid* cid, uint8_t* token, size_t cidlen);
-
- void GetConnectionCloseInfo();
-
- void HandshakeCompleted();
-
- void HandshakeConfirmed();
-
- void PathValidation(
- const ngtcp2_path* path,
- ngtcp2_path_validation_result res);
-
- bool ReceivePacket(ngtcp2_path* path, const uint8_t* data, ssize_t nread);
-
- void ScheduleRetransmit();
-
- bool SendPacket(std::unique_ptr<QuicPacket> packet);
-
- void StreamClose(int64_t stream_id, uint64_t app_error_code);
-
- void StreamReset(
- int64_t stream_id,
- uint64_t final_size,
- uint64_t app_error_code);
-
- bool WritePackets(const char* diagnostic_label = nullptr);
-
- void UpdateConnectionID(
- int type,
- const QuicCID& cid,
- const StatelessResetToken& token);
-
- void UpdateDataStats();
-
- void UpdateEndpoint(const ngtcp2_path& path);
-
- void VersionNegotiation(const uint32_t* sv, size_t nsv);
-
- void UpdateIdleTimer();
-
- void UpdateClosingTimer();
-
- void UpdateRetransmitTimer(uint64_t timeout);
-
- bool StartClosingPeriod();
-
- void IncrementConnectionCloseAttempts();
-
- bool ShouldAttemptConnectionClose();
-
- static int OnReceiveCryptoData(
- ngtcp2_conn* conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen,
- void* user_data);
-
- static int OnHandshakeCompleted(
- ngtcp2_conn* conn,
- void* user_data);
-
- static int OnHandshakeConfirmed(
- ngtcp2_conn* conn,
- void* user_data);
-
- static int OnReceiveStreamData(
- ngtcp2_conn* conn,
- uint32_t flags,
- int64_t stream_id,
- uint64_t offset,
- const uint8_t* data,
- size_t datalen,
- void* user_data,
- void* stream_user_data);
-
- static int OnAckedCryptoOffset(
- ngtcp2_conn* conn,
- ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- uint64_t datalen,
- void* user_data);
-
- static int OnAckedStreamDataOffset(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t offset,
- uint64_t datalen,
- void* user_data,
- void* stream_user_data);
-
- static int OnSelectPreferredAddress(
- ngtcp2_conn* conn,
- ngtcp2_addr* dest,
- const ngtcp2_preferred_addr* paddr,
- void* user_data);
-
- static int OnStreamClose(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t app_error_code,
- void* user_data,
- void* stream_user_data);
-
- static int OnStreamOpen(
- ngtcp2_conn* conn,
- int64_t stream_id,
- void* user_data);
-
- static int OnStreamReset(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t final_size,
- uint64_t app_error_code,
- void* user_data,
- void* stream_user_data);
-
- static int OnRand(
- uint8_t* dest,
- size_t destlen,
- ngtcp2_rand_ctx ctx);
-
- static int OnGetNewConnectionID(
- ngtcp2_conn* conn,
- ngtcp2_cid* cid,
- uint8_t* token,
- size_t cidlen,
- void* user_data);
-
- static int OnRemoveConnectionID(
- ngtcp2_conn* conn,
- const ngtcp2_cid* cid,
- void* user_data);
-
- static int OnPathValidation(
- ngtcp2_conn* conn,
- const ngtcp2_path* path,
- ngtcp2_path_validation_result res,
- void* user_data);
-
- static int OnExtendMaxStreamsUni(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data);
-
- static int OnExtendMaxStreamsBidi(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data);
-
- static int OnExtendMaxStreamData(
- ngtcp2_conn* conn,
- int64_t stream_id,
- uint64_t max_data,
- void* user_data,
- void* stream_user_data);
-
- static int OnVersionNegotiation(
- ngtcp2_conn* conn,
- const ngtcp2_pkt_hd* hd,
- const uint32_t* sv,
- size_t nsv,
- void* user_data);
-
- static int OnStatelessReset(
- ngtcp2_conn* conn,
- const ngtcp2_pkt_stateless_reset* sr,
- void* user_data);
-
- static int OnExtendMaxStreamsRemoteUni(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data);
-
- static int OnExtendMaxStreamsRemoteBidi(
- ngtcp2_conn* conn,
- uint64_t max_streams,
- void* user_data);
-
- static int OnConnectionIDStatus(
- ngtcp2_conn* conn,
- int type,
- uint64_t seq,
- const ngtcp2_cid* cid,
- const uint8_t* token,
- void* user_data);
-
- static void OnQlogWrite(
- void* user_data,
- uint32_t flags,
- const void* data,
- size_t len);
-
-#define V(id, _) QUICSESSION_FLAG_##id,
- enum QuicSessionFlags : uint32_t {
- QUICSESSION_FLAGS(V)
- QUICSESSION_FLAG_COUNT
- };
-#undef V
-
- // Select the QUIC Application based on the configured ALPN identifier
- QuicApplication* SelectApplication(QuicSession* session);
-
- ngtcp2_mem alloc_info_;
- std::unique_ptr<QuicCryptoContext> crypto_context_;
- std::unique_ptr<QuicApplication> application_;
- BaseObjectWeakPtr<QuicSocket> socket_;
- std::string alpn_;
- std::string hostname_;
- QuicError last_error_ = {
- uint32_t{QUIC_ERROR_SESSION},
- uint64_t{NGTCP2_NO_ERROR}
- };
- ConnectionPointer connection_;
- SocketAddress local_address_{};
- SocketAddress remote_address_{};
- uint32_t flags_ = 0;
- size_t max_pktlen_ = 0;
- size_t current_ngtcp2_memory_ = 0;
- size_t connection_close_attempts_ = 0;
- size_t connection_close_limit_ = 1;
-
- ConnectionIDStrategy connection_id_strategy_ = nullptr;
- PreferredAddressStrategy preferred_address_strategy_ = nullptr;
-
- QuicSessionListener* listener_ = nullptr;
- JSQuicSessionListener default_listener_;
-
- TimerWrapHandle idle_;
- TimerWrapHandle retransmit_;
-
- QuicCID scid_;
- QuicCID dcid_;
- QuicCID pscid_;
- ngtcp2_transport_params transport_params_;
-
- std::unique_ptr<QuicPacket> conn_closebuf_;
-
- StreamsMap streams_;
-
- AliasedStruct<QuicSessionState> state_;
-
- struct RemoteTransportParamsDebug {
- QuicSession* session;
- explicit RemoteTransportParamsDebug(QuicSession* session_)
- : session(session_) {}
- std::string ToString() const;
- };
-
- static const ngtcp2_conn_callbacks callbacks[2];
-
- BaseObjectPtr<QuicState> quic_state_;
- BaseObjectWeakPtr<QLogStream> qlog_stream_;
-
- friend class QuicCryptoContext;
- friend class QuicSessionListener;
- friend class JSQuicSessionListener;
-};
-
-class QuicCallbackScope {
- public:
- explicit QuicCallbackScope(QuicSession* session);
- ~QuicCallbackScope();
-
- void operator=(const QuicCallbackScope&) = delete;
- void operator=(QuicCallbackScope&&) = delete;
- QuicCallbackScope(const QuicCallbackScope&) = delete;
- QuicCallbackScope(QuicCallbackScope&&) = delete;
-
- private:
- BaseObjectPtr<QuicSession> session_;
- std::unique_ptr<InternalCallbackScope> private_;
- v8::TryCatch try_catch_;
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-#endif // SRC_QUIC_NODE_QUIC_SESSION_H_
diff --git a/src/quic/node_quic_socket-inl.h b/src/quic/node_quic_socket-inl.h
deleted file mode 100644
index 8e7bc65d78..0000000000
--- a/src/quic/node_quic_socket-inl.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_SOCKET_INL_H_
-#define SRC_QUIC_NODE_QUIC_SOCKET_INL_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node_quic_socket.h"
-#include "node_sockaddr-inl.h"
-#include "node_quic_session.h"
-#include "node_crypto.h"
-#include "debug_utils-inl.h"
-
-namespace node {
-
-using crypto::EntropySource;
-
-namespace quic {
-
-std::unique_ptr<QuicPacket> QuicPacket::Create(
- const char* diagnostic_label,
- size_t len) {
- CHECK_LE(len, MAX_PKTLEN);
- return std::make_unique<QuicPacket>(diagnostic_label, len);
-}
-
-std::unique_ptr<QuicPacket> QuicPacket::Copy(
- const std::unique_ptr<QuicPacket>& other) {
- return std::make_unique<QuicPacket>(*other.get());
-}
-
-void QuicPacket::set_length(size_t len) {
- CHECK_LE(len, MAX_PKTLEN);
- len_ = len;
-}
-
-int QuicEndpoint::Send(
- uv_buf_t* buf,
- size_t len,
- const sockaddr* addr) {
- int ret = static_cast<int>(udp_->Send(buf, len, addr));
- if (ret == 0)
- IncrementPendingCallbacks();
- return ret;
-}
-
-int QuicEndpoint::ReceiveStart() {
- return udp_->RecvStart();
-}
-
-int QuicEndpoint::ReceiveStop() {
- return udp_->RecvStop();
-}
-
-void QuicEndpoint::WaitForPendingCallbacks() {
- if (!has_pending_callbacks()) {
- listener_->OnEndpointDone(this);
- return;
- }
- waiting_for_callbacks_ = true;
-}
-
-void QuicSocket::AssociateCID(
- const QuicCID& cid,
- const QuicCID& scid) {
- if (cid && scid)
- dcid_to_scid_[cid] = scid;
-}
-
-void QuicSocket::DisassociateCID(const QuicCID& cid) {
- if (cid) {
- Debug(this, "Removing association for cid %s", cid);
- dcid_to_scid_.erase(cid);
- }
-}
-
-void QuicSocket::AssociateStatelessResetToken(
- const StatelessResetToken& token,
- BaseObjectPtr<QuicSession> session) {
- Debug(this, "Associating stateless reset token %s", token);
- token_map_[token] = session;
-}
-
-SocketAddress QuicSocket::local_address() const {
- DCHECK(preferred_endpoint_);
- return preferred_endpoint_->local_address();
-}
-
-void QuicSocket::DisassociateStatelessResetToken(
- const StatelessResetToken& token) {
- Debug(this, "Removing stateless reset token %s", token);
- token_map_.erase(token);
-}
-
-void QuicSocket::ReceiveStart() {
- for (const auto& endpoint : endpoints_)
- CHECK_EQ(endpoint->ReceiveStart(), 0);
-}
-
-void QuicSocket::ReceiveStop() {
- for (const auto& endpoint : endpoints_)
- CHECK_EQ(endpoint->ReceiveStop(), 0);
-}
-
-void QuicSocket::RemoveSession(
- const QuicCID& cid,
- const SocketAddress& addr) {
- DecrementSocketAddressCounter(addr);
- sessions_.erase(cid);
-}
-
-void QuicSocket::ReportSendError(int error) {
- listener_->OnError(error);
-}
-
-void QuicSocket::IncrementStatelessResetCounter(const SocketAddress& addr) {
- addrLRU_.Upsert(addr)->reset_count++;
-}
-
-void QuicSocket::IncrementSocketAddressCounter(const SocketAddress& addr) {
- addrLRU_.Upsert(addr)->active_connections++;
-}
-
-void QuicSocket::DecrementSocketAddressCounter(const SocketAddress& addr) {
- SocketAddressInfo* counts = addrLRU_.Peek(addr);
- if (counts != nullptr && counts->active_connections > 0)
- counts->active_connections--;
-}
-
-size_t QuicSocket::GetCurrentSocketAddressCounter(const SocketAddress& addr) {
- SocketAddressInfo* counts = addrLRU_.Peek(addr);
- return counts != nullptr ? counts->active_connections : 0;
-}
-
-size_t QuicSocket::GetCurrentStatelessResetCounter(const SocketAddress& addr) {
- SocketAddressInfo* counts = addrLRU_.Peek(addr);
- return counts != nullptr ? counts->reset_count : 0;
-}
-
-void QuicSocket::ServerBusy(bool on) {
- Debug(this, "Turning Server Busy Response %s", on ? "on" : "off");
- state_->server_busy = on ? 1 : 0;
- listener_->OnServerBusy();
-}
-
-bool QuicSocket::is_diagnostic_packet_loss(double prob) const {
- if (LIKELY(prob == 0.0)) return false;
- unsigned char c = 255;
- EntropySource(&c, 1);
- return (static_cast<double>(c) / 255) < prob;
-}
-
-void QuicSocket::set_diagnostic_packet_loss(double rx, double tx) {
- rx_loss_ = rx;
- tx_loss_ = tx;
-}
-
-void QuicSocket::set_validated_address(const SocketAddress& addr) {
- addrLRU_.Upsert(addr)->validated = true;
-}
-
-bool QuicSocket::is_validated_address(const SocketAddress& addr) const {
- auto info = addrLRU_.Peek(addr);
- return info != nullptr ? info->validated : false;
-}
-
-void QuicSocket::AddSession(
- const QuicCID& cid,
- BaseObjectPtr<QuicSession> session) {
- sessions_[cid] = session;
- IncrementSocketAddressCounter(session->remote_address());
- IncrementStat(
- session->is_server() ?
- &QuicSocketStats::server_sessions :
- &QuicSocketStats::client_sessions);
-}
-
-void QuicSocket::AddEndpoint(
- BaseObjectPtr<QuicEndpoint> endpoint_,
- bool preferred) {
- Debug(this, "Adding %sendpoint", preferred ? "preferred " : "");
- if (preferred || endpoints_.empty())
- preferred_endpoint_ = endpoint_;
- endpoints_.emplace_back(endpoint_);
- if (state_->server_listening)
- endpoint_->ReceiveStart();
-}
-
-} // namespace quic
-} // namespace node
-
-#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_SOCKET_INL_H_
diff --git a/src/quic/node_quic_socket.cc b/src/quic/node_quic_socket.cc
deleted file mode 100644
index 810705014c..0000000000
--- a/src/quic/node_quic_socket.cc
+++ /dev/null
@@ -1,1202 +0,0 @@
-#include "node_quic_socket-inl.h" // NOLINT(build/include)
-#include "aliased_struct-inl.h"
-#include "allocated_buffer-inl.h"
-#include "async_wrap-inl.h"
-#include "debug_utils-inl.h"
-#include "env-inl.h"
-#include "memory_tracker-inl.h"
-#include "nghttp2/nghttp2.h"
-#include "nghttp3/nghttp3.h"
-#include "node.h"
-#include "node_buffer.h"
-#include "node_crypto.h"
-#include "node_internals.h"
-#include "node_mem-inl.h"
-#include "node_quic_crypto.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include "req_wrap-inl.h"
-#include "util.h"
-#include "uv.h"
-#include "v8.h"
-
-#include <random>
-
-namespace node {
-
-using crypto::EntropySource;
-using crypto::SecureContext;
-
-using v8::ArrayBufferView;
-using v8::Context;
-using v8::FunctionCallbackInfo;
-using v8::FunctionTemplate;
-using v8::HandleScope;
-using v8::Isolate;
-using v8::Local;
-using v8::Number;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::PropertyAttribute;
-using v8::Value;
-
-namespace quic {
-
-namespace {
-// The reserved version is a mechanism QUIC endpoints
-// can use to ensure correct handling of version
-// negotiation. It is defined by the QUIC spec in
-// https://tools.ietf.org/html/draft-ietf-quic-transport-24#section-6.3
-// Specifically, any version that follows the pattern
-// 0x?a?a?a?a may be used to force version negotiation.
-inline uint32_t GenerateReservedVersion(
- const SocketAddress& addr,
- uint32_t version) {
- socklen_t addrlen = addr.length();
- uint32_t h = 0x811C9DC5u;
- const uint8_t* p = addr.raw();
- const uint8_t* ep = p + addrlen;
- for (; p != ep; ++p) {
- h ^= *p;
- h *= 0x01000193u;
- }
- version = htonl(version);
- p = reinterpret_cast<const uint8_t*>(&version);
- ep = p + sizeof(version);
- for (; p != ep; ++p) {
- h ^= *p;
- h *= 0x01000193u;
- }
- h &= 0xf0f0f0f0u;
- h |= 0x0a0a0a0au;
- return h;
-}
-
-bool IsShortHeader(
- uint32_t version,
- const uint8_t* pscid,
- size_t pscidlen) {
- return version == NGTCP2_PROTO_VER &&
- pscid == nullptr &&
- pscidlen == 0;
-}
-} // namespace
-
-QuicPacket::QuicPacket(const char* diagnostic_label, size_t len)
- : data_{0},
- len_(len),
- diagnostic_label_(diagnostic_label) {
- CHECK_LE(len, MAX_PKTLEN);
-}
-
-QuicPacket::QuicPacket(const QuicPacket& other) :
- QuicPacket(other.diagnostic_label_, other.len_) {
- memcpy(&data_, &other.data_, other.len_);
-}
-
-const char* QuicPacket::diagnostic_label() const {
- return diagnostic_label_ != nullptr ?
- diagnostic_label_ : "unspecified";
-}
-
-QuicSocketListener::~QuicSocketListener() {
- if (socket_)
- socket_->RemoveListener(this);
-}
-
-void QuicSocketListener::OnError(ssize_t code) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnError(code);
-}
-
-void QuicSocketListener::OnSessionReady(BaseObjectPtr<QuicSession> session) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnSessionReady(session);
-}
-
-void QuicSocketListener::OnServerBusy() {
- if (previous_listener_ != nullptr)
- previous_listener_->OnServerBusy();
-}
-
-void QuicSocketListener::OnEndpointDone(QuicEndpoint* endpoint) {
- if (previous_listener_ != nullptr)
- previous_listener_->OnEndpointDone(endpoint);
-}
-
-void QuicSocketListener::OnDestroy() {
- if (previous_listener_ != nullptr)
- previous_listener_->OnDestroy();
-}
-
-void JSQuicSocketListener::OnError(ssize_t code) {
- Environment* env = socket()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
- Local<Value> arg = Number::New(env->isolate(), static_cast<double>(code));
- socket()->MakeCallback(env->quic_on_socket_close_function(), 1, &arg);
-}
-
-void JSQuicSocketListener::OnSessionReady(BaseObjectPtr<QuicSession> session) {
- Environment* env = socket()->env();
- Local<Value> arg = session->object();
- Context::Scope context_scope(env->context());
- socket()->MakeCallback(env->quic_on_session_ready_function(), 1, &arg);
-}
-
-void JSQuicSocketListener::OnServerBusy() {
- Environment* env = socket()->env();
- HandleScope handle_scope(env->isolate());
- Context::Scope context_scope(env->context());
- socket()->MakeCallback(
- env->quic_on_socket_server_busy_function(), 0, nullptr);
-}
-
-void JSQuicSocketListener::OnEndpointDone(QuicEndpoint* endpoint) {
- Environment* env = socket()->env();
- HandleScope scope(env->isolate());
- Context::Scope context_scope(env->context());
- MakeCallback(
- env->isolate(),
- endpoint->object(),
- env->ondone_string(),
- 0, nullptr);
-}
-
-void JSQuicSocketListener::OnDestroy() {
- // Do nothing here.
-}
-
-QuicEndpoint::QuicEndpoint(
- QuicState* quic_state,
- Local<Object> wrap,
- QuicSocket* listener,
- Local<Object> udp_wrap)
- : BaseObject(quic_state->env(), wrap),
- listener_(listener),
- quic_state_(quic_state) {
- MakeWeak();
- udp_ = static_cast<UDPWrapBase*>(
- udp_wrap->GetAlignedPointerFromInternalField(
- UDPWrapBase::kUDPWrapBaseField));
- CHECK_NOT_NULL(udp_);
- udp_->set_listener(this);
- strong_ptr_.reset(udp_->GetAsyncWrap());
-}
-
-QuicEndpoint::~QuicEndpoint() {
- udp_->set_listener(nullptr);
-}
-
-uv_buf_t QuicEndpoint::OnAlloc(size_t suggested_size) {
- return AllocatedBuffer::AllocateManaged(env(), suggested_size).release();
-}
-
-void QuicEndpoint::OnRecv(
- ssize_t nread,
- const uv_buf_t& buf_,
- const sockaddr* addr,
- unsigned int flags) {
- AllocatedBuffer buf(env(), buf_);
-
- if (nread <= 0) {
- if (nread < 0)
- listener_->OnError(this, nread);
- return;
- }
-
- listener_->OnReceive(
- nread,
- std::move(buf),
- local_address(),
- SocketAddress(addr),
- flags);
-}
-
-ReqWrap<uv_udp_send_t>* QuicEndpoint::CreateSendWrap(size_t msg_size) {
- return listener_->OnCreateSendWrap(msg_size);
-}
-
-void QuicEndpoint::OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) {
- DecrementPendingCallbacks();
- listener_->OnSendDone(wrap, status);
- if (!has_pending_callbacks() && waiting_for_callbacks_)
- listener_->OnEndpointDone(this);
-}
-
-void QuicEndpoint::OnAfterBind() {
- listener_->OnBind(this);
-}
-
-template <typename Fn>
-void QuicSocketStatsTraits::ToString(const QuicSocket& ptr, Fn&& add_field) {
-#define V(_n, name, label) \
- add_field(label, ptr.GetStat(&QuicSocketStats::name));
- SOCKET_STATS(V)
-#undef V
-}
-
-QuicSocket::QuicSocket(
- QuicState* quic_state,
- Local<Object> wrap,
- uint64_t retry_token_expiration,
- size_t max_connections,
- size_t max_connections_per_host,
- size_t max_stateless_resets_per_host,
- uint32_t options,
- QlogMode qlog,
- const uint8_t* session_reset_secret,
- bool disable_stateless_reset)
- : AsyncWrap(quic_state->env(), wrap, AsyncWrap::PROVIDER_QUICSOCKET),
- StatsBase(quic_state->env(), wrap),
- alloc_info_(MakeAllocator()),
- block_list_(SocketAddressBlockListWrap::New(quic_state->env())),
- options_(options),
- state_(quic_state->env()->isolate()),
- max_connections_(max_connections),
- max_connections_per_host_(max_connections_per_host),
- max_stateless_resets_per_host_(max_stateless_resets_per_host),
- retry_token_expiration_(retry_token_expiration),
- qlog_(qlog),
- server_alpn_(NGHTTP3_ALPN_H3),
- addrLRU_(DEFAULT_MAX_SOCKETADDRESS_LRU_SIZE),
- quic_state_(quic_state) {
- MakeWeak();
- PushListener(&default_listener_);
-
- Debug(this, "New QuicSocket created");
-
- EntropySource(token_secret_, kTokenSecretLen);
-
- wrap->DefineOwnProperty(
- env()->context(),
- env()->block_list_string(),
- block_list_->object(),
- PropertyAttribute::ReadOnly).Check();
-
- wrap->DefineOwnProperty(
- env()->context(),
- env()->state_string(),
- state_.GetArrayBuffer(),
- PropertyAttribute::ReadOnly).Check();
-
- if (disable_stateless_reset)
- state_->stateless_reset_disabled = 1;
-
- // Set the session reset secret to the one provided or random.
- // Note that a random secret is going to make it exceedingly
- // difficult for the session reset token to be useful.
- if (session_reset_secret != nullptr) {
- memcpy(reset_token_secret_,
- session_reset_secret,
- NGTCP2_STATELESS_RESET_TOKENLEN);
- } else {
- EntropySource(reset_token_secret_, NGTCP2_STATELESS_RESET_TOKENLEN);
- }
-}
-
-QuicSocket::~QuicSocket() {
- QuicSocketListener* listener = listener_;
- listener_->OnDestroy();
- if (listener == listener_)
- RemoveListener(listener_);
-
- // In a clean shutdown, all QuicSessions associated with the QuicSocket
- // would have been destroyed explicitly. However, if the QuicSocket is
- // garbage collected / freed before Destroy having been called, there
- // may be sessions remaining. This is not really a good thing.
- Debug(this, "Destroying with %d sessions remaining", sessions_.size());
-
- DebugStats();
-}
-
-void QuicSocket::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("endpoints", endpoints_);
- tracker->TrackField("sessions", sessions_);
- tracker->TrackField("dcid_to_scid", dcid_to_scid_);
- tracker->TrackField("address_counts", addrLRU_);
- tracker->TrackField("token_map", token_map_);
- StatsBase::StatsMemoryInfo(tracker);
- tracker->TrackFieldWithSize(
- "current_ngtcp2_memory",
- current_ngtcp2_memory_);
-}
-
-void QuicSocket::Listen(
- BaseObjectPtr<SecureContext> sc,
- const sockaddr* preferred_address,
- const std::string& alpn,
- uint32_t options) {
- CHECK(sc);
- CHECK_NE(state_->server_listening, 1);
- Debug(this, "Starting to listen");
- server_session_config_.Set(quic_state(), preferred_address);
- server_secure_context_ = sc;
- server_alpn_ = alpn;
- server_options_ = options;
- state_->server_listening = 1;
- RecordTimestamp(&QuicSocketStats::listen_at);
- ReceiveStart();
-}
-
-void QuicSocket::OnError(QuicEndpoint* endpoint, ssize_t error) {
- // TODO(@jasnell): What should we do with the endpoint?
- Debug(this, "Reading data from UDP socket failed. Error %" PRId64, error);
- listener_->OnError(error);
-}
-
-ReqWrap<uv_udp_send_t>* QuicSocket::OnCreateSendWrap(size_t msg_size) {
- HandleScope handle_scope(env()->isolate());
- Local<Object> obj;
- if (!env()->quicsocketsendwrap_instance_template()
- ->NewInstance(env()->context()).ToLocal(&obj)) return nullptr;
- return last_created_send_wrap_ = new SendWrap(quic_state(), obj, msg_size);
-}
-
-void QuicSocket::OnEndpointDone(QuicEndpoint* endpoint) {
- Debug(this, "Endpoint has no pending callbacks");
- listener_->OnEndpointDone(endpoint);
-}
-
-void QuicSocket::OnBind(QuicEndpoint* endpoint) {
- SocketAddress local_address = endpoint->local_address();
- bound_endpoints_[local_address] =
- BaseObjectWeakPtr<QuicEndpoint>(endpoint);
- Debug(this, "Endpoint %s bound", local_address);
- RecordTimestamp(&QuicSocketStats::bound_at);
-}
-
-BaseObjectPtr<QuicSession> QuicSocket::FindSession(const QuicCID& cid) {
- BaseObjectPtr<QuicSession> session;
- auto session_it = sessions_.find(cid);
- if (session_it == std::end(sessions_)) {
- auto scid_it = dcid_to_scid_.find(cid);
- if (scid_it != std::end(dcid_to_scid_)) {
- session_it = sessions_.find(scid_it->second);
- CHECK_NE(session_it, std::end(sessions_));
- session = session_it->second;
- }
- } else {
- session = session_it->second;
- }
- return session;
-}
-
-// When a received packet contains a QUIC short header but cannot be
-// matched to a known QuicSession, it is either (a) garbage,
-// (b) a valid packet for a connection we no longer have state
-// for, or (c) a stateless reset. Because we do not yet know if
-// we are going to process the packet, we need to try to quickly
-// determine -- with as little cost as possible -- whether the
-// packet contains a reset token. We do so by checking the final
-// NGTCP2_STATELESS_RESET_TOKENLEN bytes in the packet to see if
-// they match one of the known reset tokens previously given by
-// the remote peer. If there's a match, then it's a reset token,
-// if not, we move on the to the next check. It is very important
-// that this check be as inexpensive as possible to avoid a DOS
-// vector.
-bool QuicSocket::MaybeStatelessReset(
- const QuicCID& dcid,
- const QuicCID& scid,
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) {
- if (UNLIKELY(state_->stateless_reset_disabled || nread < 16))
- return false;
- StatelessResetToken possible_token(
- data + nread - NGTCP2_STATELESS_RESET_TOKENLEN);
- Debug(this, "Possible stateless reset token: %s", possible_token);
- auto it = token_map_.find(possible_token);
- if (it == token_map_.end())
- return false;
- Debug(this, "Received a stateless reset token %s", possible_token);
- return it->second->Receive(nread, data, local_addr, remote_addr, flags);
-}
-
-// When a packet is received here, we do not yet know if we can
-// process it successfully as a QUIC packet or not. Given the
-// nature of UDP, we may receive a great deal of garbage here
-// so it is extremely important not to commit resources until
-// we're certain we can process the data we received as QUIC
-// packet.
-// Any packet we choose not to process must be ignored.
-void QuicSocket::OnReceive(
- ssize_t nread,
- AllocatedBuffer buf,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) {
- Debug(this, "Receiving %d bytes from the UDP socket", nread);
-
- // When diagnostic packet loss is enabled, the packet will be randomly
- // dropped based on the rx_loss_ probability.
- if (UNLIKELY(is_diagnostic_packet_loss(rx_loss_))) {
- Debug(this, "Simulating received packet loss");
- return;
- }
-
- if (UNLIKELY(block_list_->Apply(remote_addr))) {
- Debug(this, "Ignoring blocked remote address: %s", remote_addr);
- IncrementStat(&QuicSocketStats::packets_ignored);
- return;
- }
-
- IncrementStat(&QuicSocketStats::bytes_received, nread);
-
- const uint8_t* data = reinterpret_cast<const uint8_t*>(buf.data());
-
- uint32_t pversion;
- const uint8_t* pdcid;
- size_t pdcidlen;
- const uint8_t* pscid;
- size_t pscidlen;
-
- // This is our first check to see if the received data can be
- // processed as a QUIC packet. If this fails, then the QUIC packet
- // header is invalid and cannot be processed; all we can do is ignore
- // it. It's questionable whether we should even increment the
- // packets_ignored statistic here but for now we do. If it succeeds,
- // we have a valid QUIC header but there's still no guarantee that
- // the packet can be successfully processed.
- if (ngtcp2_pkt_decode_version_cid(
- &pversion,
- &pdcid,
- &pdcidlen,
- &pscid,
- &pscidlen,
- data, nread, kScidLen) < 0) {
- IncrementStat(&QuicSocketStats::packets_ignored);
- return;
- }
-
- // QUIC currently requires CID lengths of max NGTCP2_MAX_CIDLEN. The
- // ngtcp2 API allows non-standard lengths, and we may want to allow
- // non-standard lengths later. But for now, we're going to ignore any
- // packet with a non-standard CID length.
- if (pdcidlen > NGTCP2_MAX_CIDLEN || pscidlen > NGTCP2_MAX_CIDLEN) {
- IncrementStat(&QuicSocketStats::packets_ignored);
- return;
- }
-
- QuicCID dcid(pdcid, pdcidlen);
- QuicCID scid(pscid, pscidlen);
-
- Debug(this, "Received a QUIC packet for dcid %s", dcid);
-
- BaseObjectPtr<QuicSession> session = FindSession(dcid);
-
- // If a session is not found, there are four possible reasons:
- // 1. The session has not been created yet
- // 2. The session existed once but we've lost the local state for it
- // 3. The packet is a stateless reset sent by the peer
- // 4. This is a malicious or malformed packet.
- if (!session) {
- Debug(this, "There is no existing session for dcid %s", dcid);
- bool is_short_header = IsShortHeader(pversion, pscid, pscidlen);
-
- // Handle possible reception of a stateless reset token...
- // If it is a stateless reset, the packet will be handled with
- // no additional action necessary here. We want to return immediately
- // without committing any further resources.
- if (is_short_header &&
- MaybeStatelessReset(
- dcid,
- scid,
- nread,
- data,
- local_addr,
- remote_addr,
- flags)) {
- Debug(this, "Handled stateless reset");
- return;
- }
-
- // AcceptInitialPacket will first validate that the packet can be
- // accepted, then create a new server QuicSession instance if able
- // to do so. If a new instance cannot be created (for any reason),
- // the session BaseObjectPtr will be empty on return.
- session = AcceptInitialPacket(
- pversion,
- dcid,
- scid,
- nread,
- data,
- local_addr,
- remote_addr,
- flags);
-
- // There are many reasons why a server QuicSession could not be
- // created. The most common will be invalid packets or incorrect
- // QUIC version. In any of these cases, however, to prevent a
- // potential attacker from causing us to consume resources,
- // we're just going to ignore the packet. It is possible that
- // the AcceptInitialPacket sent a version negotiation packet,
- // or a CONNECTION_CLOSE packet.
- if (!session) {
- Debug(this, "Unable to create a new server QuicSession");
- // If the packet contained a short header, we might need to send
- // a stateless reset. The stateless reset contains a token derived
- // from the received destination connection ID.
- //
- // TODO(@jasnell): Stateless resets are generated programmatically
- // using HKDF with the sender provided dcid and a locally provided
- // secret as input. It is entirely possible that a malicious
- // peer could send multiple stateless reset eliciting packets
- // with the specific intent of using the returned stateless
- // reset to guess the stateless reset token secret used by
- // the server. Once guessed, the malicious peer could use
- // that secret as a DOS vector against other peers. We currently
- // implement some mitigations for this by limiting the number
- // of stateless resets that can be sent to a specific remote
- // address but there are other possible mitigations, such as
- // including the remote address as input in the generation of
- // the stateless token.
- if (is_short_header &&
- SendStatelessReset(dcid, local_addr, remote_addr, nread)) {
- Debug(this, "Sent stateless reset");
- IncrementStat(&QuicSocketStats::stateless_reset_count);
- return;
- }
- IncrementStat(&QuicSocketStats::packets_ignored);
- return;
- }
- }
-
- CHECK(session);
- // If the QuicSession is already destroyed, there's nothing to do.
- if (session->is_destroyed())
- return IncrementStat(&QuicSocketStats::packets_ignored);
-
- // If the packet could not successfully processed for any reason (possibly
- // due to being malformed or malicious in some way) we mark it ignored.
- if (!session->Receive(nread, data, local_addr, remote_addr, flags)) {
- IncrementStat(&QuicSocketStats::packets_ignored);
- return;
- }
-
- IncrementStat(&QuicSocketStats::packets_received);
-}
-
-// Generates and sends a version negotiation packet. This is
-// terminal for the connection and is sent only when a QUIC
-// packet is received for an unsupported Node.js version.
-// It is possible that a malicious packet triggered this
-// so we need to be careful not to commit too many resources.
-// Currently, we only support one QUIC version at a time.
-void QuicSocket::SendVersionNegotiation(
- uint32_t version,
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr) {
- uint32_t sv[2];
- sv[0] = GenerateReservedVersion(remote_addr, version);
- sv[1] = NGTCP2_PROTO_VER;
-
- uint8_t unused_random;
- EntropySource(&unused_random, 1);
-
- size_t pktlen = dcid.length() + scid.length() + (sizeof(sv)) + 7;
-
- auto packet = QuicPacket::Create("version negotiation", pktlen);
- ssize_t nwrite = ngtcp2_pkt_write_version_negotiation(
- packet->data(),
- NGTCP2_MAX_PKTLEN_IPV6,
- unused_random,
- dcid.data(),
- dcid.length(),
- scid.data(),
- scid.length(),
- sv,
- arraysize(sv));
- if (nwrite <= 0)
- return;
- packet->set_length(nwrite);
- SocketAddress remote_address(remote_addr);
- SendPacket(local_addr, remote_address, std::move(packet));
-}
-
-// Possible generates and sends a stateless reset packet.
-// This is terminal for the connection. It is possible
-// that a malicious packet triggered this so we need to
-// be careful not to commit too many resources.
-bool QuicSocket::SendStatelessReset(
- const QuicCID& cid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- size_t source_len) {
- if (UNLIKELY(state_->stateless_reset_disabled))
- return false;
- constexpr static size_t kRandlen = NGTCP2_MIN_STATELESS_RESET_RANDLEN * 5;
- constexpr static size_t kMinStatelessResetLen = 41;
- uint8_t random[kRandlen];
-
- // Per the QUIC spec, we need to protect against sending too
- // many stateless reset tokens to an endpoint to prevent
- // endless looping.
- if (GetCurrentStatelessResetCounter(remote_addr) >=
- max_stateless_resets_per_host_) {
- return false;
- }
- // Per the QUIC spec, a stateless reset token must be strictly
- // smaller than the packet that triggered it. This is one of the
- // mechanisms to prevent infinite looping exchange of stateless
- // tokens with the peer.
- // An endpoint should never send a stateless reset token smaller than
- // 41 bytes per the QUIC spec. The reason is that packets less than
- // 41 bytes may allow an observer to determine that it's a stateless
- // reset.
- size_t pktlen = source_len - 1;
- if (pktlen < kMinStatelessResetLen)
- return false;
-
- StatelessResetToken token(reset_token_secret_, cid);
- EntropySource(random, kRandlen);
-
- auto packet = QuicPacket::Create("stateless reset", pktlen);
- ssize_t nwrite =
- ngtcp2_pkt_write_stateless_reset(
- packet->data(),
- NGTCP2_MAX_PKTLEN_IPV4,
- const_cast<uint8_t*>(token.data()),
- random,
- kRandlen);
- if (nwrite < static_cast<ssize_t>(kMinStatelessResetLen))
- return false;
- packet->set_length(nwrite);
- SocketAddress remote_address(remote_addr);
- IncrementStatelessResetCounter(remote_address);
- return SendPacket(local_addr, remote_address, std::move(packet)) == 0;
-}
-
-// Generates and sends a retry packet. This is terminal
-// for the connection. Retry packets are used to force
-// explicit path validation by issuing a token to the
-// peer that it must thereafter include in all subsequent
-// initial packets. Upon receiving a retry packet, the
-// peer must termination it's initial attempt to
-// establish a connection and start a new attempt.
-//
-// Retry packets will only ever be generated by QUIC servers,
-// and only if the QuicSocket is configured for explicit path
-// validation. There is no way for a client to force a retry
-// packet to be created. However, once a client determines that
-// explicit path validation is enabled, it could attempt to
-// DOS by sending a large number of malicious initial packets
-// to intentionally ellicit retry packets (It can do so by
-// intentionally sending initial packets that ignore the retry
-// token). To help mitigate that risk, we limit the number of
-// retries we send to a given remote endpoint.
-bool QuicSocket::SendRetry(
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr) {
- auto info = addrLRU_.Upsert(remote_addr);
- // Do not send a retry if the retry count is greater
- // than the retry limit.
- // TODO(@jasnell): Make the retry limit configurable.
- if (++(info->retry_count) > DEFAULT_MAX_RETRY_LIMIT)
- return true;
- std::unique_ptr<QuicPacket> packet =
- GenerateRetryPacket(token_secret_, dcid, scid, local_addr, remote_addr);
- return packet ?
- SendPacket(local_addr, remote_addr, std::move(packet)) == 0 : false;
-}
-
-// Shutdown a connection prematurely, before a QuicSession is created.
-// This should only be called t the start of a session before the crypto
-// keys have been established.
-void QuicSocket::ImmediateConnectionClose(
- const QuicCID& scid,
- const QuicCID& dcid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- int64_t reason) {
- Debug(this, "Sending stateless connection close to %s", scid);
- auto packet = QuicPacket::Create("immediate connection close");
- ssize_t nwrite = ngtcp2_crypto_write_connection_close(
- packet->data(),
- packet->length(),
- scid.cid(),
- dcid.cid(),
- reason);
- if (nwrite > 0) {
- packet->set_length(nwrite);
- SendPacket(local_addr, remote_addr, std::move(packet));
- }
-}
-
-// Inspects the packet and possibly accepts it as a new
-// initial packet creating a new QuicSession instance.
-// If the packet is not acceptable, it is very important
-// not to commit resources.
-BaseObjectPtr<QuicSession> QuicSocket::AcceptInitialPacket(
- uint32_t version,
- const QuicCID& dcid,
- const QuicCID& scid,
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) {
- HandleScope handle_scope(env()->isolate());
- Context::Scope context_scope(env()->context());
- ngtcp2_pkt_hd hd;
- QuicCID ocid;
-
- // If the QuicSocket is not listening, the paket will be ignored.
- if (!state_->server_listening) {
- Debug(this, "QuicSocket is not listening");
- return {};
- }
-
- switch (ngtcp2_accept(&hd, data, static_cast<size_t>(nread))) {
- case 1:
- // Send Version Negotiation
- SendVersionNegotiation(version, dcid, scid, local_addr, remote_addr);
- // Fall through
- case -1:
- // Either a version negotiation packet was sent or the packet is
- // an invalid initial packet. Either way, there's nothing more we
- // can do here.
- return {};
- }
-
- // If the server is busy, new connections will be shut down immediately
- // after the initial keys are installed. The busy state is controlled
- // entirely by local user code. It is important to understand that
- // a QuicSession is created and resources are committed even though
- // the QuicSession will be torn down as quickly as possible.
- // Else, check to see if the number of connections total for this QuicSocket
- // has been exceeded. If the count has been exceeded, shutdown the connection
- // immediately after the initial keys are installed.
- if (UNLIKELY(state_->server_busy == 1) ||
- sessions_.size() >= max_connections_ ||
- GetCurrentSocketAddressCounter(remote_addr) >=
- max_connections_per_host_) {
- Debug(this, "QuicSocket is busy or connection count exceeded");
- IncrementStat(&QuicSocketStats::server_busy_count);
- ImmediateConnectionClose(
- QuicCID(hd.scid),
- QuicCID(hd.dcid),
- local_addr,
- remote_addr,
- NGTCP2_CONNECTION_REFUSED);
- return {};
- }
-
- // QUIC has address validation built in to the handshake but allows for
- // an additional explicit validation request using RETRY frames. If we
- // are using explicit validation, we check for the existence of a valid
- // retry token in the packet. If one does not exist, we send a retry with
- // a new token. If it does exist, and if it's valid, we grab the original
- // cid and continue.
- if (!is_validated_address(remote_addr)) {
- switch (hd.type) {
- case NGTCP2_PKT_INITIAL:
- if (has_option_validate_address() || hd.token.len > 0) {
- Debug(this, "Performing explicit address validation");
- if (hd.token.len == 0) {
- Debug(this, "No retry token was detected. Generating one");
- SendRetry(dcid, scid, local_addr, remote_addr);
- // Sending a retry token terminates this connection attempt.
- return {};
- }
- if (InvalidRetryToken(
- hd.token,
- remote_addr,
- &ocid,
- token_secret_,
- retry_token_expiration_)) {
- Debug(this, "Invalid retry token was detected. Failing");
- ImmediateConnectionClose(
- QuicCID(hd.scid),
- QuicCID(hd.dcid),
- local_addr,
- remote_addr);
- return {};
- }
- }
- break;
- case NGTCP2_PKT_0RTT:
- SendRetry(dcid, scid, local_addr, remote_addr);
- return {};
- }
- }
-
- BaseObjectPtr<QuicSession> session =
- QuicSession::CreateServer(
- this,
- server_session_config_,
- local_addr,
- remote_addr,
- scid,
- dcid,
- ocid,
- version,
- server_alpn_,
- server_options_,
- qlog_);
- CHECK(session);
-
- listener_->OnSessionReady(session);
-
- // It's possible that the session was destroyed while processing
- // the ready callback. If it was, then we need to send an early
- // CONNECTION_CLOSE.
- if (session->is_destroyed()) {
- ImmediateConnectionClose(
- QuicCID(hd.scid),
- QuicCID(hd.dcid),
- local_addr,
- remote_addr,
- NGTCP2_CONNECTION_REFUSED);
- } else {
- session->set_wrapped();
- }
-
- return session;
-}
-
-QuicSocket::SendWrap::SendWrap(
- QuicState* quic_state,
- Local<Object> req_wrap_obj,
- size_t total_length)
- : ReqWrap(quic_state->env(), req_wrap_obj, PROVIDER_QUICSOCKET),
- total_length_(total_length),
- quic_state_(quic_state) {
-}
-
-std::string QuicSocket::SendWrap::MemoryInfoName() const {
- return "QuicSendWrap";
-}
-
-void QuicSocket::SendWrap::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("session", session_);
- tracker->TrackField("packet", packet_);
-}
-
-int QuicSocket::SendPacket(
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- std::unique_ptr<QuicPacket> packet,
- BaseObjectPtr<QuicSession> session) {
- // If the packet is empty, there's nothing to do
- if (packet->length() == 0)
- return 0;
-
- Debug(this, "Sending %" PRIu64 " bytes to %s from %s (label: %s)",
- packet->length(),
- remote_addr,
- local_addr,
- packet->diagnostic_label());
-
- // If DiagnosticPacketLoss returns true, it will call Done() internally
- if (UNLIKELY(is_diagnostic_packet_loss(tx_loss_))) {
- Debug(this, "Simulating transmitted packet loss");
- return 0;
- }
-
- last_created_send_wrap_ = nullptr;
- uv_buf_t buf = packet->buf();
-
- auto endpoint = bound_endpoints_.find(local_addr);
- CHECK_NE(endpoint, bound_endpoints_.end());
- int err = endpoint->second->Send(&buf, 1, remote_addr.data());
-
- if (err != 0) {
- if (err > 0) err = 0;
- OnSend(err, packet.get());
- } else {
- CHECK_NOT_NULL(last_created_send_wrap_);
- last_created_send_wrap_->set_packet(std::move(packet));
- if (session)
- last_created_send_wrap_->set_session(session);
- }
- return err;
-}
-
-void QuicSocket::OnSend(int status, QuicPacket* packet) {
- if (status == 0) {
- Debug(this, "Sent %" PRIu64 " bytes (label: %s)",
- packet->length(),
- packet->diagnostic_label());
- IncrementStat(&QuicSocketStats::bytes_sent, packet->length());
- IncrementStat(&QuicSocketStats::packets_sent);
- } else {
- Debug(this, "Failed to send %" PRIu64 " bytes (status: %d, label: %s)",
- packet->length(),
- status,
- packet->diagnostic_label());
- }
-}
-
-void QuicSocket::OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) {
- std::unique_ptr<SendWrap> req_wrap(static_cast<SendWrap*>(wrap));
- OnSend(status, req_wrap->packet());
-}
-
-void QuicSocket::CheckAllocatedSize(size_t previous_size) const {
- CHECK_GE(current_ngtcp2_memory_, previous_size);
-}
-
-void QuicSocket::IncreaseAllocatedSize(size_t size) {
- current_ngtcp2_memory_ += size;
-}
-
-void QuicSocket::DecreaseAllocatedSize(size_t size) {
- current_ngtcp2_memory_ -= size;
-}
-
-void QuicSocket::PushListener(QuicSocketListener* listener) {
- CHECK_NOT_NULL(listener);
- CHECK(!listener->socket_);
-
- listener->previous_listener_ = listener_;
- listener->socket_.reset(this);
-
- listener_ = listener;
-}
-
-void QuicSocket::RemoveListener(QuicSocketListener* listener) {
- CHECK_NOT_NULL(listener);
-
- QuicSocketListener* previous;
- QuicSocketListener* current;
-
- for (current = listener_, previous = nullptr;
- /* No loop condition because we want a crash if listener is not found */
- ; previous = current, current = current->previous_listener_) {
- CHECK_NOT_NULL(current);
- if (current == listener) {
- if (previous != nullptr)
- previous->previous_listener_ = current->previous_listener_;
- else
- listener_ = listener->previous_listener_;
- break;
- }
- }
-
- listener->socket_.reset();
- listener->previous_listener_ = nullptr;
-}
-
-bool QuicSocket::SocketAddressInfoTraits::CheckExpired(
- const SocketAddress& address,
- const Type& type) {
- return (uv_hrtime() - type.timestamp) > 1e10; // 10 seconds.
-}
-
-void QuicSocket::SocketAddressInfoTraits::Touch(
- const SocketAddress& address,
- Type* type) {
- type->timestamp = uv_hrtime();
-}
-
-// JavaScript API
-namespace {
-void NewQuicEndpoint(const FunctionCallbackInfo<Value>& args) {
- QuicState* state = Environment::GetBindingData<QuicState>(args);
- CHECK(args.IsConstructCall());
- CHECK(args[0]->IsObject());
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&socket, args[0].As<Object>());
- CHECK(args[1]->IsObject());
- CHECK_GE(args[1].As<Object>()->InternalFieldCount(),
- UDPWrapBase::kUDPWrapBaseField);
- new QuicEndpoint(state, args.This(), socket, args[1].As<Object>());
-}
-
-void NewQuicSocket(const FunctionCallbackInfo<Value>& args) {
- QuicState* state = Environment::GetBindingData<QuicState>(args);
- Environment* env = state->env();
- CHECK(args.IsConstructCall());
-
- uint32_t options;
- uint32_t retry_token_expiration;
- uint32_t max_connections;
- uint32_t max_connections_per_host;
- uint32_t max_stateless_resets_per_host;
-
- if (!args[0]->Uint32Value(env->context()).To(&options) ||
- !args[1]->Uint32Value(env->context()).To(&retry_token_expiration) ||
- !args[2]->Uint32Value(env->context()).To(&max_connections) ||
- !args[3]->Uint32Value(env->context()).To(&max_connections_per_host) ||
- !args[4]->Uint32Value(env->context())
- .To(&max_stateless_resets_per_host)) {
- return;
- }
- CHECK_GE(retry_token_expiration, MIN_RETRYTOKEN_EXPIRATION);
- CHECK_LE(retry_token_expiration, MAX_RETRYTOKEN_EXPIRATION);
-
- const uint8_t* session_reset_secret = nullptr;
- if (args[6]->IsArrayBufferView()) {
- ArrayBufferViewContents<uint8_t> buf(args[6].As<ArrayBufferView>());
- CHECK_EQ(buf.length(), kTokenSecretLen);
- session_reset_secret = buf.data();
- }
-
- new QuicSocket(
- state,
- args.This(),
- retry_token_expiration,
- max_connections,
- max_connections_per_host,
- max_stateless_resets_per_host,
- options,
- args[5]->IsTrue() ? QlogMode::kEnabled : QlogMode::kDisabled,
- session_reset_secret,
- args[7]->IsTrue());
-}
-
-void QuicSocketAddEndpoint(const FunctionCallbackInfo<Value>& args) {
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&socket, args.Holder());
- CHECK(args[0]->IsObject());
- QuicEndpoint* endpoint;
- ASSIGN_OR_RETURN_UNWRAP(&endpoint, args[0].As<Object>());
- socket->AddEndpoint(
- BaseObjectPtr<QuicEndpoint>(endpoint),
- args[1]->IsTrue());
-}
-
-// Enabling diagnostic packet loss enables a mode where the QuicSocket
-// instance will randomly ignore received packets in order to simulate
-// packet loss. This is not an API that should be enabled in production
-// but is useful when debugging and diagnosing performance issues.
-// Diagnostic packet loss is enabled by setting either the tx or rx
-// arguments to a value between 0.0 and 1.0. Setting both values to 0.0
-// disables the mechanism.
-void QuicSocketSetDiagnosticPacketLoss(
- const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&socket, args.Holder());
- double rx, tx;
- if (!args[0]->NumberValue(env->context()).To(&rx) ||
- !args[1]->NumberValue(env->context()).To(&tx)) return;
- CHECK_GE(rx, 0.0f);
- CHECK_GE(tx, 0.0f);
- CHECK_LE(rx, 1.0f);
- CHECK_LE(tx, 1.0f);
- socket->set_diagnostic_packet_loss(rx, tx);
-}
-
-void QuicSocketDestroy(const FunctionCallbackInfo<Value>& args) {
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&socket, args.Holder());
- socket->ReceiveStop();
-}
-
-void QuicSocketListen(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicSocket* socket;
- ASSIGN_OR_RETURN_UNWRAP(&socket, args.Holder(),
- args.GetReturnValue().Set(UV_EBADF));
- CHECK(args[0]->IsObject() &&
- env->secure_context_constructor_template()->HasInstance(args[0]));
- SecureContext* sc;
- ASSIGN_OR_RETURN_UNWRAP(&sc, args[0].As<Object>(),
- args.GetReturnValue().Set(UV_EBADF));
-
- sockaddr_storage preferred_address_storage;
- const sockaddr* preferred_address = nullptr;
- if (args[1]->IsString()) {
- node::Utf8Value preferred_address_host(args.GetIsolate(), args[1]);
- int32_t preferred_address_family;
- uint32_t preferred_address_port;
- if (!args[2]->Int32Value(env->context()).To(&preferred_address_family) ||
- !args[3]->Uint32Value(env->context()).To(&preferred_address_port))
- return;
- if (SocketAddress::ToSockAddr(
- preferred_address_family,
- *preferred_address_host,
- preferred_address_port,
- &preferred_address_storage)) {
- preferred_address =
- reinterpret_cast<const sockaddr*>(&preferred_address_storage);
- }
- }
-
- std::string alpn(NGHTTP3_ALPN_H3);
- if (args[4]->IsString()) {
- Utf8Value val(env->isolate(), args[4]);
- alpn = val.length();
- alpn += *val;
- }
-
- uint32_t options = 0;
- if (!args[5]->Uint32Value(env->context()).To(&options)) return;
-
- socket->Listen(
- BaseObjectPtr<SecureContext>(sc),
- preferred_address,
- alpn,
- options);
-}
-
-void QuicEndpointWaitForPendingCallbacks(
- const FunctionCallbackInfo<Value>& args) {
- QuicEndpoint* endpoint;
- ASSIGN_OR_RETURN_UNWRAP(&endpoint, args.Holder());
- endpoint->WaitForPendingCallbacks();
-}
-
-} // namespace
-
-void QuicEndpoint::Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context) {
- Isolate* isolate = env->isolate();
- Local<FunctionTemplate> endpoint = env->NewFunctionTemplate(NewQuicEndpoint);
- endpoint->Inherit(BaseObject::GetConstructorTemplate(env));
- endpoint->InstanceTemplate()->SetInternalFieldCount(
- QuicEndpoint::kInternalFieldCount);
- env->SetProtoMethod(endpoint,
- "waitForPendingCallbacks",
- QuicEndpointWaitForPendingCallbacks);
- endpoint->InstanceTemplate()->Set(env->owner_symbol(), Null(isolate));
-
- env->SetConstructorFunction(target, "QuicEndpoint", endpoint);
-}
-
-void QuicSocket::Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context) {
- Isolate* isolate = env->isolate();
- Local<FunctionTemplate> socket = env->NewFunctionTemplate(NewQuicSocket);
- socket->Inherit(AsyncWrap::GetConstructorTemplate(env));
- socket->InstanceTemplate()->SetInternalFieldCount(
- QuicSocket::kInternalFieldCount);
- socket->InstanceTemplate()->Set(env->owner_symbol(), Null(isolate));
- env->SetProtoMethod(socket,
- "addEndpoint",
- QuicSocketAddEndpoint);
- env->SetProtoMethod(socket,
- "destroy",
- QuicSocketDestroy);
- env->SetProtoMethod(socket,
- "listen",
- QuicSocketListen);
- env->SetProtoMethod(socket,
- "setDiagnosticPacketLoss",
- QuicSocketSetDiagnosticPacketLoss);
- socket->Inherit(HandleWrap::GetConstructorTemplate(env));
- env->SetConstructorFunction(target, "QuicSocket", socket);
-
- Local<FunctionTemplate> sendwrap_ctor = FunctionTemplate::New(isolate);
- sendwrap_ctor->Inherit(AsyncWrap::GetConstructorTemplate(env));
- sendwrap_ctor->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "SendWrap"));
- Local<ObjectTemplate> sendwrap_template = sendwrap_ctor->InstanceTemplate();
- sendwrap_template->SetInternalFieldCount(SendWrap::kInternalFieldCount);
- env->set_quicsocketsendwrap_instance_template(sendwrap_template);
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_socket.h b/src/quic/node_quic_socket.h
deleted file mode 100644
index 63bb49091b..0000000000
--- a/src/quic/node_quic_socket.h
+++ /dev/null
@@ -1,609 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_SOCKET_H_
-#define SRC_QUIC_NODE_QUIC_SOCKET_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "aliased_struct.h"
-#include "base_object.h"
-#include "node.h"
-#include "node_crypto.h"
-#include "node_internals.h"
-#include "ngtcp2/ngtcp2.h"
-#include "nghttp3/nghttp3.h"
-#include "node_quic_state.h"
-#include "node_quic_session.h"
-#include "node_quic_util.h"
-#include "node_sockaddr.h"
-#include "env.h"
-#include "udp_wrap.h"
-#include "v8.h"
-#include "uv.h"
-
-#include <deque>
-#include <map>
-#include <string>
-#include <vector>
-
-namespace node {
-
-using v8::Context;
-using v8::Local;
-using v8::Object;
-
-namespace quic {
-
-class QuicSocket;
-class QuicEndpoint;
-
-constexpr size_t DEFAULT_MAX_SOCKETADDRESS_LRU_SIZE = 1000;
-constexpr size_t DEFAULT_MAX_RETRY_LIMIT = 10;
-
-#define QUICSOCKET_OPTIONS(V) \
- V(VALIDATE_ADDRESS, validate_address)
-
-#define V(id, _) QUICSOCKET_OPTIONS_##id,
-enum QuicSocketOptions : uint32_t {
- QUICSOCKET_OPTIONS(V)
- QUICSOCKET_OPTIONS_COUNT
-};
-#undef V
-
-#define QUICSOCKET_SHARED_STATE(V) \
- V(SERVER_LISTENING, server_listening, uint8_t) \
- V(SERVER_BUSY, server_busy, uint8_t) \
- V(STATELESS_RESET_DISABLED, stateless_reset_disabled, uint8_t)
-
-#define V(_, name, type) type name;
-struct QuicSocketState {
- QUICSOCKET_SHARED_STATE(V)
-};
-#undef V
-
-#define V(id, name, _) \
- IDX_QUICSOCKET_STATE_##id = offsetof(QuicSocketState, name),
-enum QuicSocketStateFields {
- QUICSOCKET_SHARED_STATE(V)
- IDX_QUICSOCKET_STATE_END
-};
-#undef V
-
-#define SOCKET_STATS(V) \
- V(CREATED_AT, created_at, "Created At") \
- V(BOUND_AT, bound_at, "Bound At") \
- V(LISTEN_AT, listen_at, "Listen At") \
- V(DESTROYED_AT, destroyed_at, "Destroyed At") \
- V(BYTES_RECEIVED, bytes_received, "Bytes Received") \
- V(BYTES_SENT, bytes_sent, "Bytes Sent") \
- V(PACKETS_RECEIVED, packets_received, "Packets Received") \
- V(PACKETS_IGNORED, packets_ignored, "Packets Ignored") \
- V(PACKETS_SENT, packets_sent, "Packets Sent") \
- V(SERVER_SESSIONS, server_sessions, "Server Sessions") \
- V(CLIENT_SESSIONS, client_sessions, "Client Sessions") \
- V(STATELESS_RESET_COUNT, stateless_reset_count, "Stateless Reset Count") \
- V(SERVER_BUSY_COUNT, server_busy_count, "Server Busy Count")
-
-#define V(name, _, __) IDX_QUIC_SOCKET_STATS_##name,
-enum QuicSocketStatsIdx : int {
- SOCKET_STATS(V)
- IDX_QUIC_SOCKET_STATS_COUNT
-};
-#undef V
-
-#define V(_, name, __) uint64_t name;
-struct QuicSocketStats {
- SOCKET_STATS(V)
-};
-#undef V
-
-struct QuicSocketStatsTraits {
- using Stats = QuicSocketStats;
- using Base = QuicSocket;
-
- template <typename Fn>
- static void ToString(const Base& ptr, Fn&& add_field);
-};
-
-// This is the generic interface for objects that control QuicSocket
-// instances. The default `JSQuicSocketListener` emits events to
-// JavaScript
-class QuicSocketListener {
- public:
- virtual ~QuicSocketListener();
-
- virtual void OnError(ssize_t code);
- virtual void OnSessionReady(BaseObjectPtr<QuicSession> session);
- virtual void OnServerBusy();
- virtual void OnEndpointDone(QuicEndpoint* endpoint);
- virtual void OnDestroy();
-
- QuicSocket* socket() const { return socket_.get(); }
-
- private:
- BaseObjectWeakPtr<QuicSocket> socket_;
- QuicSocketListener* previous_listener_ = nullptr;
- friend class QuicSocket;
-};
-
-class JSQuicSocketListener final : public QuicSocketListener {
- public:
- void OnError(ssize_t code) override;
- void OnSessionReady(BaseObjectPtr<QuicSession> session) override;
- void OnServerBusy() override;
- void OnEndpointDone(QuicEndpoint* endpoint) override;
- void OnDestroy() override;
-};
-
-// This is just a formality as the QUIC spec normatively
-// defines that the ipv4 max pktlen is always going to be
-// larger than the ipv6 max pktlen, but in the off chance
-// ever changes (which is unlikely) we check here.
-constexpr size_t MAX_PKTLEN =
- std::max<size_t>(NGTCP2_MAX_PKTLEN_IPV4, NGTCP2_MAX_PKTLEN_IPV6);
-
-// A serialized QuicPacket to be sent by a QuicSocket instance.
-// QuicPackets are intended to be transient. They are created,
-// filled with the contents of a serialized packet, and passed
-// off immediately to the QuicSocket to be sent. As soon as
-// the packet is sent, it is freed.
-class QuicPacket : public MemoryRetainer {
- public:
- // Creates a new QuicPacket. By default the packet will be
- // stack allocated with a max size of NGTCP2_MAX_PKTLEN_IPV4.
- // If a larger packet size is specified, it will be heap
- // allocated. A QUIC packet should never be larger than the
- // current MTU to avoid IP fragmentation.
- //
- // The content of a QuicPacket is provided by ngtcp2 and is
- // opaque for us. The typical use pattern is to create a QuicPacket
- // instance and then pass a pointer to it's internal buffer and max
- // size in to an ngtcp2 function that serializes the data.
- // ngtcp2 will fill the buffer as much as possible then return
- // the number of bytes serialized. User code is then responsible
- // for calling set_length() to set the final length of the
- // QuicPacket prior to sending it off to the QuicSocket.
- //
- // The diagnostic label is used in NODE_DEBUG_NATIVE output
- // to differentiate send operations. This should always be
- // a statically allocated string or nullptr (in which case
- // the value "unspecified" is used in the debug output).
- //
- // Instances of std::unique_ptr<QuicPacket> are moved through
- // QuicSocket and ultimately become the responsibility of the
- // SendWrap instance. When the SendWrap is cleaned up, the
- // QuicPacket instance will be freed.
- static inline std::unique_ptr<QuicPacket> Create(
- const char* diagnostic_label = nullptr,
- size_t len = MAX_PKTLEN);
-
- // Copy the data of the QuicPacket to a new one. Currently,
- // this is only used when retransmitting close connection
- // packets from a QuicServer.
- static inline std::unique_ptr<QuicPacket> Copy(
- const std::unique_ptr<QuicPacket>& other);
-
- QuicPacket(const char* diagnostic_label, size_t len);
- QuicPacket(const QuicPacket& other);
-
- uint8_t* data() { return data_; }
-
- size_t length() const { return len_; }
-
- uv_buf_t buf() const {
- return uv_buf_init(
- const_cast<char*>(reinterpret_cast<const char*>(&data_)),
- length());
- }
-
- inline void set_length(size_t len);
-
- const char* diagnostic_label() const;
-
- SET_NO_MEMORY_INFO();
- SET_MEMORY_INFO_NAME(QuicPacket);
- SET_SELF_SIZE(QuicPacket);
-
- private:
- uint8_t data_[MAX_PKTLEN];
- size_t len_ = MAX_PKTLEN;
- const char* diagnostic_label_ = nullptr;
-};
-
-// QuicEndpointListener listens to events generated by a QuicEndpoint.
-class QuicEndpointListener {
- public:
- virtual void OnError(QuicEndpoint* endpoint, ssize_t error) = 0;
- virtual void OnReceive(
- ssize_t nread,
- AllocatedBuffer buf,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) = 0;
- virtual ReqWrap<uv_udp_send_t>* OnCreateSendWrap(size_t msg_size) = 0;
- virtual void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) = 0;
- virtual void OnBind(QuicEndpoint* endpoint) = 0;
- virtual void OnEndpointDone(QuicEndpoint* endpoint) = 0;
-};
-
-// A QuicEndpoint wraps a UDPBaseWrap. A single QuicSocket may
-// have multiple QuicEndpoints, the lifecycles of which are
-// attached to the QuicSocket.
-class QuicEndpoint final : public BaseObject,
- public UDPListener {
- public:
- static void Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context);
-
- QuicEndpoint(
- QuicState* quic_state,
- Local<Object> wrap,
- QuicSocket* listener,
- Local<Object> udp_wrap);
-
- ~QuicEndpoint() override;
-
- SocketAddress local_address() const {
- return udp_->GetSockName();
- }
-
- // Implementation for UDPListener
- uv_buf_t OnAlloc(size_t suggested_size) override;
-
- void OnRecv(ssize_t nread,
- const uv_buf_t& buf,
- const sockaddr* addr,
- unsigned int flags) override;
-
- ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) override;
-
- void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) override;
-
- void OnAfterBind() override;
-
- inline int ReceiveStart();
-
- inline int ReceiveStop();
-
- inline int Send(
- uv_buf_t* buf,
- size_t len,
- const sockaddr* addr);
-
- void IncrementPendingCallbacks() { pending_callbacks_++; }
- void DecrementPendingCallbacks() { pending_callbacks_--; }
- bool has_pending_callbacks() const { return pending_callbacks_ > 0; }
- inline void WaitForPendingCallbacks();
-
- QuicState* quic_state() const { return quic_state_.get(); }
-
- SET_NO_MEMORY_INFO();
- SET_MEMORY_INFO_NAME(QuicEndpoint)
- SET_SELF_SIZE(QuicEndpoint)
-
- private:
- BaseObjectWeakPtr<QuicSocket> listener_;
- UDPWrapBase* udp_;
- BaseObjectPtr<AsyncWrap> strong_ptr_;
- size_t pending_callbacks_ = 0;
- bool waiting_for_callbacks_ = false;
- BaseObjectPtr<QuicState> quic_state_;
-};
-
-// QuicSocket manages the flow of data from the UDP socket to the
-// QuicSession. It is responsible for managing the lifecycle of the
-// UDP sockets, listening for new server QuicSession instances, and
-// passing data two and from the remote peer.
-class QuicSocket : public AsyncWrap,
- public QuicEndpointListener,
- public mem::NgLibMemoryManager<QuicSocket, ngtcp2_mem>,
- public StatsBase<QuicSocketStatsTraits> {
- public:
- static void Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context);
-
- QuicSocket(
- QuicState* quic_state,
- Local<Object> wrap,
- // A retry token should only be valid for a small window of time.
- // The retry_token_expiration specifies the number of seconds a
- // retry token is permitted to be valid.
- uint64_t retry_token_expiration,
- // To prevent malicious clients from opening too many concurrent
- // connections, we limit the maximum number per remote sockaddr.
- size_t max_connections,
- size_t max_connections_per_host,
- size_t max_stateless_resets_per_host
- = DEFAULT_MAX_STATELESS_RESETS_PER_HOST,
- uint32_t options = 0,
- QlogMode qlog = QlogMode::kDisabled,
- const uint8_t* session_reset_secret = nullptr,
- bool disable_session_reset = false);
-
- ~QuicSocket() override;
-
- // Returns the default/preferred local address. Additional
- // QuicEndpoint instances may be associated with the
- // QuicSocket bound to other local addresses.
- inline SocketAddress local_address() const;
-
- void MaybeClose();
-
- inline void AddSession(
- const QuicCID& cid,
- BaseObjectPtr<QuicSession> session);
-
- inline void AssociateCID(
- const QuicCID& cid,
- const QuicCID& scid);
-
- inline void DisassociateCID(
- const QuicCID& cid);
-
- inline void AssociateStatelessResetToken(
- const StatelessResetToken& token,
- BaseObjectPtr<QuicSession> session);
-
- inline void DisassociateStatelessResetToken(
- const StatelessResetToken& token);
-
- void Listen(
- BaseObjectPtr<crypto::SecureContext> context,
- const sockaddr* preferred_address = nullptr,
- const std::string& alpn = NGHTTP3_ALPN_H3,
- uint32_t options = 0);
-
- inline void ReceiveStart();
-
- inline void ReceiveStop();
-
- inline void RemoveSession(
- const QuicCID& cid,
- const SocketAddress& addr);
-
- inline void ReportSendError(int error);
-
- int SendPacket(
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- std::unique_ptr<QuicPacket> packet,
- BaseObjectPtr<QuicSession> session = BaseObjectPtr<QuicSession>());
-
-#define V(id, name) \
- bool has_option_##name() const { \
- return options_ & (1 << QUICSOCKET_OPTIONS_##id); }
- QUICSOCKET_OPTIONS(V)
-#undef V
-
- // Allows the server busy status to be enabled from C++. A notification
- // will be sent to the JavaScript side informing that the status has
- // changed.
- inline void ServerBusy(bool on);
-
- inline void set_diagnostic_packet_loss(double rx = 0.0, double tx = 0.0);
-
- BaseObjectPtr<crypto::SecureContext> server_secure_context() const {
- return server_secure_context_;
- }
-
- QuicState* quic_state() { return quic_state_.get(); }
-
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_MEMORY_INFO_NAME(QuicSocket)
- SET_SELF_SIZE(QuicSocket)
-
- // Implementation for mem::NgLibMemoryManager
- void CheckAllocatedSize(size_t previous_size) const;
-
- void IncreaseAllocatedSize(size_t size);
-
- void DecreaseAllocatedSize(size_t size);
-
- const uint8_t* session_reset_secret() { return reset_token_secret_; }
-
- // Implementation for QuicListener
- ReqWrap<uv_udp_send_t>* OnCreateSendWrap(size_t msg_size) override;
-
- // Implementation for QuicListener
- void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) override;
-
- // Implementation for QuicListener
- void OnBind(QuicEndpoint* endpoint) override;
-
- // Implementation for QuicListener
- void OnReceive(
- ssize_t nread,
- AllocatedBuffer buf,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags) override;
-
- // Implementation for QuicListener
- void OnError(QuicEndpoint* endpoint, ssize_t error) override;
-
- // Implementation for QuicListener
- void OnEndpointDone(QuicEndpoint* endpoint) override;
-
- // Serializes and transmits a RETRY packet to the connected peer.
- bool SendRetry(
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr);
-
- // Serializes and transmits a Stateless Reset to the connected peer.
- bool SendStatelessReset(
- const QuicCID& cid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- size_t source_len);
-
- // Serializes and transmits a Version Negotiation packet to the
- // connected peer.
- void SendVersionNegotiation(
- uint32_t version,
- const QuicCID& dcid,
- const QuicCID& scid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr);
-
- void PushListener(QuicSocketListener* listener);
-
- void RemoveListener(QuicSocketListener* listener);
-
- inline void AddEndpoint(
- BaseObjectPtr<QuicEndpoint> endpoint,
- bool preferred = false);
-
- void ImmediateConnectionClose(
- const QuicCID& scid,
- const QuicCID& dcid,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- int64_t reason = NGTCP2_INVALID_TOKEN);
-
- private:
- static void OnAlloc(
- uv_handle_t* handle,
- size_t suggested_size,
- uv_buf_t* buf);
-
- void OnSend(int status, QuicPacket* packet);
-
- inline void set_validated_address(const SocketAddress& addr);
-
- inline bool is_validated_address(const SocketAddress& addr) const;
-
- bool MaybeStatelessReset(
- const QuicCID& dcid,
- const QuicCID& scid,
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags);
-
- BaseObjectPtr<QuicSession> AcceptInitialPacket(
- uint32_t version,
- const QuicCID& dcid,
- const QuicCID& scid,
- ssize_t nread,
- const uint8_t* data,
- const SocketAddress& local_addr,
- const SocketAddress& remote_addr,
- unsigned int flags);
-
- BaseObjectPtr<QuicSession> FindSession(const QuicCID& cid);
-
- inline void IncrementSocketAddressCounter(const SocketAddress& addr);
-
- inline void DecrementSocketAddressCounter(const SocketAddress& addr);
-
- inline void IncrementStatelessResetCounter(const SocketAddress& addr);
-
- inline size_t GetCurrentSocketAddressCounter(const SocketAddress& addr);
-
- inline size_t GetCurrentStatelessResetCounter(const SocketAddress& addr);
-
- // Returns true if, and only if, diagnostic packet loss is enabled
- // and the current packet should be artificially considered lost.
- inline bool is_diagnostic_packet_loss(double prob) const;
-
- ngtcp2_mem alloc_info_;
-
- std::vector<BaseObjectPtr<QuicEndpoint>> endpoints_;
- SocketAddress::Map<BaseObjectWeakPtr<QuicEndpoint>> bound_endpoints_;
- BaseObjectWeakPtr<QuicEndpoint> preferred_endpoint_;
- BaseObjectPtr<SocketAddressBlockListWrap> block_list_;
-
- uint32_t flags_ = 0;
- uint32_t options_ = 0;
- uint32_t server_options_;
-
- AliasedStruct<QuicSocketState> state_;
-
- size_t max_connections_ = DEFAULT_MAX_CONNECTIONS;
- size_t max_connections_per_host_ = DEFAULT_MAX_CONNECTIONS_PER_HOST;
- size_t current_ngtcp2_memory_ = 0;
- size_t max_stateless_resets_per_host_ = DEFAULT_MAX_STATELESS_RESETS_PER_HOST;
-
- uint64_t retry_token_expiration_;
-
- // Used to specify diagnostic packet loss probabilities
- double rx_loss_ = 0.0;
- double tx_loss_ = 0.0;
-
- QuicSocketListener* listener_;
- JSQuicSocketListener default_listener_;
- QuicSessionConfig server_session_config_;
- QlogMode qlog_ = QlogMode::kDisabled;
- BaseObjectPtr<crypto::SecureContext> server_secure_context_;
- std::string server_alpn_;
- QuicCID::Map<BaseObjectPtr<QuicSession>> sessions_;
- QuicCID::Map<QuicCID> dcid_to_scid_;
-
- uint8_t token_secret_[kTokenSecretLen];
- uint8_t reset_token_secret_[NGTCP2_STATELESS_RESET_TOKENLEN];
-
- struct SocketAddressInfo {
- size_t active_connections;
- size_t reset_count;
- size_t retry_count;
- bool validated;
- uint64_t timestamp;
- };
-
- struct SocketAddressInfoTraits {
- using Type = SocketAddressInfo;
-
- static bool CheckExpired(const SocketAddress& address, const Type& type);
- static void Touch(const SocketAddress& address, Type* type);
- };
-
- SocketAddressLRU<SocketAddressInfoTraits> addrLRU_;
-
- StatelessResetToken::Map<QuicSession> token_map_;
-
- class SendWrap : public ReqWrap<uv_udp_send_t> {
- public:
- SendWrap(QuicState* quic_state,
- v8::Local<v8::Object> req_wrap_obj,
- size_t total_length_);
-
- void set_packet(std::unique_ptr<QuicPacket> packet) {
- packet_ = std::move(packet);
- }
-
- QuicPacket* packet() { return packet_.get(); }
-
- void set_session(BaseObjectPtr<QuicSession> session) { session_ = session; }
-
- size_t total_length() const { return total_length_; }
-
- QuicState* quic_state() { return quic_state_.get(); }
-
- SET_SELF_SIZE(SendWrap);
- std::string MemoryInfoName() const override;
- void MemoryInfo(MemoryTracker* tracker) const override;
-
- private:
- BaseObjectPtr<QuicSession> session_;
- std::unique_ptr<QuicPacket> packet_;
- size_t total_length_;
- BaseObjectPtr<QuicState> quic_state_;
- };
-
- SendWrap* last_created_send_wrap_ = nullptr;
- BaseObjectPtr<QuicState> quic_state_;
-
- friend class QuicSocketListener;
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_SOCKET_H_
diff --git a/src/quic/node_quic_state.h b/src/quic/node_quic_state.h
deleted file mode 100644
index 6eb76529f8..0000000000
--- a/src/quic/node_quic_state.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_STATE_H_
-#define SRC_QUIC_NODE_QUIC_STATE_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "aliased_buffer.h"
-
-namespace node {
-namespace quic {
-
-enum QuicSessionConfigIndex : int {
- IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_REMOTE,
- IDX_QUIC_SESSION_MAX_STREAM_DATA_UNI,
- IDX_QUIC_SESSION_MAX_DATA,
- IDX_QUIC_SESSION_MAX_STREAMS_BIDI,
- IDX_QUIC_SESSION_MAX_STREAMS_UNI,
- IDX_QUIC_SESSION_MAX_IDLE_TIMEOUT,
- IDX_QUIC_SESSION_MAX_UDP_PAYLOAD_SIZE,
- IDX_QUIC_SESSION_ACK_DELAY_EXPONENT,
- IDX_QUIC_SESSION_DISABLE_MIGRATION,
- IDX_QUIC_SESSION_MAX_ACK_DELAY,
- IDX_QUIC_SESSION_CC_ALGO,
- IDX_QUIC_SESSION_CONFIG_COUNT
-};
-
-enum Http3ConfigIndex : int {
- IDX_HTTP3_QPACK_MAX_TABLE_CAPACITY,
- IDX_HTTP3_QPACK_BLOCKED_STREAMS,
- IDX_HTTP3_MAX_HEADER_LIST_SIZE,
- IDX_HTTP3_MAX_PUSHES,
- IDX_HTTP3_MAX_HEADER_PAIRS,
- IDX_HTTP3_MAX_HEADER_LENGTH,
- IDX_HTTP3_CONFIG_COUNT
-};
-
-class QuicState : public BaseObject {
- public:
- explicit QuicState(Environment* env, v8::Local<v8::Object> obj)
- : BaseObject(env, obj),
- root_buffer(
- env->isolate(),
- sizeof(quic_state_internal)),
- quicsessionconfig_buffer(
- env->isolate(),
- offsetof(quic_state_internal, quicsessionconfig_buffer),
- IDX_QUIC_SESSION_CONFIG_COUNT + 1,
- root_buffer),
- http3config_buffer(
- env->isolate(),
- offsetof(quic_state_internal, http3config_buffer),
- IDX_HTTP3_CONFIG_COUNT + 1,
- root_buffer) {
- }
-
- AliasedUint8Array root_buffer;
- AliasedFloat64Array quicsessionconfig_buffer;
- AliasedFloat64Array http3config_buffer;
-
- bool warn_trace_tls = true;
-
- static constexpr FastStringKey binding_data_name { "quic" };
-
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_SELF_SIZE(QuicState)
- SET_MEMORY_INFO_NAME(QuicState)
-
- private:
- struct quic_state_internal {
- // doubles first so that they are always sizeof(double)-aligned
- double quicsessionconfig_buffer[IDX_QUIC_SESSION_CONFIG_COUNT + 1];
- double http3config_buffer[IDX_HTTP3_CONFIG_COUNT + 1];
- };
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_STATE_H_
diff --git a/src/quic/node_quic_stream-inl.h b/src/quic/node_quic_stream-inl.h
deleted file mode 100644
index e79a326359..0000000000
--- a/src/quic/node_quic_stream-inl.h
+++ /dev/null
@@ -1,180 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_STREAM_INL_H_
-#define SRC_QUIC_NODE_QUIC_STREAM_INL_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "debug_utils-inl.h"
-#include "node_quic_session.h"
-#include "node_quic_stream.h"
-#include "node_quic_buffer-inl.h"
-
-namespace node {
-namespace quic {
-
-QuicStreamDirection QuicStream::direction() const {
- return stream_id_ & 0b10 ?
- QUIC_STREAM_UNIDIRECTIONAL :
- QUIC_STREAM_BIRECTIONAL;
-}
-
-QuicStreamOrigin QuicStream::origin() const {
- return stream_id_ & 0b01 ?
- QUIC_STREAM_SERVER :
- QUIC_STREAM_CLIENT;
-}
-
-void QuicStream::set_final_size(uint64_t final_size) {
- // Only set the final size once.
- if (state_->fin_received == 1) {
- CHECK_LE(final_size, GetStat(&QuicStreamStats::final_size));
- return;
- }
- state_->fin_received = 1;
- SetStat(&QuicStreamStats::final_size, final_size);
-}
-
-bool QuicStream::was_ever_writable() const {
- if (direction() == QUIC_STREAM_UNIDIRECTIONAL) {
- return session_->is_server() ?
- origin() == QUIC_STREAM_SERVER :
- origin() == QUIC_STREAM_CLIENT;
- }
- return true;
-}
-
-bool QuicStream::is_writable() const {
- return was_ever_writable() && !streambuf_.is_ended();
-}
-
-bool QuicStream::was_ever_readable() const {
- if (direction() == QUIC_STREAM_UNIDIRECTIONAL) {
- return session_->is_server() ?
- origin() == QUIC_STREAM_CLIENT :
- origin() == QUIC_STREAM_SERVER;
- }
-
- return true;
-}
-
-void QuicStream::set_fin_sent() {
- Debug(this, "final stream frame sent");
- state_->fin_sent = 1;
- if (shutdown_done_ != nullptr) {
- shutdown_done_(0);
- }
-}
-
-void QuicStream::set_destroyed() {
- destroyed_ = true;
-}
-
-bool QuicStream::is_readable() const {
- return was_ever_readable() && state_->read_ended == 0;
-}
-
-bool QuicStream::is_write_finished() const {
- return state_->fin_sent == 1 && streambuf_.length() == 0;
-}
-
-bool QuicStream::SubmitInformation(v8::Local<v8::Array> headers) {
- return session_->SubmitInformation(stream_id_, headers);
-}
-
-bool QuicStream::SubmitHeaders(v8::Local<v8::Array> headers, uint32_t flags) {
- return session_->SubmitHeaders(stream_id_, headers, flags);
-}
-
-bool QuicStream::SubmitTrailers(v8::Local<v8::Array> headers) {
- return session_->SubmitTrailers(stream_id_, headers);
-}
-
-BaseObjectPtr<QuicStream> QuicStream::SubmitPush(
- v8::Local<v8::Array> headers) {
- return session_->SubmitPush(stream_id_, headers);
-}
-
-void QuicStream::EndHeaders(int64_t push_id) {
- Debug(this, "End Headers");
- // Upon completion of a block of headers, convert the
- // vector of Header objects into an array of name+value
- // pairs, then call the on_stream_headers function.
- session()->application()->StreamHeaders(
- stream_id_,
- headers_kind_,
- headers_,
- push_id);
- headers_.clear();
-}
-
-void QuicStream::set_headers_kind(QuicStreamHeadersKind kind) {
- headers_kind_ = kind;
-}
-
-void QuicStream::BeginHeaders(QuicStreamHeadersKind kind) {
- Debug(this, "Beginning Headers");
- // Upon start of a new block of headers, ensure that any
- // previously collected ones are cleaned up.
- headers_.clear();
- set_headers_kind(kind);
-}
-
-void QuicStream::Commit(size_t amount) {
- CHECK(!is_destroyed());
- streambuf_.Seek(amount);
-}
-
-// ResetStream will cause ngtcp2 to queue a RESET_STREAM and STOP_SENDING
-// frame, as appropriate, for the given stream_id. For a locally-initiated
-// unidirectional stream, only a RESET_STREAM frame will be scheduled and
-// the stream will be immediately closed. For a bidirectional stream, a
-// STOP_SENDING frame will be sent.
-void QuicStream::ResetStream(uint64_t app_error_code) {
- QuicSession::SendSessionScope send_scope(session());
- session()->ShutdownStream(id(), app_error_code);
- state_->read_ended = 1;
- streambuf_.Cancel();
- streambuf_.End();
-}
-
-// StopSending will cause ngtcp2 to queue a STOP_SENDING frame if the
-// stream is still inbound readable.
-void QuicStream::StopSending(uint64_t app_error_code) {
- QuicSession::SendSessionScope send_scope(session());
- ngtcp2_conn_shutdown_stream_read(
- session()->connection(),
- stream_id_,
- app_error_code);
- state_->read_ended = 1;
-}
-
-void QuicStream::CancelPendingWrites() {
- // In case this stream is scheduled for sending data, remove it
- // from the schedule queue
- Unschedule();
-
- // If there is data currently buffered in the streambuf_,
- // then cancel will call out to invoke an arbitrary
- // JavaScript callback (the on write callback). Within
- // that callback, however, the QuicStream will no longer
- // be usable to send or receive data.
- streambuf_.End();
- streambuf_.Cancel();
- CHECK_EQ(streambuf_.length(), 0);
-}
-
-void QuicStream::Schedule(Queue* queue) {
- if (!stream_queue_.IsEmpty()) // Already scheduled?
- return;
- queue->PushBack(this);
-}
-
-void QuicStream::Unschedule() {
- stream_queue_.Remove();
-}
-
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_STREAM_INL_H_
diff --git a/src/quic/node_quic_stream.cc b/src/quic/node_quic_stream.cc
deleted file mode 100644
index 57976ae50d..0000000000
--- a/src/quic/node_quic_stream.cc
+++ /dev/null
@@ -1,548 +0,0 @@
-#include "node_quic_stream-inl.h" // NOLINT(build/include)
-#include "aliased_struct-inl.h"
-#include "async_wrap-inl.h"
-#include "debug_utils-inl.h"
-#include "env-inl.h"
-#include "node.h"
-#include "node_buffer.h"
-#include "node_internals.h"
-#include "stream_base-inl.h"
-#include "node_sockaddr-inl.h"
-#include "node_http_common-inl.h"
-#include "node_quic_session-inl.h"
-#include "node_quic_socket-inl.h"
-#include "node_quic_util-inl.h"
-#include "v8.h"
-#include "uv.h"
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <utility>
-
-namespace node {
-
-using v8::Array;
-using v8::Context;
-using v8::FunctionCallbackInfo;
-using v8::FunctionTemplate;
-using v8::Local;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::PropertyAttribute;
-using v8::Value;
-
-namespace quic {
-
-QuicStream::QuicStream(
- QuicSession* sess,
- Local<Object> wrap,
- int64_t stream_id,
- int64_t push_id)
- : AsyncWrap(sess->env(), wrap, AsyncWrap::PROVIDER_QUICSTREAM),
- StreamBase(sess->env()),
- StatsBase(sess->env(), wrap,
- HistogramOptions::ACK |
- HistogramOptions::RATE |
- HistogramOptions::SIZE),
- session_(sess),
- stream_id_(stream_id),
- push_id_(push_id),
- state_(sess->env()->isolate()),
- quic_state_(sess->quic_state()) {
- CHECK_NOT_NULL(sess);
- Debug(this, "Created");
- StreamBase::AttachToObject(GetObject());
-
- wrap->DefineOwnProperty(
- env()->context(),
- env()->state_string(),
- state_.GetArrayBuffer(),
- PropertyAttribute::ReadOnly).Check();
-
- ngtcp2_transport_params params;
- ngtcp2_conn_get_local_transport_params(session()->connection(), &params);
- IncrementStat(&QuicStreamStats::max_offset, params.initial_max_data);
-}
-
-QuicStream::~QuicStream() {
- DebugStats();
-}
-
-template <typename Fn>
-void QuicStreamStatsTraits::ToString(const QuicStream& ptr, Fn&& add_field) {
-#define V(_n, name, label) \
- add_field(label, ptr.GetStat(&QuicStreamStats::name));
- STREAM_STATS(V)
-#undef V
-}
-
-// Acknowledge is called when ngtcp2 has received an acknowledgement
-// for one or more stream frames for this QuicStream. This will cause
-// data stored in the streambuf_ outbound queue to be consumed and may
-// result in the JavaScript callback for the write to be invoked.
-void QuicStream::Acknowledge(uint64_t offset, size_t datalen) {
- if (is_destroyed())
- return;
-
- // ngtcp2 guarantees that offset must always be greater
- // than the previously received offset, but let's just
- // make sure that holds.
- CHECK_GE(offset, GetStat(&QuicStreamStats::max_offset_ack));
- SetStat(&QuicStreamStats::max_offset_ack, offset);
-
- Debug(this, "Acknowledging %d bytes", datalen);
-
- // Consumes the given number of bytes in the buffer. This may
- // have the side-effect of causing the onwrite callback to be
- // invoked if a complete chunk of buffered data has been acknowledged.
- streambuf_.Consume(datalen);
-
- RecordAck(&QuicStreamStats::acked_at);
-}
-
-// While not all QUIC applications will support headers, QuicStream
-// includes basic, generic support for storing them.
-bool QuicStream::AddHeader(std::unique_ptr<QuicHeader> header) {
- size_t len = header->length();
- QuicApplication* app = session()->application();
- // We cannot add the header if we've either reached
- // * the max number of header pairs or
- // * the max number of header bytes
- if (headers_.size() == app->max_header_pairs() ||
- current_headers_length_ + len > app->max_header_length()) {
- return false;
- }
-
- current_headers_length_ += header->length();
- Debug(this, "Header - %s", header.get());
- headers_.emplace_back(std::move(header));
- return true;
-}
-
-std::string QuicStream::diagnostic_name() const {
- return std::string("QuicStream ") + std::to_string(stream_id_) +
- " (" + std::to_string(static_cast<int64_t>(get_async_id())) +
- ", " + session_->diagnostic_name() + ")";
-}
-
-void QuicStream::Destroy(QuicError* error) {
- if (destroyed_)
- return;
- destroyed_ = true;
-
- if (is_writable() || is_readable())
- session()->ShutdownStream(id(), 0);
-
- CancelPendingWrites();
-
- session_->RemoveStream(stream_id_);
-}
-
-// Do shutdown is called when the JS stream writable side is closed.
-// If we're not within an ngtcp2 callback, this will trigger the
-// QuicSession to send any pending data. If a final stream frame
-// has not already been sent, it will be after this.
-int QuicStream::DoShutdown(ShutdownWrap* req_wrap) {
- if (is_destroyed())
- return UV_EPIPE;
-
- // If the fin bit has already been sent, we can return
- // immediately because there's nothing else to do. The
- // _final callback will be invoked immediately.
- if (state_->fin_sent || !is_writable()) {
- Debug(this, "Shutdown write immediately");
- return 1;
- }
- Debug(this, "Deferred shutdown. Waiting for fin sent");
-
- CHECK_NULL(shutdown_done_);
- CHECK_NOT_NULL(req_wrap);
- shutdown_done_ = [=](int status) {
- CHECK_NOT_NULL(req_wrap);
- shutdown_done_ = nullptr;
- req_wrap->Done(status);
- };
-
- QuicSession::SendSessionScope send_scope(session());
-
- Debug(this, "Shutdown writable side");
- RecordTimestamp(&QuicStreamStats::closing_at);
- state_->write_ended = 1;
- streambuf_.End();
- session()->ResumeStream(stream_id_);
-
- return 0;
-}
-
-int QuicStream::DoWrite(
- WriteWrap* req_wrap,
- uv_buf_t* bufs,
- size_t nbufs,
- uv_stream_t* send_handle) {
- CHECK_NULL(send_handle);
- CHECK(!streambuf_.is_ended());
-
- // A write should not have happened if we've been destroyed or
- // the QuicStream is no longer (or was never) writable.
- if (is_destroyed() || !is_writable()) {
- req_wrap->Done(UV_EPIPE);
- return 0;
- }
-
- // Nothing to write.
- size_t length = get_length(bufs, nbufs);
- if (length == 0) {
- req_wrap->Done(0);
- return 0;
- }
-
- QuicSession::SendSessionScope send_scope(session());
-
- Debug(this, "Queuing %" PRIu64 " bytes of data from %d buffers",
- length, nbufs);
- IncrementStat(&QuicStreamStats::bytes_sent, static_cast<uint64_t>(length));
-
- BaseObjectPtr<AsyncWrap> strong_ref{req_wrap->GetAsyncWrap()};
- // The list of buffers will be appended onto streambuf_ without
- // copying. Those will remain in the buffer until the serialized
- // stream frames are acknowledged.
- // This callback function will be invoked once this
- // complete batch of buffers has been acknowledged
- // by the peer. This will have the side effect of
- // blocking additional pending writes from the
- // javascript side, so writing data to the stream
- // will be throttled by how quickly the peer is
- // able to acknowledge stream packets. This is good
- // in the sense of providing back-pressure, but
- // also means that writes will be significantly
- // less performant unless written in batches.
- streambuf_.Push(
- bufs,
- nbufs,
- [req_wrap, strong_ref](int status) {
- req_wrap->Done(status);
- });
-
- // If end() was called on the JS side, the write_ended flag
- // will have been set. This allows us to know early if this
- // is the final chunk. But this is only only to be triggered
- // if end() was called with a final chunk of data to write.
- // Otherwise, we have to wait for DoShutdown to be called.
- if (state_->write_ended == 1) {
- RecordTimestamp(&QuicStreamStats::closing_at);
- streambuf_.End();
- }
-
- session()->ResumeStream(stream_id_);
-
- return 0;
-}
-
-bool QuicStream::IsAlive() {
- return !is_destroyed() && !IsClosing();
-}
-
-bool QuicStream::IsClosing() {
- return !is_writable() && !is_readable();
-}
-
-int QuicStream::ReadStart() {
- CHECK(!is_destroyed());
- CHECK(is_readable());
- state_->read_started = 1;
- state_->read_paused = 0;
- IncrementStat(
- &QuicStreamStats::max_offset,
- inbound_consumed_data_while_paused_);
- session_->ExtendStreamOffset(id(), inbound_consumed_data_while_paused_);
- return 0;
-}
-
-int QuicStream::ReadStop() {
- CHECK(!is_destroyed());
- CHECK(is_readable());
- state_->read_paused = 1;
- return 0;
-}
-
-void QuicStream::IncrementStats(size_t datalen) {
- uint64_t len = static_cast<uint64_t>(datalen);
- IncrementStat(&QuicStreamStats::bytes_received, len);
- RecordRate(&QuicStreamStats::received_at);
- RecordSize(len);
-}
-
-void QuicStream::MemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("buffer", &streambuf_);
- StatsBase::StatsMemoryInfo(tracker);
- tracker->TrackField("headers", headers_);
-}
-
-BaseObjectPtr<QuicStream> QuicStream::New(
- QuicSession* session,
- int64_t stream_id,
- int64_t push_id) {
- Local<Object> obj;
- if (!session->env()
- ->quicserverstream_instance_template()
- ->NewInstance(session->env()->context()).ToLocal(&obj)) {
- return {};
- }
- BaseObjectPtr<QuicStream> stream =
- MakeDetachedBaseObject<QuicStream>(
- session,
- obj,
- stream_id,
- push_id);
- CHECK(stream);
- session->AddStream(stream);
- return stream;
-}
-
-// Passes chunks of data on to the JavaScript side as soon as they are
-// received but only if we're still readable. The caller of this must have a
-// HandleScope.
-//
-// Note that this is pushing data to the JS side regardless of whether
-// anything is listening. For flow-control, we only send window updates
-// to the sending peer if the stream is in flowing mode, so the sender
-// should not be sending too much data.
-void QuicStream::ReceiveData(
- uint32_t flags,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset) {
- CHECK(!is_destroyed());
- Debug(this, "Receiving %d bytes. Final? %s. Readable? %s",
- datalen,
- flags & NGTCP2_STREAM_DATA_FLAG_FIN ? "yes" : "no",
- is_readable() ? "yes" : "no");
-
- // If the QuicStream is not (or was never) readable, just ignore the chunk.
- if (!is_readable())
- return;
-
- // ngtcp2 guarantees that datalen will only be 0 if fin is set.
- // Let's just make sure.
- CHECK(datalen > 0 || flags & NGTCP2_STREAM_DATA_FLAG_FIN);
-
- // ngtcp2 guarantees that offset is always greater than the previously
- // received offset. Let's just make sure.
- CHECK_GE(offset, GetStat(&QuicStreamStats::max_offset_received));
- SetStat(&QuicStreamStats::max_offset_received, offset);
-
- if (datalen > 0) {
- // IncrementStats will update the data_rx_rate_ and data_rx_size_
- // histograms. These will provide data necessary to detect and
- // prevent Slow Send DOS attacks specifically by allowing us to
- // see if a connection is sending very small chunks of data at very
- // slow speeds. It is important to emphasize, however, that slow send
- // rates may be perfectly legitimate so we cannot simply take blanket
- // action when slow rates are detected. Nor can we reliably define what
- // a slow rate even is! Will will need to determine some reasonable
- // default and allow user code to change the default as well as determine
- // what action to take. The current strategy will be to trigger an event
- // on the stream when data transfer rates are likely to be considered too
- // slow.
- IncrementStats(datalen);
-
- while (datalen > 0) {
- uv_buf_t buf = EmitAlloc(datalen);
- size_t avail = std::min(static_cast<size_t>(buf.len), datalen);
-
- // For now, we're allocating and copying. Once we determine if we can
- // safely switch to a non-allocated mode like we do with http2 streams,
- // we can make this branch more efficient by using the LIKELY
- // optimization. The way ngtcp2 currently works, however, we have
- // to memcpy here.
- if (UNLIKELY(buf.base == nullptr))
- buf.base = reinterpret_cast<char*>(const_cast<uint8_t*>(data));
- else
- memcpy(buf.base, data, avail);
- data += avail;
- datalen -= avail;
- // Capture read_paused before EmitRead in case user code callbacks
- // alter the state when EmitRead is called.
- bool read_paused = state_->read_paused == 1;
- EmitRead(avail, buf);
- // Reading can be paused while we are processing. If that's
- // the case, we still want to acknowledge the current bytes
- // so that pausing does not throw off our flow control.
- if (read_paused) {
- inbound_consumed_data_while_paused_ += avail;
- } else {
- IncrementStat(&QuicStreamStats::max_offset, avail);
- session_->ExtendStreamOffset(id(), avail);
- }
- }
- }
-
- // When fin != 0, we've received that last chunk of data for this
- // stream, indicating that the stream will no longer be readable.
- if (flags & NGTCP2_STREAM_DATA_FLAG_FIN) {
- set_final_size(offset + datalen);
- EmitRead(UV_EOF);
- }
-}
-
-int QuicStream::DoPull(
- bob::Next<ngtcp2_vec> next,
- int options,
- ngtcp2_vec* data,
- size_t count,
- size_t max_count_hint) {
- return streambuf_.Pull(
- std::move(next),
- options,
- data,
- count,
- max_count_hint);
-}
-
-// JavaScript API
-namespace {
-void QuicStreamGetID(const FunctionCallbackInfo<Value>& args) {
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- args.GetReturnValue().Set(static_cast<double>(stream->id()));
-}
-
-void OpenUnidirectionalStream(const FunctionCallbackInfo<Value>& args) {
- CHECK(!args.IsConstructCall());
- CHECK(args[0]->IsObject());
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
-
- int64_t stream_id;
- if (!session->OpenUnidirectionalStream(&stream_id))
- return;
-
- BaseObjectPtr<QuicStream> stream = QuicStream::New(session, stream_id);
- args.GetReturnValue().Set(stream->object());
-}
-
-void OpenBidirectionalStream(const FunctionCallbackInfo<Value>& args) {
- CHECK(!args.IsConstructCall());
- CHECK(args[0]->IsObject());
- QuicSession* session;
- ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
-
- int64_t stream_id;
- if (!session->OpenBidirectionalStream(&stream_id))
- return;
-
- BaseObjectPtr<QuicStream> stream = QuicStream::New(session, stream_id);
- args.GetReturnValue().Set(stream->object());
-}
-
-void QuicStreamDestroy(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- QuicError error(env, args[0], args[1], QUIC_ERROR_APPLICATION);
- stream->Destroy(&error);
-}
-
-void QuicStreamReset(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
-
- QuicError error(env, args[0], args[1], QUIC_ERROR_APPLICATION);
-
- stream->ResetStream(
- error.family == QUIC_ERROR_APPLICATION ?
- error.code : static_cast<uint64_t>(NGTCP2_NO_ERROR));
-}
-
-void QuicStreamStopSending(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
-
- QuicError error(env, args[0], args[1], QUIC_ERROR_APPLICATION);
-
- stream->StopSending(
- error.family == QUIC_ERROR_APPLICATION ?
- error.code : static_cast<uint64_t>(NGTCP2_NO_ERROR));
-}
-
-// Requests transmission of a block of informational headers. Not all
-// QUIC Applications will support headers. If headers are not supported,
-// This will set the return value to false, otherwise the return value
-// is set to true
-void QuicStreamSubmitInformation(const FunctionCallbackInfo<Value>& args) {
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- CHECK(args[0]->IsArray());
- args.GetReturnValue().Set(stream->SubmitInformation(args[0].As<Array>()));
-}
-
-// Requests transmission of a block of initial headers. Not all
-// QUIC Applications will support headers. If headers are not supported,
-// this will set the return value to false, otherwise the return value
-// is set to true. For http/3, these may be request or response headers.
-void QuicStreamSubmitHeaders(const FunctionCallbackInfo<Value>& args) {
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- CHECK(args[0]->IsArray());
- uint32_t flags = QUICSTREAM_HEADER_FLAGS_NONE;
- CHECK(args[1]->Uint32Value(stream->env()->context()).To(&flags));
- args.GetReturnValue().Set(stream->SubmitHeaders(args[0].As<Array>(), flags));
-}
-
-// Requests transmission of a block of trailing headers. Not all
-// QUIC Applications will support headers. If headers are not supported,
-// this will set the return value to false, otherwise the return value
-// is set to true.
-void QuicStreamSubmitTrailers(const FunctionCallbackInfo<Value>& args) {
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- CHECK(args[0]->IsArray());
- args.GetReturnValue().Set(stream->SubmitTrailers(args[0].As<Array>()));
-}
-
-// Requests creation of a push stream. Not all QUIC Applications will
-// support push streams. If pushes are not supported, the return value
-// will be undefined, otherwise the return value will be the created
-// QuicStream representing the push.
-void QuicStreamSubmitPush(const FunctionCallbackInfo<Value>& args) {
- QuicStream* stream;
- ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
- CHECK(args[0]->IsArray());
- BaseObjectPtr<QuicStream> push_stream =
- stream->SubmitPush(args[0].As<Array>());
- if (push_stream)
- args.GetReturnValue().Set(push_stream->object());
-}
-
-} // namespace
-
-void QuicStream::Initialize(
- Environment* env,
- Local<Object> target,
- Local<Context> context) {
- Local<FunctionTemplate> stream = FunctionTemplate::New(env->isolate());
- stream->Inherit(AsyncWrap::GetConstructorTemplate(env));
- StreamBase::AddMethods(env, stream);
- Local<ObjectTemplate> streamt = stream->InstanceTemplate();
- streamt->SetInternalFieldCount(StreamBase::kInternalFieldCount);
- streamt->Set(env->owner_symbol(), Null(env->isolate()));
- env->SetProtoMethod(stream, "destroy", QuicStreamDestroy);
- env->SetProtoMethod(stream, "resetStream", QuicStreamReset);
- env->SetProtoMethod(stream, "stopSending", QuicStreamStopSending);
- env->SetProtoMethod(stream, "id", QuicStreamGetID);
- env->SetProtoMethod(stream, "submitInformation", QuicStreamSubmitInformation);
- env->SetProtoMethod(stream, "submitHeaders", QuicStreamSubmitHeaders);
- env->SetProtoMethod(stream, "submitTrailers", QuicStreamSubmitTrailers);
- env->SetProtoMethod(stream, "submitPush", QuicStreamSubmitPush);
- env->set_quicserverstream_instance_template(streamt);
- env->SetConstructorFunction(target, "QuicStream", stream);
-
- env->SetMethod(target, "openBidirectionalStream", OpenBidirectionalStream);
- env->SetMethod(target, "openUnidirectionalStream", OpenUnidirectionalStream);
-}
-
-} // namespace quic
-} // namespace node
diff --git a/src/quic/node_quic_stream.h b/src/quic/node_quic_stream.h
deleted file mode 100644
index 6cbdef2416..0000000000
--- a/src/quic/node_quic_stream.h
+++ /dev/null
@@ -1,409 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_STREAM_H_
-#define SRC_QUIC_NODE_QUIC_STREAM_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "memory_tracker.h"
-#include "aliased_struct.h"
-#include "async_wrap.h"
-#include "env.h"
-#include "node_http_common.h"
-#include "node_quic_state.h"
-#include "node_quic_util.h"
-#include "stream_base-inl.h"
-#include "util-inl.h"
-#include "v8.h"
-
-#include <string>
-#include <vector>
-
-namespace node {
-namespace quic {
-
-class QuicSession;
-class QuicStream;
-class QuicApplication;
-
-using QuicHeader = NgHeaderBase<QuicApplication>;
-
-enum QuicStreamHeaderFlags : uint32_t {
- // No flags
- QUICSTREAM_HEADER_FLAGS_NONE = 0,
-
- // Set if the initial headers are considered
- // terminal (that is, the stream should be closed
- // after transmitting the headers). If headers are
- // not supported by the QUIC Application, flag is
- // ignored.
- QUICSTREAM_HEADER_FLAGS_TERMINAL = 1
-};
-
-enum QuicStreamHeadersKind : int {
- QUICSTREAM_HEADERS_KIND_NONE = 0,
- QUICSTREAM_HEADERS_KIND_INFORMATIONAL,
- QUICSTREAM_HEADERS_KIND_INITIAL,
- QUICSTREAM_HEADERS_KIND_TRAILING,
- QUICSTREAM_HEADERS_KIND_PUSH
-};
-
-#define STREAM_STATS(V) \
- V(CREATED_AT, created_at, "Created At") \
- V(RECEIVED_AT, received_at, "Last Received At") \
- V(ACKED_AT, acked_at, "Last Acknowledged At") \
- V(CLOSING_AT, closing_at, "Closing At") \
- V(DESTROYED_AT, destroyed_at, "Destroyed At") \
- V(BYTES_RECEIVED, bytes_received, "Bytes Received") \
- V(BYTES_SENT, bytes_sent, "Bytes Sent") \
- V(MAX_OFFSET, max_offset, "Max Offset") \
- V(MAX_OFFSET_ACK, max_offset_ack, "Max Acknowledged Offset") \
- V(MAX_OFFSET_RECV, max_offset_received, "Max Received Offset") \
- V(FINAL_SIZE, final_size, "Final Size")
-
-#define V(name, _, __) IDX_QUIC_STREAM_STATS_##name,
-enum QuicStreamStatsIdx : int {
- STREAM_STATS(V)
- IDX_QUIC_STREAM_STATS_COUNT
-};
-#undef V
-
-#define V(_, name, __) uint64_t name;
-struct QuicStreamStats {
- STREAM_STATS(V)
-};
-#undef V
-
-struct QuicStreamStatsTraits {
- using Stats = QuicStreamStats;
- using Base = QuicStream;
-
- template <typename Fn>
- static void ToString(const Base& ptr, Fn&& add_field);
-};
-
-#define QUICSTREAM_SHARED_STATE(V) \
- V(WRITE_ENDED, write_ended, uint8_t) \
- V(READ_STARTED, read_started, uint8_t) \
- V(READ_PAUSED, read_paused, uint8_t) \
- V(READ_ENDED, read_ended, uint8_t) \
- V(FIN_SENT, fin_sent, uint8_t) \
- V(FIN_RECEIVED, fin_received, uint8_t)
-
-#define V(_, name, type) type name;
-struct QuicStreamState {
- QUICSTREAM_SHARED_STATE(V);
-};
-#undef V
-
-#define V(id, name, _) \
- IDX_QUICSTREAM_STATE_##id = offsetof(QuicStreamState, name),
-enum QuicStreamStateFields {
- QUICSTREAM_SHARED_STATE(V)
- IDX_QUICSTREAM_STATE_END
-};
-#undef V
-
-enum QuicStreamDirection {
- // The QuicStream is readable and writable in both directions
- QUIC_STREAM_BIRECTIONAL,
-
- // The QuicStream is writable and readable in only one direction.
- // The direction depends on the QuicStreamOrigin.
- QUIC_STREAM_UNIDIRECTIONAL
-};
-
-enum QuicStreamOrigin {
- // The QuicStream was created by the server.
- QUIC_STREAM_SERVER,
-
- // The QuicStream was created by the client.
- QUIC_STREAM_CLIENT
-};
-
-// QuicStream's are simple data flows that, fortunately, do not
-// require much. They may be:
-//
-// * Bidirectional or Unidirectional
-// * Server or Client Initiated
-//
-// The flow direction and origin of the stream are important in
-// determining the write and read state (Open or Closed). Specifically:
-//
-// A Unidirectional stream originating with the Server is:
-//
-// * Server Writable (Open) but not Client Writable (Closed)
-// * Client Readable (Open) but not Server Readable (Closed)
-//
-// Likewise, a Unidirectional stream originating with the
-// Client is:
-//
-// * Client Writable (Open) but not Server Writable (Closed)
-// * Server Readable (Open) but not Client Readable (Closed)
-//
-// Bidirectional Stream States
-// +------------+--------------+--------------------+---------------------+
-// | | Initiated By | Initial Read State | Initial Write State |
-// +------------+--------------+--------------------+---------------------+
-// | On Server | Server | Open | Open |
-// +------------+--------------+--------------------+---------------------+
-// | On Server | Client | Open | Open |
-// +------------+--------------+--------------------+---------------------+
-// | On Client | Server | Open | Open |
-// +------------+--------------+--------------------+---------------------+
-// | On Client | Client | Open | Open |
-// +------------+--------------+--------------------+---------------------+
-//
-// Unidirectional Stream States
-// +------------+--------------+--------------------+---------------------+
-// | | Initiated By | Initial Read State | Initial Write State |
-// +------------+--------------+--------------------+---------------------+
-// | On Server | Server | Closed | Open |
-// +------------+--------------+--------------------+---------------------+
-// | On Server | Client | Open | Closed |
-// +------------+--------------+--------------------+---------------------+
-// | On Client | Server | Open | Closed |
-// +------------+--------------+--------------------+---------------------+
-// | On Client | Client | Closed | Open |
-// +------------+--------------+--------------------+---------------------+
-//
-// All data sent via the QuicStream is buffered internally until either
-// receipt is acknowledged from the peer or attempts to send are abandoned.
-//
-// A QuicStream may be in a fully Closed (Read and Write) state but still
-// have unacknowledged data in it's outbound queue.
-//
-// A QuicStream is gracefully closed when (a) both Read and Write states
-// are Closed, (b) all queued data has been acknowledged.
-//
-// The JavaScript Writable side of the QuicStream may be shutdown before
-// all pending queued data has been serialized to frames. During this state,
-// no additional data may be queued to send.
-//
-// The Write state of a QuicStream will not be closed while there is still
-// pending writes on the JavaScript side.
-//
-// The QuicStream may be forcefully closed immediately using destroy(err).
-// This causes all queued data and pending JavaScript writes to be
-// abandoned, and causes the QuicStream to be immediately closed at the
-// ngtcp2 level.
-class QuicStream : public AsyncWrap,
- public bob::SourceImpl<ngtcp2_vec>,
- public StreamBase,
- public StatsBase<QuicStreamStatsTraits> {
- public:
- static void Initialize(
- Environment* env,
- v8::Local<v8::Object> target,
- v8::Local<v8::Context> context);
-
- static BaseObjectPtr<QuicStream> New(
- QuicSession* session,
- int64_t stream_id,
- int64_t push_id = 0);
-
- QuicStream(
- QuicSession* session,
- v8::Local<v8::Object> target,
- int64_t stream_id,
- int64_t push_id = 0);
-
- ~QuicStream() override;
-
- std::string diagnostic_name() const override;
-
- // The numeric identifier of the QuicStream.
- int64_t id() const { return stream_id_; }
-
- // If the QuicStream is associated with a push promise,
- // the numeric identifier of the promise. Currently only
- // used by HTTP/3.
- int64_t push_id() const { return push_id_; }
-
- QuicSession* session() const { return session_.get(); }
-
- // A QuicStream can be either uni- or bi-directional.
- inline QuicStreamDirection direction() const;
-
- // A QuicStream can be initiated by either the client
- // or the server.
- inline QuicStreamOrigin origin() const;
-
- inline void set_fin_sent();
-
- inline bool is_destroyed() const { return destroyed_; }
-
- inline void set_destroyed();
-
- // A QuicStream will not be writable if:
- // - The streambuf_ is ended
- // - It is a Unidirectional stream originating from the peer
- inline bool is_writable() const;
-
- // A QuicStream will not be readable if:
- // - The read ended flag is set or
- // - It is a Unidirectional stream originating from the local peer.
- inline bool is_readable() const;
-
- // IsWriteFinished will return true if a final stream frame
- // has been sent and all data has been acknowledged (the
- // send buffer is empty).
- inline bool is_write_finished() const;
-
- // Specifies the kind of headers currently being processed.
- inline void set_headers_kind(QuicStreamHeadersKind kind);
-
- // Set the final size for the QuicStream. This only works
- // the first time it is called. Subsequent calls will be
- // ignored unless the subsequent size is greater than the
- // prior set size, in which case we have a bug and we'll
- // assert.
- inline void set_final_size(uint64_t final_size);
-
- // The final size is the maximum amount of data that has been
- // acknowleged to have been received for a QuicStream.
- uint64_t final_size() const {
- return GetStat(&QuicStreamStats::final_size);
- }
-
- // Marks the given data range as having been acknowledged.
- // This means that the data range may be released from
- // memory.
- void Acknowledge(uint64_t offset, size_t datalen);
-
- // Destroy the QuicStream and render it no longer usable.
- void Destroy(QuicError* error = nullptr);
-
- inline void CancelPendingWrites();
-
- // Buffers chunks of data to be written to the QUIC connection.
- int DoWrite(
- WriteWrap* req_wrap,
- uv_buf_t* bufs,
- size_t nbufs,
- uv_stream_t* send_handle) override;
-
- // Returns false if the header cannot be added. This will
- // typically only happen if a maximimum number of headers
- // has been reached.
- bool AddHeader(std::unique_ptr<QuicHeader> header);
-
- // Some QUIC applications support headers, others do not.
- // The following methods allow consistent handling of
- // headers at the QuicStream level regardless of the
- // protocol. For applications that do not support headers,
- // these are simply not used.
- inline void BeginHeaders(
- QuicStreamHeadersKind kind = QUICSTREAM_HEADERS_KIND_NONE);
-
- // Indicates an amount of unacknowledged data that has been
- // submitted to the QUIC connection.
- inline void Commit(size_t amount);
-
- inline void EndHeaders(int64_t push_id = 0);
-
- // Passes a chunk of data on to the QuicStream listener.
- void ReceiveData(
- uint32_t flags,
- const uint8_t* data,
- size_t datalen,
- uint64_t offset);
-
- // Resets the QUIC stream, sending a signal to the peer that
- // no additional data will be transmitted for this stream.
- inline void ResetStream(uint64_t app_error_code = NGTCP2_NO_ERROR);
-
- inline void StopSending(uint64_t app_error_code = NGTCP2_NO_ERROR);
-
- // Submits informational headers. Returns false if headers are not
- // supported on the underlying QuicApplication.
- inline bool SubmitInformation(v8::Local<v8::Array> headers);
-
- // Submits initial headers. Returns false if headers are not
- // supported on the underlying QuicApplication.
- inline bool SubmitHeaders(v8::Local<v8::Array> headers, uint32_t flags);
-
- // Submits trailing headers. Returns false if headers are not
- // supported on the underlying QuicApplication.
- inline bool SubmitTrailers(v8::Local<v8::Array> headers);
-
- inline BaseObjectPtr<QuicStream> SubmitPush(v8::Local<v8::Array> headers);
-
- // Required for StreamBase
- bool IsAlive() override;
-
- // Required for StreamBase
- bool IsClosing() override;
-
- // Required for StreamBase
- int ReadStart() override;
-
- // Required for StreamBase
- int ReadStop() override;
-
- // Required for StreamBase
- int DoShutdown(ShutdownWrap* req_wrap) override;
-
- AsyncWrap* GetAsyncWrap() override { return this; }
-
- QuicState* quic_state() { return quic_state_.get(); }
-
- // Required for MemoryRetainer
- void MemoryInfo(MemoryTracker* tracker) const override;
- SET_MEMORY_INFO_NAME(QuicStream)
- SET_SELF_SIZE(QuicStream)
-
- protected:
- int DoPull(
- bob::Next<ngtcp2_vec> next,
- int options,
- ngtcp2_vec* data,
- size_t count,
- size_t max_count_hint) override;
-
- private:
- // WasEverWritable returns true if it is a bidirectional stream,
- // or a Unidirectional stream originating from the local peer.
- // If was_ever_writable() is false, then no stream frames should
- // ever be sent from the local peer, including final stream frames.
- inline bool was_ever_writable() const;
-
- // WasEverReadable returns true if it is a bidirectional stream,
- // or a Unidirectional stream originating from the remote
- // peer.
- inline bool was_ever_readable() const;
-
- void IncrementStats(size_t datalen);
-
- BaseObjectWeakPtr<QuicSession> session_;
- QuicBuffer streambuf_;
-
- int64_t stream_id_ = 0;
- int64_t push_id_ = 0;
- bool destroyed_ = false;
- AliasedStruct<QuicStreamState> state_;
- DoneCB shutdown_done_ = nullptr;
-
- size_t inbound_consumed_data_while_paused_ = 0;
-
- std::vector<std::unique_ptr<QuicHeader>> headers_;
- QuicStreamHeadersKind headers_kind_;
- size_t current_headers_length_ = 0;
-
- ListNode<QuicStream> stream_queue_;
-
- BaseObjectPtr<QuicState> quic_state_;
-
- public:
- // Linked List of QuicStream objects
- using Queue = ListHead<QuicStream, &QuicStream::stream_queue_>;
-
- inline void Schedule(Queue* queue);
-
- inline void Unschedule();
-};
-
-} // namespace quic
-} // namespace node
-
-#endif // NODE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_STREAM_H_
diff --git a/src/quic/node_quic_util-inl.h b/src/quic/node_quic_util-inl.h
deleted file mode 100644
index 65b2e08823..0000000000
--- a/src/quic/node_quic_util-inl.h
+++ /dev/null
@@ -1,435 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_UTIL_INL_H_
-#define SRC_QUIC_NODE_QUIC_UTIL_INL_H_
-
-#include "debug_utils-inl.h"
-#include "node_internals.h"
-#include "node_quic_crypto.h"
-#include "node_quic_util.h"
-#include "memory_tracker-inl.h"
-#include "env-inl.h"
-#include "histogram-inl.h"
-#include "string_bytes.h"
-#include "util-inl.h"
-#include "uv.h"
-
-#include <string>
-
-namespace node {
-
-namespace quic {
-
-QuicPath::QuicPath(
- const SocketAddress& local,
- const SocketAddress& remote) {
- ngtcp2_addr_init(
- &this->local,
- local.data(),
- local.length(),
- const_cast<SocketAddress*>(&local));
- ngtcp2_addr_init(
- &this->remote,
- remote.data(),
- remote.length(),
- const_cast<SocketAddress*>(&remote));
-}
-
-size_t QuicCID::Hash::operator()(const QuicCID& token) const {
- size_t hash = 0;
- for (size_t n = 0; n < token->datalen; n++) {
- hash ^= std::hash<uint8_t>{}(token->data[n]) + 0x9e3779b9 +
- (hash << 6) + (hash >> 2);
- }
- return hash;
-}
-
-QuicCID& QuicCID::operator=(const QuicCID& cid) {
- if (this == &cid) return *this;
- this->~QuicCID();
- return *new(this) QuicCID(std::move(cid));
-}
-
-bool QuicCID::operator==(const QuicCID& other) const {
- return memcmp(cid()->data, other.cid()->data, cid()->datalen) == 0;
-}
-
-bool QuicCID::operator!=(const QuicCID& other) const {
- return !(*this == other);
-}
-
-std::string QuicCID::ToString() const {
- std::vector<char> dest(ptr_->datalen * 2 + 1);
- dest[dest.size() - 1] = '\0';
- size_t written = StringBytes::hex_encode(
- reinterpret_cast<const char*>(ptr_->data),
- ptr_->datalen,
- dest.data(),
- dest.size());
- return std::string(dest.data(), written);
-}
-
-size_t GetMaxPktLen(const SocketAddress& addr) {
- return addr.family() == AF_INET6 ?
- NGTCP2_MAX_PKTLEN_IPV6 :
- NGTCP2_MAX_PKTLEN_IPV4;
-}
-
-QuicError::QuicError(
- int32_t family_,
- uint64_t code_) :
- family(family_),
- code(code_) {}
-
-QuicError::QuicError(
- int32_t family_,
- int code_) :
- family(family_) {
- switch (family) {
- case QUIC_ERROR_CRYPTO:
- code_ |= NGTCP2_CRYPTO_ERROR;
- // Fall-through...
- case QUIC_ERROR_SESSION:
- code = ngtcp2_err_infer_quic_transport_error_code(code_);
- break;
- case QUIC_ERROR_APPLICATION:
- code = code_;
- break;
- default:
- UNREACHABLE();
- }
-}
-
-QuicError::QuicError(ngtcp2_connection_close_error_code ccec) :
- family(QUIC_ERROR_SESSION),
- code(ccec.error_code) {
- switch (ccec.type) {
- case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION:
- family = QUIC_ERROR_APPLICATION;
- break;
- case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT:
- if (code & NGTCP2_CRYPTO_ERROR)
- family = QUIC_ERROR_CRYPTO;
- break;
- default:
- UNREACHABLE();
- }
-}
-
-QuicError::QuicError(
- Environment* env,
- v8::Local<v8::Value> codeArg,
- v8::Local<v8::Value> familyArg,
- int32_t family_) :
- family(family_),
- code(NGTCP2_NO_ERROR) {
- if (codeArg->IsBigInt()) {
- code = codeArg.As<v8::BigInt>()->Int64Value();
- } else if (codeArg->IsNumber()) {
- double num = 0;
- CHECK(codeArg->NumberValue(env->context()).To(&num));
- code = static_cast<uint64_t>(num);
- }
- if (familyArg->IsNumber()) {
- CHECK(familyArg->Int32Value(env->context()).To(&family));
- }
-}
-
-const char* QuicError::family_name() {
- switch (family) {
- case QUIC_ERROR_SESSION:
- return "Session";
- case QUIC_ERROR_APPLICATION:
- return "Application";
- case QUIC_ERROR_CRYPTO:
- return "Crypto";
- default:
- UNREACHABLE();
- }
-}
-
-const ngtcp2_cid* PreferredAddress::cid() const {
- return &paddr_->cid;
-}
-
-const uint8_t* PreferredAddress::stateless_reset_token() const {
- return paddr_->stateless_reset_token;
-}
-
-std::string PreferredAddress::ipv6_address() const {
- char host[NI_MAXHOST];
- // Return an empty string if unable to convert...
- if (uv_inet_ntop(AF_INET6, paddr_->ipv6_addr, host, sizeof(host)) != 0)
- return std::string();
-
- return std::string(host);
-}
-std::string PreferredAddress::ipv4_address() const {
- char host[NI_MAXHOST];
- // Return an empty string if unable to convert...
- if (uv_inet_ntop(AF_INET, paddr_->ipv4_addr, host, sizeof(host)) != 0)
- return std::string();
-
- return std::string(host);
-}
-
-uint16_t PreferredAddress::ipv6_port() const {
- return paddr_->ipv6_port;
-}
-
-uint16_t PreferredAddress::ipv4_port() const {
- return paddr_->ipv4_port;
-}
-
-bool PreferredAddress::Use(int family) const {
- uv_getaddrinfo_t req;
-
- if (!ResolvePreferredAddress(family, &req))
- return false;
-
- dest_->addrlen = req.addrinfo->ai_addrlen;
- memcpy(dest_->addr, req.addrinfo->ai_addr, req.addrinfo->ai_addrlen);
- uv_freeaddrinfo(req.addrinfo);
- return true;
-}
-
-bool PreferredAddress::ResolvePreferredAddress(
- int local_address_family,
- uv_getaddrinfo_t* req) const {
- int af;
- const uint8_t* binaddr;
- uint16_t port;
- switch (local_address_family) {
- case AF_INET:
- if (paddr_->ipv4_port > 0) {
- af = AF_INET;
- binaddr = paddr_->ipv4_addr;
- port = paddr_->ipv4_port;
- break;
- }
- return false;
- case AF_INET6:
- if (paddr_->ipv6_port > 0) {
- af = AF_INET6;
- binaddr = paddr_->ipv6_addr;
- port = paddr_->ipv6_port;
- break;
- }
- return false;
- default:
- UNREACHABLE();
- }
-
- char host[NI_MAXHOST];
- if (uv_inet_ntop(af, binaddr, host, sizeof(host)) != 0)
- return false;
-
- addrinfo hints{};
- hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
- hints.ai_family = af;
- hints.ai_socktype = SOCK_DGRAM;
-
- // Unfortunately ngtcp2 requires the selection of the
- // preferred address to be synchronous, which means we
- // have to do a sync resolve using uv_getaddrinfo here.
- return
- uv_getaddrinfo(
- env_->event_loop(),
- req,
- nullptr,
- host,
- std::to_string(port).c_str(),
- &hints) == 0 &&
- req->addrinfo != nullptr;
-}
-
-StatelessResetToken::StatelessResetToken(
- uint8_t* token,
- const uint8_t* secret,
- const QuicCID& cid) {
- GenerateResetToken(token, secret, cid);
- memcpy(buf_, token, sizeof(buf_));
-}
-
-StatelessResetToken::StatelessResetToken(
- const uint8_t* secret,
- const QuicCID& cid) {
- GenerateResetToken(buf_, secret, cid);
-}
-
-StatelessResetToken::StatelessResetToken(
- const uint8_t* token) {
- memcpy(buf_, token, sizeof(buf_));
-}
-
-std::string StatelessResetToken::ToString() const {
- std::vector<char> dest(NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1);
- dest[dest.size() - 1] = '\0';
- size_t written = StringBytes::hex_encode(
- reinterpret_cast<const char*>(buf_),
- NGTCP2_STATELESS_RESET_TOKENLEN,
- dest.data(),
- dest.size());
- return std::string(dest.data(), written);
-}
-
-size_t StatelessResetToken::Hash::operator()(
- const StatelessResetToken& token) const {
- size_t hash = 0;
- for (size_t n = 0; n < NGTCP2_STATELESS_RESET_TOKENLEN; n++)
- hash ^= std::hash<uint8_t>{}(token.buf_[n]) + 0x9e3779b9 +
- (hash << 6) + (hash >> 2);
- return hash;
-}
-
-bool StatelessResetToken::operator==(const StatelessResetToken& other) const {
- return memcmp(data(), other.data(), NGTCP2_STATELESS_RESET_TOKENLEN) == 0;
-}
-
-bool StatelessResetToken::operator!=(const StatelessResetToken& other) const {
- return !(*this == other);
-}
-
-template <typename T>
-StatsBase<T>::StatsBase(
- Environment* env,
- v8::Local<v8::Object> wrap,
- int options) {
- static constexpr uint64_t kMax = std::numeric_limits<int64_t>::max();
-
- // Create the backing store for the statistics
- size_t size = sizeof(Stats);
- size_t count = size / sizeof(uint64_t);
- stats_store_ = v8::ArrayBuffer::NewBackingStore(env->isolate(), size);
- stats_ = new (stats_store_->Data()) Stats;
-
- DCHECK_NOT_NULL(stats_);
- stats_->created_at = uv_hrtime();
-
- // The stats buffer is exposed as a BigUint64Array on
- // the JavaScript side to allow statistics to be monitored.
- v8::Local<v8::ArrayBuffer> stats_buffer =
- v8::ArrayBuffer::New(env->isolate(), stats_store_);
- v8::Local<v8::BigUint64Array> stats_array =
- v8::BigUint64Array::New(stats_buffer, 0, count);
- USE(wrap->DefineOwnProperty(
- env->context(),
- env->stats_string(),
- stats_array,
- v8::PropertyAttribute::ReadOnly));
-
- if (options & HistogramOptions::ACK) {
- ack_ = HistogramBase::New(env, 1, kMax);
- wrap->DefineOwnProperty(
- env->context(),
- env->ack_string(),
- ack_->object(),
- v8::PropertyAttribute::ReadOnly).Check();
- }
-
- if (options & HistogramOptions::RATE) {
- rate_ = HistogramBase::New(env, 1, kMax);
- wrap->DefineOwnProperty(
- env->context(),
- env->rate_string(),
- rate_->object(),
- v8::PropertyAttribute::ReadOnly).Check();
- }
-
- if (options & HistogramOptions::SIZE) {
- size_ = HistogramBase::New(env, 1, kMax);
- wrap->DefineOwnProperty(
- env->context(),
- env->size_string(),
- size_->object(),
- v8::PropertyAttribute::ReadOnly).Check();
- }
-}
-
-template <typename T>
-void StatsBase<T>::IncrementStat(uint64_t Stats::*member, uint64_t amount) {
- static constexpr uint64_t kMax = std::numeric_limits<uint64_t>::max();
- stats_->*member += std::min(amount, kMax - stats_->*member);
-}
-
-template <typename T>
-void StatsBase<T>::SetStat(uint64_t Stats::*member, uint64_t value) {
- stats_->*member = value;
-}
-
-template <typename T>
-void StatsBase<T>::RecordTimestamp(uint64_t Stats::*member) {
- stats_->*member = uv_hrtime();
-}
-
-template <typename T>
-uint64_t StatsBase<T>::GetStat(uint64_t Stats::*member) const {
- return stats_->*member;
-}
-
-template <typename T>
-inline void StatsBase<T>::RecordRate(uint64_t Stats::*member) {
- CHECK(rate_);
- uint64_t received_at = GetStat(member);
- uint64_t now = uv_hrtime();
- if (received_at > 0)
- rate_->Record(now - received_at);
- SetStat(member, now);
-}
-
-template <typename T>
-inline void StatsBase<T>::RecordSize(uint64_t val) {
- CHECK(size_);
- size_->Record(val);
-}
-
-template <typename T>
-inline void StatsBase<T>::RecordAck(uint64_t Stats::*member) {
- CHECK(ack_);
- uint64_t acked_at = GetStat(member);
- uint64_t now = uv_hrtime();
- if (acked_at > 0)
- ack_->Record(now - acked_at);
- SetStat(member, now);
-}
-
-template <typename T>
-void StatsBase<T>::StatsMemoryInfo(MemoryTracker* tracker) const {
- tracker->TrackField("stats_store", stats_store_);
- tracker->TrackField("rate_histogram", rate_);
- tracker->TrackField("size_histogram", size_);
- tracker->TrackField("ack_histogram", ack_);
-}
-
-template <typename T>
-void StatsBase<T>::DebugStats() {
- StatsDebug stats_debug(static_cast<typename T::Base*>(this));
- Debug(static_cast<typename T::Base*>(this), "Destroyed. %s", stats_debug);
-}
-
-template <typename T>
-std::string StatsBase<T>::StatsDebug::ToString() const {
- std::string out = "Statistics:\n";
- auto add_field = [&out](const char* name, uint64_t val) {
- out += " ";
- out += std::string(name);
- out += ": ";
- out += std::to_string(val);
- out += "\n";
- };
- add_field("Duration", uv_hrtime() - ptr->GetStat(&Stats::created_at));
- T::ToString(*ptr, add_field);
- return out;
-}
-
-template <typename T>
-size_t get_length(const T* vec, size_t count) {
- CHECK_NOT_NULL(vec);
- size_t len = 0;
- for (size_t n = 0; n < count; n++)
- len += vec[n].len;
- return len;
-}
-
-} // namespace quic
-} // namespace node
-
-#endif // SRC_QUIC_NODE_QUIC_UTIL_INL_H_
diff --git a/src/quic/node_quic_util.h b/src/quic/node_quic_util.h
deleted file mode 100644
index b3afcb9483..0000000000
--- a/src/quic/node_quic_util.h
+++ /dev/null
@@ -1,394 +0,0 @@
-#ifndef SRC_QUIC_NODE_QUIC_UTIL_H_
-#define SRC_QUIC_NODE_QUIC_UTIL_H_
-
-#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-
-#include "node.h"
-#include "node_sockaddr.h"
-#include "uv.h"
-#include "v8.h"
-#include "histogram.h"
-#include "memory_tracker.h"
-
-#include <ngtcp2/ngtcp2.h>
-#include <openssl/ssl.h>
-
-#include <algorithm>
-#include <functional>
-#include <limits>
-#include <string>
-#include <unordered_map>
-
-namespace node {
-namespace quic {
-
-// k-constants are used internally, all-caps constants
-// are exposed to javascript as constants (see node_quic.cc)
-
-constexpr size_t kMaxSizeT = std::numeric_limits<size_t>::max();
-constexpr size_t kMaxValidateAddressLru = 10;
-constexpr size_t kMinInitialQuicPktSize = 1200;
-constexpr size_t kScidLen = NGTCP2_MAX_CIDLEN;
-constexpr size_t kTokenRandLen = 16;
-constexpr size_t kTokenSecretLen = 16;
-
-constexpr uint64_t DEFAULT_ACTIVE_CONNECTION_ID_LIMIT = 2;
-constexpr uint64_t DEFAULT_MAX_CONNECTIONS =
- std::min<uint64_t>(kMaxSizeT, kMaxSafeJsInteger);
-constexpr uint64_t DEFAULT_MAX_CONNECTIONS_PER_HOST = 100;
-constexpr uint64_t DEFAULT_MAX_STREAM_DATA_BIDI_LOCAL = 256 * 1024;
-constexpr uint64_t DEFAULT_MAX_STREAM_DATA_BIDI_REMOTE = 256 * 1024;
-constexpr uint64_t DEFAULT_MAX_STREAM_DATA_UNI = 256 * 1024;
-constexpr uint64_t DEFAULT_MAX_DATA = 1 * 1024 * 1024;
-constexpr uint64_t DEFAULT_MAX_STATELESS_RESETS_PER_HOST = 10;
-constexpr uint64_t DEFAULT_MAX_STREAMS_BIDI = 100;
-constexpr uint64_t DEFAULT_MAX_STREAMS_UNI = 3;
-constexpr uint64_t DEFAULT_MAX_IDLE_TIMEOUT = 10;
-constexpr uint64_t DEFAULT_RETRYTOKEN_EXPIRATION = 10;
-constexpr uint64_t MIN_RETRYTOKEN_EXPIRATION = 1;
-constexpr uint64_t MAX_RETRYTOKEN_EXPIRATION = 60;
-constexpr uint64_t NGTCP2_APP_NOERROR = 0xff00;
-
-constexpr int ERR_FAILED_TO_CREATE_SESSION = -1;
-
-// The preferred address policy determines how a client QuicSession
-// handles a server-advertised preferred address. As suggested, the
-// preferred address is the address the server would prefer the
-// client to use for subsequent communication for a QuicSession.
-// The client may choose to ignore the preference but really shouldn't
-// without good reason. We currently only support two options but
-// additional options may be added later.
-enum SelectPreferredAddressPolicy : int {
- // Ignore the server-provided preferred address
- QUIC_PREFERRED_ADDRESS_IGNORE,
-
- // Use the server-provided preferred address.
- // With this policy in effect, when a client
- // receives a preferred address from the server,
- // the client QuicSession will be automatically
- // switched to use the selected address if it
- // matches the current local address family.
- QUIC_PREFERRED_ADDRESS_USE
-};
-
-// QUIC error codes generally fall into two distinct namespaces:
-// Connection Errors and Application Errors. Connection errors
-// are further subdivided into Crypto and non-Crypto. Application
-// errors are entirely specific to the QUIC application being
-// used. An easy rule of thumb is that Application errors are
-// semantically associated with the ALPN identifier negotiated
-// for the QuicSession. So, if a connection is closed with
-// family: QUIC_ERROR_APPLICATION and code: 123, you have to
-// look at the ALPN identifier to determine exactly what it
-// means. Connection (Session) and Crypto errors, on the other
-// hand, share the same meaning regardless of the ALPN.
-enum QuicErrorFamily : int32_t {
- QUIC_ERROR_SESSION,
- QUIC_ERROR_CRYPTO,
- QUIC_ERROR_APPLICATION
-};
-
-
-template <typename T> class StatsBase;
-
-template <typename T, typename Q>
-struct StatsTraits {
- using Stats = T;
- using Base = Q;
-
- template <typename Fn>
- static void ToString(const Q& ptr, Fn&& add_field);
-};
-
-// StatsBase is a utility help for classes (like QuicSession)
-// that record performance statistics. The template takes a
-// single Traits argument (see QuicStreamStatsTraits in
-// node_quic_stream.h as an example). When the StatsBase
-// is deconstructed, collected statistics are output to
-// Debug automatically.
-template <typename T>
-class StatsBase {
- public:
- typedef typename T::Stats Stats;
-
- // A StatsBase instance may have one of three histogram
- // instances. One that records rate of data flow, one
- // that records size of data chunk, and one that records
- // rate of data acknowledgement. These may be used in
- // slightly different ways of different StatsBase
- // instances or may be turned off entirely.
- enum HistogramOptions {
- NONE = 0,
- RATE = 1,
- SIZE = 2,
- ACK = 4
- };
-
- inline StatsBase(
- Environment* env,
- v8::Local<v8::Object> wrap,
- int options = HistogramOptions::NONE);
-
- inline ~StatsBase() { if (stats_ != nullptr) stats_->~Stats(); }
-
- // The StatsDebug utility is used when StatsBase is destroyed
- // to output statistical information to Debug. It is designed
- // to only incur a performance cost constructing the debug
- // output when Debug output is enabled.
- struct StatsDebug {
- typename T::Base* ptr;
- explicit StatsDebug(typename T::Base* ptr_) : ptr(ptr_) {}
- std::string ToString() const;
- };
-
- // Increments the given stat field by the given amount or 1 if
- // no amount is specified.
- inline void IncrementStat(uint64_t Stats::*member, uint64_t amount = 1);
-
- // Sets an entirely new value for the given stat field
- inline void SetStat(uint64_t Stats::*member, uint64_t value);
-
- // Sets the given stat field to the current uv_hrtime()
- inline void RecordTimestamp(uint64_t Stats::*member);
-
- // Gets the current value of the given stat field
- inline uint64_t GetStat(uint64_t Stats::*member) const;
-
- // If the rate histogram is used, records the time elapsed
- // between now and the timestamp specified by the member
- // field.
- inline void RecordRate(uint64_t Stats::*member);
-
- // If the size histogram is used, records the given size.
- inline void RecordSize(uint64_t val);
-
- // If the ack rate histogram is used, records the time
- // elapsed between now and the timestamp specified by
- // the member field.
- inline void RecordAck(uint64_t Stats::*member);
-
- inline void StatsMemoryInfo(MemoryTracker* tracker) const;
-
- inline void DebugStats();
-
- private:
- BaseObjectPtr<HistogramBase> rate_;
- BaseObjectPtr<HistogramBase> size_;
- BaseObjectPtr<HistogramBase> ack_;
- std::shared_ptr<v8::BackingStore> stats_store_;
- Stats* stats_ = nullptr;
-};
-
-// PreferredAddress is a helper class used only when a client QuicSession
-// receives an advertised preferred address from a server. The helper provides
-// information about the preferred address. The Use() function is used to let
-// ngtcp2 know to use the preferred address for the given family.
-class PreferredAddress {
- public:
- PreferredAddress(
- Environment* env,
- ngtcp2_addr* dest,
- const ngtcp2_preferred_addr* paddr) :
- env_(env),
- dest_(dest),
- paddr_(paddr) {}
-
- // When a preferred address is advertised by a server, the
- // advertisement also includes a new CID and (optionally)
- // a stateless reset token. If the preferred address is
- // selected, then the client QuicSession will make use of
- // these new values. Access to the cid and reset token
- // are provided via the PreferredAddress class only as a
- // convenience.
- inline const ngtcp2_cid* cid() const;
-
- // The stateless reset token associated with the preferred
- // address CID
- inline const uint8_t* stateless_reset_token() const;
-
- // A preferred address advertisement may include both an
- // IPv4 and IPv6 address. Only one of which will be used.
-
- inline std::string ipv4_address() const;
-
- inline uint16_t ipv4_port() const;
-
- inline std::string ipv6_address() const;
-
- inline uint16_t ipv6_port() const;
-
- // Instructs the QuicSession to use the advertised
- // preferred address matching the given family. If
- // the advertisement does not include a matching
- // address, the preferred address is ignored.
- inline bool Use(int family = AF_INET) const;
-
- private:
- inline bool ResolvePreferredAddress(
- int local_address_family,
- uv_getaddrinfo_t* req) const;
-
- Environment* env_;
- mutable ngtcp2_addr* dest_;
- const ngtcp2_preferred_addr* paddr_;
-};
-
-// QuicError is a helper class used to encapsulate basic
-// details about a QUIC protocol error. There are three
-// basic types of errors (see QuicErrorFamily)
-struct QuicError {
- int32_t family;
- uint64_t code;
- inline QuicError(
- int32_t family_ = QUIC_ERROR_SESSION,
- int code_ = NGTCP2_NO_ERROR);
- inline QuicError(
- int32_t family_ = QUIC_ERROR_SESSION,
- uint64_t code_ = NGTCP2_NO_ERROR);
- explicit inline QuicError(ngtcp2_connection_close_error_code code);
- inline QuicError(
- Environment* env,
- v8::Local<v8::Value> codeArg,
- v8::Local<v8::Value> familyArg = v8::Local<v8::Object>(),
- int32_t family_ = QUIC_ERROR_SESSION);
- inline const char* family_name();
-};
-
-// Helper function that returns the maximum QUIC packet size for
-// the given socket address.
-inline size_t GetMaxPktLen(const SocketAddress& addr);
-
-// QuicPath is a utility class that wraps ngtcp2_path to adapt
-// it to work with SocketAddress
-struct QuicPath : public ngtcp2_path {
- inline QuicPath(const SocketAddress& local, const SocketAddress& remote);
-};
-
-struct QuicPathStorage : public ngtcp2_path_storage {
- QuicPathStorage() {
- ngtcp2_path_storage_zero(this);
- }
-};
-
-// Simple wrapper for ngtcp2_cid that handles hex encoding
-// CIDs are used to identify QuicSession instances and may
-// be between 0 and 20 bytes in length.
-class QuicCID : public MemoryRetainer {
- public:
- // Empty constructor
- QuicCID() : ptr_(&cid_) {}
-
- // Copy constructor
- QuicCID(const QuicCID& cid) : QuicCID(cid->data, cid->datalen) {}
-
- // Copy constructor
- explicit QuicCID(const ngtcp2_cid& cid) : QuicCID(cid.data, cid.datalen) {}
-
- // Wrap constructor
- explicit QuicCID(const ngtcp2_cid* cid) : ptr_(cid) {}
-
- QuicCID(const uint8_t* cid, size_t len) : QuicCID() {
- ngtcp2_cid* ptr = this->cid();
- ngtcp2_cid_init(ptr, cid, len);
- ptr_ = ptr;
- }
-
- struct Hash {
- inline size_t operator()(const QuicCID& cid) const;
- };
-
- inline bool operator==(const QuicCID& other) const;
- inline bool operator!=(const QuicCID& other) const;
- inline QuicCID& operator=(const QuicCID& cid);
- const ngtcp2_cid& operator*() const { return *ptr_; }
- const ngtcp2_cid* operator->() const { return ptr_; }
-
- inline std::string ToString() const;
-
- const ngtcp2_cid* cid() const { return ptr_; }
-
- const uint8_t* data() const { return ptr_->data; }
-
- operator bool() const { return ptr_->datalen > 0; }
-
- size_t length() const { return ptr_->datalen; }
-
- ngtcp2_cid* cid() {
- CHECK_EQ(ptr_, &cid_);
- return &cid_;
- }
-
- unsigned char* data() {
- return reinterpret_cast<unsigned char*>(cid()->data);
- }
-
- void set_length(size_t length) {
- cid()->datalen = length;
- }
-
- SET_NO_MEMORY_INFO()
- SET_MEMORY_INFO_NAME(QuicCID)
- SET_SELF_SIZE(QuicCID)
-
- template <typename T>
- using Map = std::unordered_map<QuicCID, T, QuicCID::Hash>;
-
- private:
- ngtcp2_cid cid_{};
- const ngtcp2_cid* ptr_;
-};
-
-// A Stateless Reset Token is a mechanism by which a QUIC
-// endpoint can discreetly signal to a peer that it has
-// lost all state associated with a connection. This
-// helper class is used to both store received tokens and
-// provide storage when creating new tokens to send.
-class StatelessResetToken : public MemoryRetainer {
- public:
- inline StatelessResetToken(
- uint8_t* token,
- const uint8_t* secret,
- const QuicCID& cid);
-
- inline StatelessResetToken(
- const uint8_t* secret,
- const QuicCID& cid);
-
- explicit inline StatelessResetToken(
- const uint8_t* token);
-
- inline std::string ToString() const;
-
- const uint8_t* data() const { return buf_; }
-
- struct Hash {
- inline size_t operator()(const StatelessResetToken& token) const;
- };
-
- inline bool operator==(const StatelessResetToken& other) const;
- inline bool operator!=(const StatelessResetToken& other) const;
-
- SET_NO_MEMORY_INFO()
- SET_MEMORY_INFO_NAME(StatelessResetToken)
- SET_SELF_SIZE(StatelessResetToken)
-
- template <typename T>
- using Map =
- std::unordered_map<
- StatelessResetToken,
- BaseObjectPtr<T>,
- StatelessResetToken::Hash>;
-
- private:
- uint8_t buf_[NGTCP2_STATELESS_RESET_TOKENLEN]{};
-};
-
-template <typename T>
-inline size_t get_length(const T*, size_t len);
-
-} // namespace quic
-} // namespace node
-
-#endif // NOE_WANT_INTERNALS
-
-#endif // SRC_QUIC_NODE_QUIC_UTIL_H_
diff --git a/test/cctest/test_quic_buffer.cc b/test/cctest/test_quic_buffer.cc
deleted file mode 100644
index 0aa1821633..0000000000
--- a/test/cctest/test_quic_buffer.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-#include "quic/node_quic_buffer-inl.h"
-#include "node_bob-inl.h"
-#include "util-inl.h"
-#include "uv.h"
-
-#include "gtest/gtest.h"
-#include <memory>
-#include <vector>
-
-using node::quic::QuicBuffer;
-using node::quic::QuicBufferChunk;
-using node::bob::Status;
-using node::bob::Options;
-using node::bob::Done;
-using ::testing::AssertionSuccess;
-using ::testing::AssertionFailure;
-
-::testing::AssertionResult IsEqual(size_t actual, int expected) {
- return (static_cast<size_t>(expected) == actual) ? AssertionSuccess() :
- AssertionFailure() << actual << " is not equal to " << expected;
-}
-
-TEST(QuicBuffer, Simple) {
- char data[100];
- memset(&data, 0, node::arraysize(data));
- uv_buf_t buf = uv_buf_init(data, node::arraysize(data));
-
- bool done = false;
-
- QuicBuffer buffer;
- buffer.Push(&buf, 1, [&](int status) {
- EXPECT_EQ(0, status);
- done = true;
- });
-
- buffer.Consume(100);
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-
- // We have to move the read head forward in order to consume
- buffer.Seek(1);
- buffer.Consume(100);
- ASSERT_TRUE(done);
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-}
-
-TEST(QuicBuffer, ConsumeMore) {
- char data[100];
- memset(&data, 0, node::arraysize(data));
- uv_buf_t buf = uv_buf_init(data, node::arraysize(data));
-
- bool done = false;
-
- QuicBuffer buffer;
- buffer.Push(&buf, 1, [&](int status) {
- EXPECT_EQ(0, status);
- done = true;
- });
-
- buffer.Seek(1);
- buffer.Consume(150); // Consume more than what was buffered
- ASSERT_TRUE(done);
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-}
-
-TEST(QuicBuffer, Multiple) {
- uv_buf_t bufs[] {
- uv_buf_init(const_cast<char*>("abcdefghijklmnopqrstuvwxyz"), 26),
- uv_buf_init(const_cast<char*>("zyxwvutsrqponmlkjihgfedcba"), 26)
- };
-
- QuicBuffer buf;
- bool done = false;
- buf.Push(bufs, 2, [&](int status) { done = true; });
-
- buf.Seek(2);
- ASSERT_TRUE(IsEqual(buf.remaining(), 50));
- ASSERT_TRUE(IsEqual(buf.length(), 52));
-
- buf.Consume(25);
- ASSERT_TRUE(IsEqual(buf.length(), 27));
-
- buf.Consume(25);
- ASSERT_TRUE(IsEqual(buf.length(), 2));
-
- buf.Consume(2);
- ASSERT_TRUE(IsEqual(buf.length(), 0));
-}
-
-TEST(QuicBuffer, Multiple2) {
- char* ptr = new char[100];
- memset(ptr, 0, 50);
- memset(ptr + 50, 1, 50);
-
- uv_buf_t bufs[] = {
- uv_buf_init(ptr, 50),
- uv_buf_init(ptr + 50, 50)
- };
-
- int count = 0;
-
- QuicBuffer buffer;
- buffer.Push(
- bufs, node::arraysize(bufs),
- [&](int status) {
- count++;
- ASSERT_EQ(0, status);
- delete[] ptr;
- });
- buffer.Seek(node::arraysize(bufs));
-
- buffer.Consume(25);
- ASSERT_TRUE(IsEqual(buffer.length(), 75));
- buffer.Consume(25);
- ASSERT_TRUE(IsEqual(buffer.length(), 50));
- buffer.Consume(25);
- ASSERT_TRUE(IsEqual(buffer.length(), 25));
- buffer.Consume(25);
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-
- // The callback was only called once tho
- ASSERT_EQ(1, count);
-}
-
-TEST(QuicBuffer, Cancel) {
- char* ptr = new char[100];
- memset(ptr, 0, 50);
- memset(ptr + 50, 1, 50);
-
- uv_buf_t bufs[] = {
- uv_buf_init(ptr, 50),
- uv_buf_init(ptr + 50, 50)
- };
-
- int count = 0;
-
- QuicBuffer buffer;
- buffer.Push(
- bufs, node::arraysize(bufs),
- [&](int status) {
- count++;
- ASSERT_EQ(UV_ECANCELED, status);
- delete[] ptr;
- });
-
- buffer.Seek(1);
- buffer.Consume(25);
- ASSERT_TRUE(IsEqual(buffer.length(), 75));
- buffer.Cancel();
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-
- // The callback was only called once tho
- ASSERT_EQ(1, count);
-}
-
-TEST(QuicBuffer, Move) {
- QuicBuffer buffer1;
- QuicBuffer buffer2;
-
- char data[100];
- memset(&data, 0, node::arraysize(data));
- uv_buf_t buf = uv_buf_init(data, node::arraysize(data));
-
- buffer1.Push(&buf, 1);
-
- ASSERT_TRUE(IsEqual(buffer1.length(), 100));
-
- buffer2 = std::move(buffer1);
- ASSERT_TRUE(IsEqual(buffer1.length(), 0));
- ASSERT_TRUE(IsEqual(buffer2.length(), 100));
-}
-
-TEST(QuicBuffer, QuicBufferChunk) {
- std::unique_ptr<QuicBufferChunk> chunk =
- std::make_unique<QuicBufferChunk>(100);
- memset(chunk->out(), 1, 100);
-
- QuicBuffer buffer;
- buffer.Push(std::move(chunk));
- buffer.End();
- ASSERT_TRUE(IsEqual(buffer.length(), 100));
-
- auto next = [&](
- int status,
- const ngtcp2_vec* data,
- size_t count,
- Done done) {
- ASSERT_EQ(status, Status::STATUS_END);
- ASSERT_TRUE(IsEqual(count, 1));
- ASSERT_NE(data, nullptr);
- done(100);
- };
-
- ASSERT_TRUE(IsEqual(buffer.remaining(), 100));
-
- ngtcp2_vec data[2];
- size_t len = sizeof(data) / sizeof(ngtcp2_vec);
- buffer.Pull(next, Options::OPTIONS_SYNC | Options::OPTIONS_END, data, len);
-
- ASSERT_TRUE(IsEqual(buffer.remaining(), 0));
-
- buffer.Consume(50);
- ASSERT_TRUE(IsEqual(buffer.length(), 50));
-
- buffer.Consume(50);
- ASSERT_TRUE(IsEqual(buffer.length(), 0));
-}
diff --git a/test/cctest/test_quic_cid.cc b/test/cctest/test_quic_cid.cc
deleted file mode 100644
index eb1a9c5331..0000000000
--- a/test/cctest/test_quic_cid.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "quic/node_quic_util-inl.h"
-#include "node_sockaddr-inl.h"
-#include "util-inl.h"
-#include "ngtcp2/ngtcp2.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <vector>
-
-using node::quic::QuicCID;
-
-TEST(QuicCID, Simple) {
- ngtcp2_cid cid1;
- ngtcp2_cid cid2;
- uint8_t data1[3] = { 'a', 'b', 'c' };
- uint8_t data2[4] = { 1, 2, 3, 4 };
- ngtcp2_cid_init(&cid1, data1, 3);
- ngtcp2_cid_init(&cid2, data2, 4);
-
- QuicCID qcid1(cid1);
- CHECK(qcid1);
- CHECK_EQ(qcid1.length(), 3);
- CHECK_EQ(qcid1.ToString(), "616263");
-
- QuicCID qcid2(cid2);
- qcid1 = qcid2;
- CHECK_EQ(qcid1.ToString(), qcid2.ToString());
-
- qcid1.set_length(5);
- memset(qcid1.data(), 1, 5);
- CHECK_EQ(qcid1.ToString(), "0101010101");
-}
diff --git a/test/common/index.js b/test/common/index.js
index b8ffc9dbff..b70972b1a5 100644
--- a/test/common/index.js
+++ b/test/common/index.js
@@ -50,7 +50,6 @@ const noop = () => {};
const hasCrypto = Boolean(process.versions.openssl) &&
!process.env.NODE_SKIP_CRYPTO;
-const hasQuic = hasCrypto && Boolean(process.versions.ngtcp2);
// Check for flags. Skip this for workers (both, the `cluster` module and
// `worker_threads`) and child processes.
@@ -727,7 +726,6 @@ const common = {
getTTYfd,
hasIntl,
hasCrypto,
- hasQuic,
hasMultiLocalhost,
invalidArgTypeHelper,
isAIX,
diff --git a/test/common/quic.js b/test/common/quic.js
deleted file mode 100644
index bee54d8171..0000000000
--- a/test/common/quic.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* eslint-disable node-core/require-common-first, node-core/required-modules */
-'use strict';
-
-// Common bits for all QUIC-related tests
-const { debuglog } = require('util');
-const { readKeys } = require('./fixtures');
-const { createWriteStream } = require('fs');
-const kHttp3Alpn = 'h3-29';
-
-const [ key, cert, ca ] =
- readKeys(
- 'binary',
- 'agent1-key.pem',
- 'agent1-cert.pem',
- 'ca1-cert.pem');
-
-const debug = debuglog('test');
-
-const kServerPort = process.env.NODE_DEBUG_KEYLOG ? 5678 : 0;
-const kClientPort = process.env.NODE_DEBUG_KEYLOG ? 5679 : 0;
-
-function setupKeylog(session) {
- if (process.env.NODE_DEBUG_KEYLOG) {
- const kl = createWriteStream(process.env.NODE_DEBUG_KEYLOG);
- session.on('keylog', kl.write.bind(kl));
- }
-}
-
-module.exports = {
- key,
- cert,
- ca,
- debug,
- kServerPort,
- kClientPort,
- setupKeylog,
- kHttp3Alpn,
-};
diff --git a/test/parallel/test-process-versions.js b/test/parallel/test-process-versions.js
index 78c33fcf1b..14484293dc 100644
--- a/test/parallel/test-process-versions.js
+++ b/test/parallel/test-process-versions.js
@@ -16,11 +16,6 @@ if (common.hasIntl) {
expected_keys.push('unicode');
}
-if (common.hasQuic) {
- expected_keys.push('ngtcp2');
- expected_keys.push('nghttp3');
-}
-
expected_keys.sort();
const actual_keys = Object.keys(process.versions).sort();
diff --git a/test/parallel/test-quic-binding.js b/test/parallel/test-quic-binding.js
deleted file mode 100644
index 2044ed43b4..0000000000
--- a/test/parallel/test-quic-binding.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests the availability and correctness of internalBinding(quic)
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { internalBinding } = require('internal/test/binding');
-
-const quic = internalBinding('quic');
-assert(quic);
-
-assert(quic.constants);
-
-// Version numbers used to identify IETF drafts are created by
-// adding the draft number to 0xff0000, in this case 19 (25).
-assert.strictEqual(quic.constants.NGTCP2_PROTO_VER.toString(16), 'ff00001d');
-assert.strictEqual(quic.constants.NGHTTP3_ALPN_H3, '\u0005h3-29');
-
-assert.strictEqual(quic.constants.NGTCP2_NO_ERROR, 0);
-assert.strictEqual(quic.constants.NGTCP2_INTERNAL_ERROR, 1);
-assert.strictEqual(quic.constants.NGTCP2_CONNECTION_REFUSED, 2);
-assert.strictEqual(quic.constants.NGTCP2_FLOW_CONTROL_ERROR, 3);
-assert.strictEqual(quic.constants.NGTCP2_STREAM_LIMIT_ERROR, 4);
-assert.strictEqual(quic.constants.NGTCP2_STREAM_STATE_ERROR, 5);
-assert.strictEqual(quic.constants.NGTCP2_FINAL_SIZE_ERROR, 6);
-assert.strictEqual(quic.constants.NGTCP2_FRAME_ENCODING_ERROR, 7);
-assert.strictEqual(quic.constants.NGTCP2_TRANSPORT_PARAMETER_ERROR, 8);
-assert.strictEqual(quic.constants.NGTCP2_CONNECTION_ID_LIMIT_ERROR, 9);
-assert.strictEqual(quic.constants.NGTCP2_PROTOCOL_VIOLATION, 0xa);
-assert.strictEqual(quic.constants.NGTCP2_INVALID_TOKEN, 0xb);
-assert.strictEqual(quic.constants.NGTCP2_APPLICATION_ERROR, 0xc);
-assert.strictEqual(quic.constants.NGTCP2_CRYPTO_BUFFER_EXCEEDED, 0xd);
-assert.strictEqual(quic.constants.NGTCP2_KEY_UPDATE_ERROR, 0xe);
-assert.strictEqual(quic.constants.NGTCP2_CRYPTO_ERROR, 0x100);
-
-// The following just tests for the presence of things we absolutely need.
-// They don't test the functionality of those things.
-
-assert(quic.sessionConfig instanceof Float64Array);
-assert(quic.http3Config instanceof Float64Array);
-
-assert(quic.QuicSocket);
-assert(quic.QuicEndpoint);
-assert(quic.QuicStream);
-
-assert.strictEqual(typeof quic.createClientSession, 'function');
-assert.strictEqual(typeof quic.openBidirectionalStream, 'function');
-assert.strictEqual(typeof quic.openUnidirectionalStream, 'function');
-assert.strictEqual(typeof quic.setCallbacks, 'function');
-assert.strictEqual(typeof quic.initSecureContext, 'function');
-assert.strictEqual(typeof quic.initSecureContextClient, 'function');
-assert.strictEqual(typeof quic.silentCloseSession, 'function');
diff --git a/test/parallel/test-quic-blocklist.js b/test/parallel/test-quic-blocklist.js
deleted file mode 100644
index 383ea3bd49..0000000000
--- a/test/parallel/test-quic-blocklist.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { createQuicSocket, BlockList } = require('net');
-const assert = require('assert');
-
-const { key, cert, ca } = require('../common/quic');
-const { once } = require('events');
-
-const idleTimeout = common.platformTimeout(1);
-const options = { key, cert, ca, alpn: 'zzz', idleTimeout };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-assert(client.blockList instanceof BlockList);
-assert(server.blockList instanceof BlockList);
-
-client.blockList.addAddress('10.0.0.1');
-
-assert(client.blockList.check('10.0.0.1'));
-
-// Connection fails because the IP address is blocked
-assert.rejects(client.connect({ address: '10.0.0.1' }), {
- code: 'ERR_OPERATION_FAILED'
-}).then(common.mustCall());
-
-server.blockList.addAddress('127.0.0.1');
-
-(async () => {
- server.on('session', common.mustNotCall());
-
- await server.listen();
-
- const session = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- idleTimeout,
- });
-
- session.on('secure', common.mustNotCall());
-
- await once(session, 'close');
-
- await Promise.all([server.close(), client.close()]);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-client-connect-multiple-parallel.js b/test/parallel/test-quic-client-connect-multiple-parallel.js
deleted file mode 100644
index 280524df65..0000000000
--- a/test/parallel/test-quic-client-connect-multiple-parallel.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-// Test that .connect() can be called multiple times with different servers.
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-const { key, cert, ca } = require('../common/quic');
-const Countdown = require('../common/countdown');
-
-const options = { key, cert, ca, alpn: 'meow' };
-const kCount = 3;
-const servers = [];
-
-const client = createQuicSocket({ client: options });
-const countdown = new Countdown(kCount, () => {
- client.close();
-});
-
-async function connect(server, client) {
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustCall((stream) => {
- stream.on('data', common.mustCall(
- (chk) => assert.strictEqual(chk.toString(), 'Hi!')));
- stream.on('end', common.mustCall(() => {
- server.close();
- req.close();
- countdown.dec();
- }));
- }));
-
- req.on('close', common.mustCall());
-}
-
-(async function() {
- for (let i = 0; i < kCount; i++) {
- const server = createQuicSocket({ server: options });
-
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: true });
- stream.end('Hi!');
- }));
-
- server.on('close', common.mustCall());
-
- servers.push(server);
- }
-
- await Promise.all(servers.map((server) => server.listen()));
-
- await Promise.all(servers.map((server) => connect(server, client)));
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-client-connect-multiple-sequential.js b/test/parallel/test-quic-client-connect-multiple-sequential.js
deleted file mode 100644
index 5b1150d1cb..0000000000
--- a/test/parallel/test-quic-client-connect-multiple-sequential.js
+++ /dev/null
@@ -1,63 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-// Test that .connect() can be called multiple times with different servers.
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-const { key, cert, ca } = require('../common/quic');
-const Countdown = require('../common/countdown');
-const { once } = require('events');
-
-const options = { key, cert, ca, alpn: 'meow' };
-const kCount = 3;
-const servers = [];
-
-const client = createQuicSocket({ client: options });
-const countdown = new Countdown(kCount, () => {
- client.close();
-});
-
-async function connect(server, client) {
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustCall((stream) => {
- stream.on('data', common.mustCall(
- (chk) => assert.strictEqual(chk.toString(), 'Hi!')));
- stream.on('end', common.mustCall(() => {
- server.close();
- req.close();
- countdown.dec();
- }));
- }));
-
- await once(req, 'close');
-}
-
-(async function() {
- for (let i = 0; i < kCount; i++) {
- const server = createQuicSocket({ server: options });
-
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: true });
- stream.end('Hi!');
- }));
-
- server.on('close', common.mustCall());
-
- servers.push(server);
- }
-
- await Promise.all(servers.map((server) => server.listen()));
-
- for (let i = 0; i < kCount; i++)
- await connect(servers[i], client);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-client-empty-preferred-address.js b/test/parallel/test-quic-client-empty-preferred-address.js
deleted file mode 100644
index 597b312ae8..0000000000
--- a/test/parallel/test-quic-client-empty-preferred-address.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// This test ensures that when we don't define `preferredAddress`
-// on the server while the `preferredAddressPolicy` on the client
-// is `accept`, it works as expected.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { key, cert, ca } = require('../common/quic');
-const { createQuicSocket } = require('net');
-const { once } = require('events');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-(async () => {
- const server = createQuicSocket({ server: options });
- const client = createQuicSocket({ client: options });
-
- server.on('session', common.mustCall((serverSession) => {
- serverSession.on('stream', common.mustCall(async (stream) => {
- stream.on('data', common.mustCall((data) => {
- assert.strictEqual(data.toString('utf8'), 'hello');
- }));
-
- await once(stream, 'end');
-
- stream.close();
- client.close();
- server.close();
- }));
- }));
-
- await server.listen();
-
- const clientSession = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- preferredAddressPolicy: 'accept',
- });
-
- const stream = await clientSession.openStream();
- stream.end('hello');
-
- await Promise.all([
- once(stream, 'close'),
- once(client, 'close'),
- once(server, 'close')]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-client-server.js b/test/parallel/test-quic-client-server.js
deleted file mode 100644
index c4fec7b4c7..0000000000
--- a/test/parallel/test-quic-client-server.js
+++ /dev/null
@@ -1,364 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests a simple QUIC client/server round-trip
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { internalBinding } = require('internal/test/binding');
-const {
- constants: {
- NGTCP2_NO_ERROR,
- QUIC_ERROR_APPLICATION,
- }
-} = internalBinding('quic');
-
-const qlog = process.env.NODE_QLOG === '1';
-
-const { Buffer } = require('buffer');
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const {
- createReadStream,
- createWriteStream,
- readFileSync
-} = require('fs');
-const { pipeline } = require('stream');
-const {
- key,
- cert,
- ca,
- debug,
-} = require('../common/quic');
-
-const filedata = readFileSync(__filename, { encoding: 'utf8' });
-
-const { createQuicSocket } = require('net');
-
-const kStatelessResetToken =
- Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex');
-
-const unidata = ['I wonder if it worked.', 'test'];
-const kServerName = 'agent2'; // Intentionally the wrong servername
-const kALPN = 'zzz'; // ALPN can be overriden to whatever we want
-
-const {
- setImmediate: setImmediatePromise
-} = require('timers/promises');
-
-const ocspHandler = common.mustCall(async function(type, options) {
- debug(`QuicClientSession received an OCSP ${type}"`);
- switch (type) {
- case 'request':
- const {
- servername,
- certificate,
- issuer,
- } = options;
-
- assert.strictEqual(servername, kServerName);
-
- debug('QuicServerSession Certificate: ', certificate);
- debug('QuicServerSession Issuer: ', issuer);
-
- // Handshake will pause until the Promise resolves
- await setImmediatePromise();
-
- return Buffer.from('hello');
- case 'response':
- const { data } = options;
- assert.strictEqual(data.toString(), 'hello');
- }
-}, 2);
-
-const clientHelloHandler = common.mustCall(
- async (alpn, servername, ciphers) => {
- assert.strictEqual(alpn, kALPN);
- assert.strictEqual(servername, kServerName);
- assert.strictEqual(ciphers.length, 4);
- });
-
-const options = { key, cert, ca, alpn: kALPN, qlog, ocspHandler };
-
-const client = createQuicSocket({ qlog, client: options });
-const server = createQuicSocket({
- qlog,
- validateAddress: true,
- statelessResetSecret: kStatelessResetToken,
- server: options
-});
-
-const countdown = new Countdown(2, () => {
- debug('Countdown expired. Destroying sockets');
- server.close();
- client.close();
-});
-
-function onSocketClose() {
- debug(`${this.constructor.name} closing. Duration`, this.duration);
- debug(' Bound duration:',
- this.boundDuration);
- debug(' Listen duration:',
- this.listenDuration);
- debug(' Bytes Sent/Received: %d/%d',
- this.bytesSent,
- this.bytesReceived);
- debug(' Packets Sent/Received: %d/%d',
- this.packetsSent,
- this.packetsReceived);
- debug(' Sessions:', this.serverSessions, this.clientSessions);
-}
-
-server.on('listening', common.mustCall());
-server.on('ready', common.mustCall());
-server.on('close', common.mustCall(onSocketClose.bind(server)));
-client.on('endpointClose', common.mustCall());
-client.on('close', common.mustCall(onSocketClose.bind(client)));
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- if (qlog) session.qlog.pipe(createWriteStream('server.qlog'));
- debug('QuicServerSession Created');
-
- assert.strictEqual(session.maxStreams.bidi, 100);
- assert.strictEqual(session.maxStreams.uni, 3);
-
- {
- const {
- address,
- family,
- port
- } = session.remoteAddress;
- const endpoint = client.endpoints[0].address;
- assert.strictEqual(port, endpoint.port);
- assert.strictEqual(family, endpoint.family);
- debug(`QuicServerSession Client ${family} address ${address}:${port}`);
- }
-
- session.on('secure', common.mustCall((servername, alpn, cipher) => {
- debug('QuicServerSession TLS Handshake Complete');
- debug(' Server name: %s', servername);
- debug(' ALPN: %s', alpn);
- debug(' Cipher: %s, %s', cipher.name, cipher.version);
- assert.strictEqual(session.servername, servername);
- assert.strictEqual(servername, kServerName);
- assert.strictEqual(session.alpnProtocol, alpn);
- assert.strictEqual(session.getPeerCertificate().subject.CN, 'agent1');
- assert(session.authenticated);
- assert.strictEqual(session.authenticationError, undefined);
- }));
-
- const uni = await session.openStream({ halfOpen: true });
- debug('Unidirectional, Server-initiated stream %d opened', uni.id);
- assert(uni.writable);
- assert(!uni.readable);
- assert(uni.unidirectional);
- assert(!uni.bidirectional);
- assert(uni.serverInitiated);
- assert(!uni.clientInitiated);
- uni.on('end', common.mustNotCall());
- uni.on('data', common.mustNotCall());
- uni.write(unidata[0], common.mustCall());
- uni.end(unidata[1]);
- // TODO(@jasnell): There's currently a bug where the final
- // write callback is not invoked if the stream/session is
- // destroyed before we receive the acknowledgement for the
- // write.
- // uni.end(unidata[1], common.mustCall());
- // uni.on('finish', common.mustCall());
- uni.on('close', common.mustCall(() => {
- assert.strictEqual(uni.finalSize, 0);
- }));
-
- session.on('stream', common.mustCall((stream) => {
- debug('Bidirectional, Client-initiated stream %d received', stream.id);
- assert.strictEqual(stream.id, 0);
- assert.strictEqual(stream.session, session);
- assert(stream.writable);
- assert(stream.readable);
- assert(stream.bidirectional);
- assert(!stream.unidirectional);
- assert(stream.clientInitiated);
- assert(!stream.serverInitiated);
-
- let data = '';
- pipeline(createReadStream(__filename), stream, common.mustSucceed());
-
- stream.setEncoding('utf8');
- stream.on('blocked', common.mustNotCall());
- stream.on('data', (chunk) => {
- data += chunk;
-
- debug('Server: min data rate: %f', stream.dataRateHistogram.min);
- debug('Server: max data rate: %f', stream.dataRateHistogram.max);
- debug('Server: data rate 50%: %f',
- stream.dataRateHistogram.percentile(50));
- debug('Server: data rate 99%: %f',
- stream.dataRateHistogram.percentile(99));
-
- debug('Server: min data size: %f', stream.dataSizeHistogram.min);
- debug('Server: max data size: %f', stream.dataSizeHistogram.max);
- debug('Server: data size 50%: %f',
- stream.dataSizeHistogram.percentile(50));
- debug('Server: data size 99%: %f',
- stream.dataSizeHistogram.percentile(99));
- });
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, filedata);
- debug('Server received expected data for stream %d', stream.id);
- }));
- stream.on('finish', common.mustCall());
- stream.on('close', common.mustCall(() => {
- assert.strictEqual(typeof stream.duration, 'number');
- assert.strictEqual(typeof stream.bytesReceived, 'number');
- assert.strictEqual(typeof stream.bytesSent, 'number');
- assert.strictEqual(typeof stream.maxExtendedOffset, 'number');
- assert.strictEqual(stream.finalSize, filedata.length);
- }));
- }));
-
- session.on('close', common.mustCall(() => {
- const {
- code,
- family
- } = session.closeCode;
- debug(`Server session closed with code ${code} (family: ${family})`);
- assert.strictEqual(code, NGTCP2_NO_ERROR);
-
- const err = {
- code: 'ERR_INVALID_STATE',
- name: 'Error'
- };
- assert.throws(() => session.ping(), err);
- assert.throws(() => session.updateKey(), err);
- assert.rejects(() => session.openStream(), err);
- }));
- }));
-
- await server.listen({
- requestCert: true,
- rejectUnauthorized: false,
- clientHelloHandler
- });
-
- const endpoints = server.endpoints;
- for (const endpoint of endpoints) {
- const address = endpoint.address;
- debug('Server is listening on address %s:%d',
- address.address,
- address.port);
- }
- const endpoint = endpoints[0];
-
- const req = await client.connect({
- address: 'localhost',
- port: endpoint.address.port,
- servername: kServerName,
- });
- if (qlog) req.qlog.pipe(createWriteStream('client.qlog'));
-
- assert.strictEqual(req.servername, kServerName);
-
- req.on('usePreferredAddress', common.mustNotCall());
-
- req.on('sessionTicket', common.mustCall((ticket, params) => {
- debug('Session ticket received');
- assert(ticket instanceof Buffer);
- assert(params instanceof Buffer);
- debug(' Ticket: %s', ticket.toString('hex'));
- debug(' Params: %s', params.toString('hex'));
- }, 2));
-
- req.on('secure', common.mustCall(async (servername, alpn, cipher) => {
- debug('QuicClientSession TLS Handshake Complete');
- debug(' Server name: %s', servername);
- debug(' ALPN: %s', alpn);
- debug(' Cipher: %s, %s', cipher.name, cipher.version);
- assert.strictEqual(servername, kServerName);
- assert.strictEqual(req.servername, kServerName);
- assert.strictEqual(alpn, kALPN);
- assert.strictEqual(req.alpnProtocol, kALPN);
- assert(req.ephemeralKeyInfo);
- assert.strictEqual(req.getPeerCertificate().subject.CN, 'agent1');
-
- debug('Client, min handshake ack: %f',
- req.handshakeAckHistogram.min);
- debug('Client, max handshake ack: %f',
- req.handshakeAckHistogram.max);
- debug('Client, min handshake rate: %f',
- req.handshakeContinuationHistogram.min);
- debug('Client, max handshake rate: %f',
- req.handshakeContinuationHistogram.max);
-
- // The server's identity won't be valid because the requested
- // SNI hostname does not match the certificate used.
- debug('QuicClientSession server is %sauthenticated',
- req.authenticated ? '' : 'not ');
- assert(!req.authenticated);
- assert.throws(() => { throw req.authenticationError; }, {
- code: 'ERR_QUIC_VERIFY_HOSTNAME_MISMATCH',
- message: 'Hostname mismatch'
- });
- }));
-
- req.on('stream', common.mustCall((stream) => {
- debug('Unidirectional, Server-initiated stream %d received', stream.id);
- let data = '';
- assert(stream.readable);
- assert(!stream.writable);
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, unidata.join(''));
- debug('Client received expected data for stream %d', stream.id);
- }));
- stream.on('close', common.mustCall(() => {
- debug('Unidirectional, Server-initiated stream %d closed', stream.id);
- assert.strictEqual(stream.finalSize, 26);
- countdown.dec();
- }));
- }));
-
- req.on('close', common.mustCall(() => {
- const {
- code,
- family
- } = req.closeCode;
- debug(`Client session closed with code ${code} (family: ${family})`);
- assert.strictEqual(code, NGTCP2_NO_ERROR);
- assert.strictEqual(family, QUIC_ERROR_APPLICATION);
- }));
-
- {
- const {
- address,
- family,
- port
- } = req.remoteAddress;
- const endpoint = server.endpoints[0].address;
- assert.strictEqual(port, endpoint.port);
- assert.strictEqual(family, endpoint.family);
- debug(`QuicClientSession Server ${family} address ${address}:${port}`);
- }
-
- const stream = await req.openStream();
- pipeline(createReadStream(__filename), stream, common.mustSucceed());
- let data = '';
- stream.resume();
- stream.setEncoding('utf8');
- stream.on('finish', common.mustCall());
- stream.on('blocked', common.mustNotCall());
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, filedata);
- debug('Client received expected data for stream %d', stream.id);
- }));
- stream.on('close', common.mustCall(() => {
- debug('Bidirectional, Client-initiated stream %d closed', stream.id);
- assert.strictEqual(stream.finalSize, filedata.length);
- countdown.dec();
- }));
- debug('Bidirectional, Client-initiated stream %d opened', stream.id);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-errors-quicsession-openstream.js b/test/parallel/test-quic-errors-quicsession-openstream.js
deleted file mode 100644
index d608f12d20..0000000000
--- a/test/parallel/test-quic-errors-quicsession-openstream.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-// Test errors thrown when openStream is called incorrectly
-// or is not permitted
-
-const { once } = require('events');
-const { createHook } = require('async_hooks');
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-// Ensure that no QUICSTREAM instances are created during the test
-createHook({
- init(id, type) {
- assert.notStrictEqual(type, 'QUICSTREAM');
- }
-}).enable();
-
-const { key, cert, ca } = require('../common/quic');
-
-const options = { key, cert, ca, alpn: 'zzz', maxStreamsUni: 0 };
-const server = createQuicSocket({ server: options });
-const client = createQuicSocket({ client: options });
-
-server.on('close', common.mustCall());
-client.on('close', common.mustCall());
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('stream', common.mustNotCall());
- }));
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port
- });
-
- for (const halfOpen of ['z', 1, {}, [], null, Infinity, 1n]) {
- await assert.rejects(req.openStream({ halfOpen }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }
-
- for (const defaultEncoding of ['', 1n, {}, [], false, 'zebra']) {
- await assert.rejects(req.openStream({ defaultEncoding }), {
- code: 'ERR_INVALID_ARG_VALUE'
- });
- }
-
- for (const highWaterMark of [-1, Number.MAX_SAFE_INTEGER + 1]) {
- await assert.rejects(req.openStream({ highWaterMark }), {
- code: 'ERR_OUT_OF_RANGE'
- });
- }
-
- for (const highWaterMark of ['a', 1n, [], {}, false]) {
- await assert.rejects(req.openStream({ highWaterMark }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }
-
- // Unidirectional streams are not allowed. openStream will succeeed
- // but the stream will be destroyed immediately. The underlying
- // QuicStream C++ handle will not be created.
- await assert.rejects(
- req.openStream({
- halfOpen: true,
- highWaterMark: 10,
- defaultEncoding: 'utf16le'
- }), {
- code: 'ERR_OPERATION_FAILED'
- });
-
- server.close();
- client.close();
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-errors-quicsocket-connect.js b/test/parallel/test-quic-errors-quicsocket-connect.js
deleted file mode 100644
index e9aba4b0ce..0000000000
--- a/test/parallel/test-quic-errors-quicsocket-connect.js
+++ /dev/null
@@ -1,235 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests error and input validation checks for QuicSocket.connect()
-
-const common = require('../common');
-
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { createHook } = require('async_hooks');
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-// Ensure that a QuicClientSession handle is never created during the
-// error condition tests (ensures that argument and error validation)
-// is occurring before the underlying handle is created.
-createHook({
- init(id, type) {
- assert.notStrictEqual(type, 'QUICCLIENTSESSION');
- }
-}).enable();
-
-const client = createQuicSocket();
-
-(async function() {
- await Promise.all(['test', 1n, {}, [], false].map((minDHSize) => {
- return assert.rejects(client.connect({ minDHSize }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await Promise.all([-1, 'test', 1n, {}, [], NaN, false, 65536].map((port) => {
- return assert.rejects(client.connect({ port }), {
- code: 'ERR_SOCKET_BAD_PORT'
- });
- }));
-
- // Test invalid address argument option
- await Promise.all([-1, 10, 1n, {}, [], true].map((address) => {
- return assert.rejects(client.connect({ address }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- // Test servername can't be IP address argument option
- await Promise.all([
- '0.0.0.0',
- '8.8.8.8',
- '127.0.0.1',
- '192.168.0.1',
- '::',
- '1::',
- '::1',
- '1::8',
- '1::7:8',
- '1:2:3:4:5:6:7:8',
- '1:2:3:4:5:6::8',
- '2001:0000:1234:0000:0000:C1C0:ABCD:0876',
- '3ffe:0b00:0000:0000:0001:0000:0000:000a',
- 'a:0:0:0:0:0:0:0',
- 'fe80::7:8%eth0',
- 'fe80::7:8%1'
- ].map((servername) => {
- return assert.rejects(client.connect({ servername }), {
- code: 'ERR_INVALID_ARG_VALUE'
- });
- }));
-
- await Promise.all([-1, 10, 1n, {}, [], true].map((servername) => {
- return assert.rejects(client.connect({ servername }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- // Test invalid remoteTransportParams argument option
- await Promise.all([-1, 'test', 1n, {}, []].map((remoteTransportParams) => {
- return assert.rejects(client.connect({ remoteTransportParams }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- // Test invalid sessionTicket argument option
- await Promise.all([-1, 'test', 1n, {}, []].map((sessionTicket) => {
- return assert.rejects(client.connect({ sessionTicket }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- // Test invalid alpn argument option
- await Promise.all([-1, 10, 1n, {}, [], true].map((alpn) => {
- return assert.rejects(client.connect({ alpn }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await Promise.all([
- 'idleTimeout',
- 'activeConnectionIdLimit',
- 'maxAckDelay',
- 'maxData',
- 'maxUdpPayloadSize',
- 'maxStreamDataBidiLocal',
- 'maxStreamDataBidiRemote',
- 'maxStreamDataUni',
- 'maxStreamsBidi',
- 'maxStreamsUni',
- 'highWaterMark',
- ].map(async (prop) => {
- await assert.rejects(client.connect({ [prop]: -1 }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-
- await assert.rejects(
- client.connect({ [prop]: Number.MAX_SAFE_INTEGER + 1 }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-
- await Promise.all(['a', 1n, [], {}, false].map((val) => {
- return assert.rejects(client.connect({ [prop]: val }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
- }));
-
- // activeConnectionIdLimit must be between 2 and 8, inclusive
- await Promise.all([1, 9].map((activeConnectionIdLimit) => {
- return assert.rejects(client.connect({ activeConnectionIdLimit }), {
- code: 'ERR_OUT_OF_RANGE'
- });
- }));
-
- await Promise.all([1, 1n, false, [], {}].map((preferredAddressPolicy) => {
- return assert.rejects(client.connect({ preferredAddressPolicy }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await Promise.all([1, 1n, 'test', [], {}].map((qlog) => {
- return assert.rejects(client.connect({ qlog }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await Promise.all([1, 1n, 'test', [], {}].map((ocspHandler) => {
- return assert.rejects(client.connect({ ocspHandler }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await Promise.all([1, 1n, false, [], {}, 'aaa'].map((type) => {
- return assert.rejects(client.connect({ type }), {
- code: 'ERR_INVALID_ARG_VALUE'
- });
- }));
-
- await Promise.all([
- 'qpackMaxTableCapacity',
- 'qpackBlockedStreams',
- 'maxHeaderListSize',
- 'maxPushes',
- ].map(async (prop) => {
- await assert.rejects(client.connect({ h3: { [prop]: -1 } }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-
- await assert.rejects(
- client.connect({ h3: { [prop]: Number.MAX_SAFE_INTEGER + 1 } }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-
- await Promise.all(['a', 1n, [], {}, false].map((val) => {
- return assert.rejects(client.connect({ h3: { [prop]: val } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
- }));
-
- await Promise.all(['', 1n, {}, [], false, 'zebra'].map((defaultEncoding) => {
- return assert.rejects(client.connect({ defaultEncoding }), {
- code: 'ERR_INVALID_ARG_VALUE'
- });
- }));
-
- // Test that connect cannot be called after QuicSocket is closed.
- client.close();
-
- await assert.rejects(client.connect(), {
- code: 'ERR_INVALID_STATE'
- });
-})().then(common.mustCall());
-
-// TODO(@jasnell): Test additional options:
-//
-// Client QuicSession Related:
-//
-// [x] idleTimeout - must be a number greater than zero
-// [x] activeConnectionIdLimit - must be a number between 2 and 8
-// [x] maxAckDelay - must be a number greater than zero
-// [x] maxData - must be a number greater than zero
-// [x] maxUdpPayloadSize - must be a number greater than zero
-// [x] maxStreamDataBidiLocal - must be a number greater than zero
-// [x] maxStreamDataBidiRemote - must be a number greater than zero
-// [x] maxStreamDataUni - must be a number greater than zero
-// [x] maxStreamsBidi - must be a number greater than zero
-// [x] maxStreamsUni - must be a number greater than zero
-// [x] preferredAddressPolicy - must be eiher 'accept' or 'reject'
-// [x] qlog - must be a boolean
-// [x] requestOCSP - must be a boolean
-// [x] type - must be a string, either 'udp4' or 'udp6'
-//
-// HTTP/3 Related:
-//
-// [x] h3.qpackMaxTableCapacity - must be a number greater than zero
-// [x] h3.qpackBlockedStreams - must be a number greater than zero
-// [x] h3.maxHeaderListSize - must be a number greater than zero
-// [x] h3.maxPushes - must be a number greater than zero
-//
-// Secure Context Related:
-//
-// [ ] ca (certificate authority) - must be a string, string array,
-// Buffer, or Buffer array.
-// [ ] cert (cert chain) - must be a string, string array, Buffer, or
-// Buffer array.
-// [ ] ciphers - must be a string
-// [ ] clientCertEngine - must be a string
-// [ ] crl - must be a string, string array, Buffer, or Buffer array
-// [ ] dhparam - must be a string or Buffer
-// [ ] ecdhCurve - must be a string
-// [ ] honorCipherOrder - must be a boolean
-// [ ] key - must be a string, string array, Buffer, or Buffer array
-// [ ] passphrase - must be a string
-// [ ] pfx - must be a string, string array, Buffer, or Buffer array
-// [ ] secureOptions - must be a number
-// [x] minDHSize - must be a number
diff --git a/test/parallel/test-quic-errors-quicsocket-create.js b/test/parallel/test-quic-errors-quicsocket-create.js
deleted file mode 100644
index e7e47339fe..0000000000
--- a/test/parallel/test-quic-errors-quicsocket-create.js
+++ /dev/null
@@ -1,166 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Test QuicSocket constructor option errors
-
-const common = require('../common');
-const async_hooks = require('async_hooks');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-
-// Hook verifies that no QuicSocket handles are actually created.
-async_hooks.createHook({
- init: common.mustCallAtLeast((_, type) => {
- assert.notStrictEqual(type, 'QUICSOCKET');
- })
-}).enable();
-
-const { createQuicSocket } = require('net');
-
-// Test invalid QuicSocket options argument
-[1, 'test', false, 1n, null].forEach((i) => {
- assert.throws(() => createQuicSocket(i), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket port argument option
-[-1, 'test', 1n, {}, [], NaN, false].forEach((port) => {
- assert.throws(() => createQuicSocket({ endpoint: { port } }), {
- code: 'ERR_SOCKET_BAD_PORT'
- });
-});
-
-// Test invalid QuicSocket addressargument option
-[-1, 10, 1n, {}, [], NaN, false].forEach((address) => {
- assert.throws(() => createQuicSocket({ endpoint: { address } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket type argument option
-[1, false, 1n, {}, null, NaN].forEach((type) => {
- assert.throws(() => createQuicSocket({ endpoint: { type } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket reuseAddr argument option
-[1, NaN, 1n, null, {}, []].forEach((reuseAddr) => {
- assert.throws(() => createQuicSocket({ endpoint: { reuseAddr } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket lookup argument option
-[1, 1n, {}, [], 'test', true].forEach((lookup) => {
- assert.throws(() => createQuicSocket({ lookup }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket validateAddress argument option
-[1, NaN, 1n, null, {}, []].forEach((validateAddress) => {
- assert.throws(() => createQuicSocket({ validateAddress }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket qlog argument option
-[1, NaN, 1n, null, {}, []].forEach((qlog) => {
- assert.throws(() => createQuicSocket({ qlog }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-
-// Test invalid QuicSocket retryTokenTimeout option
-[0, 61, NaN].forEach((retryTokenTimeout) => {
- assert.throws(() => createQuicSocket({ retryTokenTimeout }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-});
-
-// Test invalid QuicSocket retryTokenTimeout option
-['test', null, 1n, {}, [], false].forEach((retryTokenTimeout) => {
- assert.throws(() => createQuicSocket({ retryTokenTimeout }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket maxConnectionsPerHost option
-[0, Number.MAX_SAFE_INTEGER + 1, NaN].forEach((maxConnectionsPerHost) => {
- assert.throws(() => createQuicSocket({ maxConnectionsPerHost }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-});
-
-// Test invalid QuicSocket maxConnectionsPerHost option
-[
- 'test',
- null,
- 1n,
- {},
- [],
- false
-].forEach((maxConnectionsPerHost) => {
- assert.throws(() => createQuicSocket({ maxConnectionsPerHost }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket maxConnections option
-[0, Number.MAX_SAFE_INTEGER + 1, NaN].forEach((maxConnections) => {
- assert.throws(() => createQuicSocket({ maxConnections }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-});
-
-// Test invalid QuicSocket maxConnectionsPerHost option
-[
- 'test',
- null,
- 1n,
- {},
- [],
- false
-].forEach((maxConnections) => {
- assert.throws(() => createQuicSocket({ maxConnections }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-// Test invalid QuicSocket maxStatelessResetsPerHost option
-[0, Number.MAX_SAFE_INTEGER + 1, NaN].forEach((maxStatelessResetsPerHost) => {
- assert.throws(() => createQuicSocket({ maxStatelessResetsPerHost }), {
- code: 'ERR_OUT_OF_RANGE'
- });
-});
-
-// Test invalid QuicSocket maxStatelessResetsPerHost option
-[
- 'test',
- null,
- 1n,
- {},
- [],
- false
-].forEach((maxStatelessResetsPerHost) => {
- assert.throws(() => createQuicSocket({ maxStatelessResetsPerHost }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-[1, 1n, false, 'test'].forEach((options) => {
- assert.throws(() => createQuicSocket({ endpoint: options }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- assert.throws(() => createQuicSocket({ client: options }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- assert.throws(() => createQuicSocket({ server: options }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
diff --git a/test/parallel/test-quic-errors-quicsocket-listen.js b/test/parallel/test-quic-errors-quicsocket-listen.js
deleted file mode 100644
index 19c14fb14f..0000000000
--- a/test/parallel/test-quic-errors-quicsocket-listen.js
+++ /dev/null
@@ -1,173 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests error and input validation checks for QuicSocket.connect()
-
-const common = require('../common');
-
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-async function testAlreadyListening() {
- const server = createQuicSocket();
- // Can be called multiple times while pending...
- await Promise.all([server.listen(), server.listen()]);
- // But fails if called again after resolving
- await assert.rejects(server.listen(), {
- code: 'ERR_INVALID_STATE'
- });
- server.close();
-}
-
-async function testListenAfterClose() {
- const server = createQuicSocket();
- server.close();
- await assert.rejects(server.listen(), {
- code: 'ERR_INVALID_STATE'
- });
-}
-
-async function rejectsValue(
- server,
- name,
- values,
- code = 'ERR_INVALID_ARG_TYPE') {
- for (const v of values) {
- await assert.rejects(server.listen({ [name]: v }), { code });
- }
-}
-
-async function testInvalidOptions() {
- const server = createQuicSocket();
-
- await rejectsValue(
- server,
- 'alpn',
- [1, 1n, true, {}, [], null]);
-
- for (const prop of [
- 'idleTimeout',
- 'activeConnectionIdLimit',
- 'maxAckDelay',
- 'maxData',
- 'maxUdpPayloadSize',
- 'maxStreamDataBidiLocal',
- 'maxStreamDataBidiRemote',
- 'maxStreamDataUni',
- 'maxStreamsBidi',
- 'maxStreamsUni',
- 'highWaterMark',
- ]) {
- await rejectsValue(
- server,
- prop,
- [-1],
- 'ERR_OUT_OF_RANGE');
- await rejectsValue(
- server,
- prop,
- [Number.MAX_SAFE_INTEGER + 1],
- 'ERR_OUT_OF_RANGE');
- await rejectsValue(
- server,
- prop,
- ['a', 1n, [], {}, false]);
- }
-
- await rejectsValue(
- server,
- 'rejectUnauthorized',
- [1, 1n, 'test', {}, []]);
-
- await rejectsValue(
- server,
- 'requestCert',
- [1, 1n, 'test', {}, []]);
-
- await rejectsValue(
- server,
- 'ciphers',
- [1, 1n, false, {}, [], null]);
-
- await rejectsValue(
- server,
- 'groups',
- [1, 1n, false, {}, [], null]);
-
- await rejectsValue(
- server,
- 'defaultEncoding',
- [1, 1n, false, {}, [], 'zebra'],
- 'ERR_INVALID_ARG_VALUE');
-
- await rejectsValue(
- server,
- 'preferredAddress',
- [1, 1n, 'test', false]
- );
-
- await assert.rejects(
- server.listen({ preferredAddress: { port: -1 } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-
- for (const address of [1, 1n, null, false, [], {}]) {
- await assert.rejects(
- server.listen({ preferredAddress: { address } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }
-
- for (const type of [1, 'test', false, null, [], {}]) {
- await assert.rejects(
- server.listen({ preferredAddress: { type } }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }
-
- // Make sure that after all of the validation checks, the socket
- // is not actually marked as listening at all.
- assert.strictEqual(typeof server.listening, 'boolean');
- assert(!server.listening);
-}
-
-(async function() {
- await testAlreadyListening();
- await testListenAfterClose();
- await testInvalidOptions();
-})().then(common.mustCall());
-
-// Options to check
-// * [x] alpn
-// * [x] idleTimeout
-// * [x] activeConnectionIdLimit
-// * [x] maxAckDelay
-// * [x] maxData
-// * [x] maxUdpPayloadSize
-// * [x] maxStreamsBidi
-// * [x] maxStreamsUni
-// * [x] maxStreamDataBidiLocal
-// * [x] maxStreamDataBidiRemote
-// * [x] maxStreamDataUni
-// * [x] preferredAddress
-// * [x] requestCert
-// * [x] rejectUnauthorized
-
-// SecureContext Options
-// * [ ] ca
-// * [ ] cert
-// * [x] ciphers
-// * [ ] clientCertEngine
-// * [ ] crl
-// * [ ] dhparam
-// * [ ] groups
-// * [ ] ecdhCurve
-// * [ ] honorCipherOrder
-// * [ ] key
-// * [ ] passphrase
-// * [ ] pfx
-// * [ ] secureOptions
-// * [ ] sessionIdContext
diff --git a/test/parallel/test-quic-http3-client-server.js b/test/parallel/test-quic-http3-client-server.js
deleted file mode 100644
index 2367465947..0000000000
--- a/test/parallel/test-quic-http3-client-server.js
+++ /dev/null
@@ -1,151 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests a simple QUIC HTTP/3 client/server round-trip
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const fs = require('fs');
-
-const {
- key,
- cert,
- ca,
- debug,
- kHttp3Alpn,
- kServerPort,
- kClientPort,
- setupKeylog,
-} = require('../common/quic');
-
-const filedata = fs.readFileSync(__filename, { encoding: 'utf8' });
-
-const { createQuicSocket } = require('net');
-const kServerName = 'agent2'; // Intentionally the wrong servername
-
-const options = { key, cert, ca, alpn: kHttp3Alpn };
-
-const client = createQuicSocket({
- endpoint: { port: kClientPort },
- client: options
-});
-const server = createQuicSocket({
- endpoint: { port: kServerPort },
- server: options
-});
-
-client.on('close', common.mustCall());
-server.on('close', common.mustCall());
-
-const countdown = new Countdown(1, () => {
- debug('Countdown expired. Destroying sockets');
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- debug('QuicServerSession Created');
-
- assert.strictEqual(session.maxStreams.bidi, 100);
- assert.strictEqual(session.maxStreams.uni, 3);
-
- setupKeylog(session);
-
- session.on('secure', common.mustCall((_, alpn) => {
- debug('QuicServerSession handshake completed');
- assert.strictEqual(session.alpnProtocol, alpn);
- }));
-
- session.on('stream', common.mustCall((stream) => {
- debug('Bidirectional, Client-initiated stream %d received', stream.id);
- const file = fs.createReadStream(__filename);
- let data = '';
-
- assert(stream.submitInitialHeaders({ ':status': '200' }));
-
- file.pipe(stream);
- stream.setEncoding('utf8');
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':path', '/' ],
- [ ':authority', 'localhost' ],
- [ ':scheme', 'https' ],
- [ ':method', 'POST' ]
- ];
- assert.deepStrictEqual(expected, headers);
- debug('Received expected request headers');
- }));
- stream.on('informationalHeaders', common.mustNotCall());
- stream.on('trailingHeaders', common.mustNotCall());
-
- stream.on('data', (chunk) => {
- data += chunk;
- });
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, filedata);
- debug('Server received expected data for stream %d', stream.id);
- }));
- stream.on('close', common.mustCall());
- stream.on('finish', common.mustCall());
- }));
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- debug('Server is listening on port %d', server.endpoints[0].address.port);
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- servername: kServerName,
- h3: { maxPushes: 10 }
- });
- debug('QuicClientSession Created');
-
- req.on('close', common.mustCall());
-
- const file = fs.createReadStream(__filename);
- const stream = await req.openStream();
-
- assert(stream.submitInitialHeaders({
- ':method': 'POST',
- ':scheme': 'https',
- ':authority': 'localhost',
- ':path': '/',
- }));
- file.pipe(stream);
- let data = '';
- stream.resume();
- stream.setEncoding('utf8');
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':status', '200' ]
- ];
- assert.deepStrictEqual(expected, headers);
- debug('Received expected response headers');
- }));
- stream.on('informationalHeaders', common.mustNotCall());
- stream.on('trailingHeaders', common.mustNotCall());
-
- stream.on('data', (chunk) => data += chunk);
- stream.on('finish', common.mustCall());
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, filedata);
- debug('Client received expected data for stream %d', stream.id);
- }));
- stream.on('close', common.mustCall(() => {
- debug('Bidirectional, Client-initiated stream %d closed', stream.id);
- countdown.dec();
- }));
- debug('Bidirectional, Client-initiated stream %d opened', stream.id);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-http3-push.js b/test/parallel/test-quic-http3-push.js
deleted file mode 100644
index 9b5d45f823..0000000000
--- a/test/parallel/test-quic-http3-push.js
+++ /dev/null
@@ -1,159 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests a simple QUIC HTTP/3 client/server round-trip
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const { key, cert, ca, kHttp3Alpn } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-const { createWriteStream } = require('fs');
-
-const qlog = process.env.NODE_QLOG === '1';
-
-const options = { key, cert, ca, alpn: kHttp3Alpn, qlog };
-
-const client = createQuicSocket({ qlog, client: options });
-const server = createQuicSocket({ qlog, server: options });
-
-client.on('close', common.mustCall());
-server.on('close', common.mustCall());
-
-const countdown = new Countdown(2, () => {
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- if (qlog) session.qlog.pipe(createWriteStream('server.qlog'));
- session.on('stream', common.mustCall((stream) => {
- assert(stream.submitInitialHeaders({ ':status': '200' }));
-
- [-1, Number.MAX_SAFE_INTEGER + 1].forEach((highWaterMark) => {
- assert.throws(() => stream.pushStream({}, { highWaterMark }), {
- code: 'ERR_OUT_OF_RANGE'
- });
- });
- ['', 1n, {}, [], false].forEach((highWaterMark) => {
- assert.throws(() => stream.pushStream({}, { highWaterMark }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- });
- ['', 1, 1n, true, [], {}, 'zebra'].forEach((defaultEncoding) => {
- assert.throws(() => stream.pushStream({}, { defaultEncoding }), {
- code: 'ERR_INVALID_ARG_VALUE'
- });
- });
-
- const push = stream.pushStream({
- ':method': 'GET',
- ':scheme': 'https',
- ':authority': 'localhost',
- ':path': '/foo'
- });
- assert(push);
- push.submitInitialHeaders({ ':status': '200' });
- push.end('testing');
- push.on('close', common.mustCall());
- // TODO(@jasnell): There's current a bug where the last
- // _final callback is not being invoked in this case
- // push.on('finish', common.mustCall());
-
- stream.end('hello world');
- stream.resume();
- stream.on('end', common.mustCall());
- stream.on('close', common.mustCall());
- stream.on('finish', common.mustCall());
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':path', '/' ],
- [ ':authority', 'localhost' ],
- [ ':scheme', 'https' ],
- [ ':method', 'POST' ]
- ];
- assert.deepStrictEqual(expected, headers);
- }));
- stream.on('informationalHeaders', common.mustNotCall());
- stream.on('trailingHeaders', common.mustNotCall());
- }));
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- maxStreamsUni: 10,
- h3: { maxPushes: 10 }
- });
- if (qlog) req.qlog.pipe(createWriteStream('client.qlog'));
-
- req.on('stream', common.mustCall((stream) => {
- let data = '';
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [':status', '200']
- ];
- assert.deepStrictEqual(expected, headers);
- }));
-
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, 'testing');
- }));
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
- }));
-
- req.on('close', common.mustCall());
-
- const stream = await req.openStream();
-
- stream.on('pushHeaders', common.mustCall((headers, push_id) => {
- const expected = [
- [ ':path', '/foo' ],
- [ ':authority', 'localhost' ],
- [ ':scheme', 'https' ],
- [ ':method', 'GET' ]
- ];
- assert.deepStrictEqual(expected, headers);
- assert.strictEqual(push_id, 0);
- }));
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':status', '200' ]
- ];
- assert.deepStrictEqual(expected, headers);
- }));
- stream.on('informationalHeaders', common.mustNotCall());
- stream.on('trailingHeaders', common.mustNotCall());
-
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
-
- assert(stream.submitInitialHeaders({
- ':method': 'POST',
- ':scheme': 'https',
- ':authority': 'localhost',
- ':path': '/',
- }));
-
- stream.end('hello world');
- stream.resume();
- stream.on('finish', common.mustCall());
- stream.on('end', common.mustCall());
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-http3-trailers.js b/test/parallel/test-quic-http3-trailers.js
deleted file mode 100644
index 176eacf8aa..0000000000
--- a/test/parallel/test-quic-http3-trailers.js
+++ /dev/null
@@ -1,104 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests a simple QUIC HTTP/3 client/server round-trip
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const { key, cert, ca, kHttp3Alpn } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: kHttp3Alpn };
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-client.on('close', common.mustCall());
-server.on('close', common.mustCall());
-
-const countdown = new Countdown(1, () => {
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall((session) => {
-
- session.on('stream', common.mustCall((stream) => {
- assert(stream.submitInitialHeaders({ ':status': '200' }));
-
- stream.submitTrailingHeaders({ 'a': 1 });
- stream.end('hello world');
- stream.resume();
- stream.on('end', common.mustCall());
- stream.on('close', common.mustCall());
- stream.on('finish', common.mustCall());
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':path', '/' ],
- [ ':authority', 'localhost' ],
- [ ':scheme', 'https' ],
- [ ':method', 'POST' ]
- ];
- assert.deepStrictEqual(expected, headers);
- }));
-
- stream.on('trailingHeaders', common.mustCall((headers) => {
- const expected = [ [ 'b', '2' ] ];
- assert.deepStrictEqual(expected, headers);
- }));
-
- stream.on('informationalHeaders', common.mustNotCall());
- }));
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- maxStreamsUni: 10,
- h3: { maxPushes: 10 }
- });
-
- req.on('close', common.mustCall());
-
- const stream = await req.openStream();
-
- stream.on('trailingHeaders', common.mustCall((headers) => {
- const expected = [ [ 'a', '1' ] ];
- assert.deepStrictEqual(expected, headers);
- }));
-
- assert(stream.submitInitialHeaders({
- ':method': 'POST',
- ':scheme': 'https',
- ':authority': 'localhost',
- ':path': '/',
- }));
-
- stream.submitTrailingHeaders({ 'b': 2 });
- stream.end('hello world');
- stream.resume();
- stream.on('finish', common.mustCall());
- stream.on('end', common.mustCall());
-
- stream.on('initialHeaders', common.mustCall((headers) => {
- const expected = [
- [ ':status', '200' ]
- ];
- assert.deepStrictEqual(expected, headers);
- }));
- stream.on('informationalHeaders', common.mustNotCall());
-
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-idle-timeout.js b/test/parallel/test-quic-idle-timeout.js
deleted file mode 100644
index a10a8e0d1c..0000000000
--- a/test/parallel/test-quic-idle-timeout.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-const { key, cert, ca } = require('../common/quic');
-const { once } = require('events');
-
-const kALPN = 'zzz';
-const idleTimeout = common.platformTimeout(1);
-const options = { key, cert, ca, alpn: kALPN };
-
-// Test idleTimeout. The test will hang and fail with a timeout
-// if the idleTimeout is not working correctly.
-
-(async () => {
- const server = createQuicSocket({ server: options });
- const client = createQuicSocket({ client: options });
-
- server.on('session', common.mustCall());
-
- await server.listen();
-
- const session = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- idleTimeout,
- });
-
- await once(session, 'close');
-
- assert(session.idleTimeout);
- client.close();
- server.close();
-
- await Promise.all([
- once(client, 'close'),
- once(server, 'close')
- ]);
-})().then(common.mustCall());
-
-
-(async () => {
- const server = createQuicSocket({ server: options });
- const client = createQuicSocket({ client: options });
-
- server.on('session', common.mustCall(async (session) => {
- await once(session, 'close');
- assert(session.idleTimeout);
- client.close();
- server.close();
- await Promise.all([
- once(client, 'close'),
- once(server, 'close')
- ]);
- }));
-
- await server.listen({ idleTimeout });
-
- const session = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- await once(session, 'close');
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-ipv6only.js b/test/parallel/test-quic-ipv6only.js
deleted file mode 100644
index 40b027e431..0000000000
--- a/test/parallel/test-quic-ipv6only.js
+++ /dev/null
@@ -1,115 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-
-if (!common.hasIPv6)
- common.skip('missing ipv6');
-
-if (!common.hasQuic)
- common.skip('missing quic');
-
-common.skip(
- 'temporarily skip ipv6only check. dual stack support ' +
- 'is current broken on some platforms');
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-const { key, cert, ca } = require('../common/quic');
-const { once } = require('events');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-// Connecting to ipv6 server using "127.0.0.1" should work when
-// `ipv6Only` is set to `false`.
-async function ipv6() {
- const server = createQuicSocket({
- endpoint: { type: 'udp6' },
- server: options
- });
- const client = createQuicSocket({ client: options });
-
- server.on('session', common.mustCall((serverSession) => {
- serverSession.on('stream', common.mustCall());
- }));
-
- await server.listen();
-
- const session = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port
- });
-
- const stream = await session.openStream({ halfOpen: true });
- stream.end('hello');
-
- await once(stream, 'close');
-
- client.close();
- server.close();
-
- await Promise.allSettled([
- once(client, 'close'),
- once(server, 'close')
- ]);
-}
-
-// When the `ipv6Only` set to `true`, a client cann't connect to it
-// through "127.0.0.1".
-async function ipv6Only() {
- const server = createQuicSocket({
- endpoint: { type: 'udp6-only' },
- server: options
- });
- const client = createQuicSocket({ client: options });
-
- server.on('session', common.mustNotCall());
-
- await server.listen();
-
- // This will attempt to connect to the ipv4 localhost address
- // but should fail as the connection idle timeout expires.
- const session = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- idleTimeout: common.platformTimeout(1),
- });
-
- session.on('secure', common.mustNotCall());
-
- await once(session, 'close');
-
- client.close();
- server.close();
-
- await Promise.allSettled([
- once(client, 'close'),
- once(server, 'close')
- ]);
-}
-
-// Creating the QuicSession fails when connect type does not match the
-// the connect IP address...
-async function mismatch() {
- const client = createQuicSocket({ client: options });
-
- await assert.rejects(client.connect({
- address: common.localhostIPv4,
- port: 1234,
- type: 'udp6',
- idleTimeout: common.platformTimeout(1),
- }), {
- code: 'ERR_QUIC_FAILED_TO_CREATE_SESSION'
- });
-
- client.close();
-
- await Promise.allSettled([
- once(client, 'close'),
- ]);
-}
-
-ipv6()
- .then(ipv6Only)
- .then(mismatch)
- .then(common.mustCall());
diff --git a/test/parallel/test-quic-keylog.js b/test/parallel/test-quic-keylog.js
deleted file mode 100644
index 0c5c7503e1..0000000000
--- a/test/parallel/test-quic-keylog.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests QUIC keylogging
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { key, cert, ca } = require('../common/quic');
-const { once } = require('events');
-
-const { createQuicSocket } = require('net');
-
-const kKeylogs = [
- /^CLIENT_HANDSHAKE_TRAFFIC_SECRET .*/,
- /^SERVER_HANDSHAKE_TRAFFIC_SECRET .*/,
- /^QUIC_CLIENT_HANDSHAKE_TRAFFIC_SECRET .*/,
- /^QUIC_SERVER_HANDSHAKE_TRAFFIC_SECRET .*/,
- /^CLIENT_TRAFFIC_SECRET_0 .*/,
- /^SERVER_TRAFFIC_SECRET_0 .*/,
- /^QUIC_CLIENT_TRAFFIC_SECRET_0 .*/,
- /^QUIC_SERVER_TRAFFIC_SECRET_0 .*/,
-];
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-const client = createQuicSocket({ client: options });
-
-const kServerKeylogs = Array.from(kKeylogs);
-const kClientKeylogs = Array.from(kKeylogs);
-
-(async () => {
-
- server.on('session', common.mustCall((session) => {
- session.on('keylog', common.mustCall((line) => {
- assert.match(line.toString(), kServerKeylogs.shift());
- }, kServerKeylogs.length));
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- req.on('keylog', common.mustCall((line) => {
- assert.match(line.toString(), kClientKeylogs.shift());
- }, kClientKeylogs.length));
-
- await once(req, 'secure');
-
- server.close();
- client.close();
-
- await Promise.allSettled([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
- assert.strictEqual(kServerKeylogs.length, 0);
- assert.strictEqual(kClientKeylogs.length, 0);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-maxconnectionsperhost.js b/test/parallel/test-quic-maxconnectionsperhost.js
deleted file mode 100644
index 91a0a53908..0000000000
--- a/test/parallel/test-quic-maxconnectionsperhost.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { createQuicSocket } = require('net');
-const assert = require('assert');
-const Countdown = require('../common/countdown');
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'zzz', idleTimeout: 0 };
-
-// QuicSockets must throw errors when maxConnectionsPerHost is not a
-// safe integer or is out of range.
-{
- [-1, 0, Number.MAX_SAFE_INTEGER + 1, 1.1].forEach((maxConnectionsPerHost) => {
- assert.throws(() => createQuicSocket({ maxConnectionsPerHost }), {
- code: 'ERR_OUT_OF_RANGE'
- });
- });
-}
-
-// Test that new client sessions will be closed when it exceeds
-// maxConnectionsPerHost.
-(async function() {
- const kMaxConnectionsPerHost = 5;
-
- const client = createQuicSocket({ client: options });
- const server = createQuicSocket({
- maxConnectionsPerHost: kMaxConnectionsPerHost,
- server: options
- });
-
- const countdown = new Countdown(kMaxConnectionsPerHost + 1, () => {
- client.close();
- server.close();
- });
-
- server.on('session', common.mustCall(() => {}, kMaxConnectionsPerHost));
-
- server.on('close', common.mustCall(() => {
- assert.strictEqual(server.serverBusyCount, 1);
- }));
-
- await server.listen();
-
- const sessions = [];
- for (let i = 0; i < kMaxConnectionsPerHost; i += 1) {
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
- req.on('error', common.mustNotCall());
- req.on('close', common.mustCall(() => countdown.dec()));
- sessions.push(req);
- }
-
- const extra = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
- extra.on('error', common.mustNotCall());
- extra.on('close', common.mustCall(() => {
- assert.strictEqual(extra.closeCode.code, 2);
- countdown.dec();
- // Shutdown the remaining open sessions.
- setImmediate(common.mustCall(() => {
- for (const req of sessions)
- req.close();
- }));
- }));
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-process-cleanup.js b/test/parallel/test-quic-process-cleanup.js
deleted file mode 100644
index b7ba0caa70..0000000000
--- a/test/parallel/test-quic-process-cleanup.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Flags: --no-warnings --expose-internals
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-// Test that shutting down a process containing an active QUIC server behaves
-// well. We use Workers because they have a more clearly defined shutdown
-// sequence and we can stop execution at any point.
-
-const { kRemoveFromSocket } = require('internal/quic/core');
-const { createQuicSocket } = require('net');
-const { Worker, workerData } = require('worker_threads');
-
-if (workerData == null) {
- new Worker(__filename, { workerData: { removeFromSocket: true } });
- new Worker(__filename, { workerData: { removeFromSocket: false } });
- return;
-}
-
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'meow' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-server.on('close', common.mustNotCall());
-client.on('close', common.mustNotCall());
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: false });
- stream.write('Hi!');
- stream.on('data', common.mustNotCall());
- stream.on('finish', common.mustNotCall());
- stream.on('close', common.mustNotCall());
- stream.on('end', common.mustNotCall());
-
- session.on('close', common.mustNotCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustCall(() => {
- if (workerData.removeFromSocket)
- req[kRemoveFromSocket]();
- process.exit(); // Exits the worker thread
- }));
-
- req.on('close', common.mustNotCall());
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-qlog.js b/test/parallel/test-quic-qlog.js
deleted file mode 100644
index 3d212346e1..0000000000
--- a/test/parallel/test-quic-qlog.js
+++ /dev/null
@@ -1,76 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { makeUDPPair } = require('../common/udppair');
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-const { kUDPHandleForTesting } = require('internal/quic/core');
-
-const { key, cert, ca } = require('../common/quic');
-
-const { serverSide, clientSide } = makeUDPPair();
-const options = { key, cert, ca, alpn: 'meow' };
-
-const server = createQuicSocket({
- validateAddress: true,
- endpoint: { [kUDPHandleForTesting]: serverSide._handle },
- server: options,
- qlog: true
-});
-serverSide.afterBind();
-
-const client = createQuicSocket({
- endpoint: { [kUDPHandleForTesting]: clientSide._handle },
- client: options,
- qlog: true
-});
-clientSide.afterBind();
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- gatherQlog(session, 'server');
- (await session.openStream({ halfOpen: true })).end('Hi!');
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- qlog: true
- });
-
- gatherQlog(req, 'client');
-
- req.on('stream', common.mustCall((stream) => {
- stream.resume();
- stream.on('end', common.mustCall(() => {
- req.close();
- }));
- }));
-})().then(common.mustCall());
-
-function setupQlog(qlog) {
- let data = '';
- qlog.setEncoding('utf8');
- qlog.on('data', (chunk) => data += chunk);
- qlog.once('end', common.mustCall(() => {
- const { qlog_version, traces } = JSON.parse(data);
- assert.strictEqual(typeof qlog_version, 'string');
- assert.strictEqual(typeof traces, 'object');
- }));
-}
-
-function gatherQlog(session, id) {
- switch (id) {
- case 'server':
- setupQlog(session.qlog);
- break;
- case 'client':
- session.on('qlog', setupQlog);
- break;
- }
-}
diff --git a/test/parallel/test-quic-quicendpoint-address.js b/test/parallel/test-quic-quicendpoint-address.js
deleted file mode 100644
index 742ecfbb71..0000000000
--- a/test/parallel/test-quic-quicendpoint-address.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests multiple aspects of QuicSocket multiple endpoint support
-
-const common = require('../common');
-const { once } = require('events');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-
-const { key, cert, ca } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-async function Test1(options, address) {
- const server = createQuicSocket(options);
- server.on('close', common.mustCall());
-
- const endpoint = server.endpoints[0];
-
- assert.strictEqual(endpoint.bound, false);
- assert.deepStrictEqual({}, endpoint.address);
-
- await endpoint.bind();
-
- assert.strictEqual(endpoint.bound, true);
- assert.strictEqual(endpoint.destroyed, false);
- assert.strictEqual(typeof endpoint.address.port, 'number');
- assert.strictEqual(endpoint.address.address, address);
-
- await endpoint.close();
-
- assert.strictEqual(endpoint.destroyed, true);
-}
-
-async function Test2() {
- // Creates a server with multiple endpoints (one on udp4 and udp6)
- const server = createQuicSocket({ endpoint: { type: 'udp6' } });
- server.addEndpoint();
- assert.strictEqual(server.endpoints.length, 2);
- assert.strictEqual(server.endpoints[0].bound, false);
- assert.deepStrictEqual({}, server.endpoints[0].address);
-
- server.listen({ key, cert, ca, alpn: 'zzz' });
-
- // Attempting to add an endpoint after fails.
- assert.throws(() => server.addEndpoint(), {
- code: 'ERR_INVALID_STATE'
- });
-
- await once(server, 'ready');
-
- assert.strictEqual(server.endpoints.length, 2);
-
- {
- const endpoint = server.endpoints[0];
- assert.strictEqual(endpoint.bound, true);
- assert.strictEqual(endpoint.destroyed, false);
- assert.strictEqual(endpoint.address.family, 'IPv6');
- assert.strictEqual(typeof endpoint.address.port, 'number');
- assert.strictEqual(endpoint.address.address, '::');
- }
-
- {
- const endpoint = server.endpoints[1];
- assert.strictEqual(endpoint.bound, true);
- assert.strictEqual(endpoint.destroyed, false);
- assert.strictEqual(endpoint.address.family, 'IPv4');
- assert.strictEqual(typeof endpoint.address.port, 'number');
- assert.strictEqual(endpoint.address.address, '0.0.0.0');
- }
-
- server.close();
- for (const endpoint of server.endpoints)
- assert.strictEqual(endpoint.destroyed, true);
-}
-
-const tests = [
- Test1({}, '0.0.0.0'),
- Test1({ endpoint: { port: 0 } }, '0.0.0.0'),
- Test1({ endpoint: { address: '127.0.0.1', port: 0 } }, '127.0.0.1'),
- Test1({ endpoint: { address: 'localhost', port: 0 } }, '127.0.0.1')
-];
-
-if (common.hasIPv6) {
- tests.push(
- Test1({ endpoint: { type: 'udp6' } }, '::'),
- Test1({ endpoint: { type: 'udp6', address: 'localhost' } }, '::1'),
- Test2());
-}
-
-Promise.all(tests);
diff --git a/test/parallel/test-quic-quicsession-resume.js b/test/parallel/test-quic-quicsession-resume.js
deleted file mode 100644
index f8f8ad6d27..0000000000
--- a/test/parallel/test-quic-quicsession-resume.js
+++ /dev/null
@@ -1,97 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests a simple QUIC client/server round-trip
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { Buffer } = require('buffer');
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
- debug,
-} = require('../common/quic');
-
-const { createWriteStream } = require('fs');
-const { createQuicSocket } = require('net');
-
-const qlog = process.env.NODE_QLOG === '1';
-const options = { key, cert, ca, alpn: 'zzz', qlog };
-
-const server = createQuicSocket({ qlog, server: options });
-const client = createQuicSocket({ qlog, client: options });
-
-const countdown = new Countdown(2, () => {
- server.close();
- client.close();
-});
-
-(async function() {
- let counter = 0;
- server.on('session', common.mustCall((session) => {
- if (qlog) session.qlog.pipe(createWriteStream(`server-${counter++}.qlog`));
- session.on('stream', common.mustCall((stream) => {
- stream.on('close', common.mustCall());
- assert(stream.unidirectional);
- assert(!stream.writable);
- stream.resume();
- }));
- }, 2));
-
- await server.listen();
-
- let storedTicket;
- let storedParams;
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
- if (qlog) req.qlog.pipe(createWriteStream(`client-${counter}.qlog`));
-
- req.on('sessionTicket', common.mustCall((ticket, params) => {
- assert(ticket instanceof Buffer);
- assert(params instanceof Buffer);
- debug(' Ticket: %s', ticket.toString('hex'));
- debug(' Params: %s', params.toString('hex'));
- storedTicket = ticket;
- storedParams = params;
- }, 1));
-
- const stream = await req.openStream({ halfOpen: true });
- stream.end('hello');
- stream.on('close', () => {
- countdown.dec();
- // Wait a turn then start a new session using the stored
- // ticket and transportParameters
- setImmediate(newSession, storedTicket, storedParams);
- });
-
- async function newSession(sessionTicket, remoteTransportParams) {
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- sessionTicket,
- remoteTransportParams
- });
- if (qlog) req.qlog.pipe(createWriteStream('client2.qlog'));
-
- assert(req.allowEarlyData);
-
- const stream = await req.openStream({ halfOpen: true });
- stream.end('hello');
- stream.on('error', common.mustNotCall());
- stream.on('close', common.mustCall(() => countdown.dec()));
-
- // TODO(@jasnell): This will be false for now because no
- // early data was sent. Once we actually start making
- // use of early data on the client side, this should be
- // true when the early data was accepted.
- assert(!req.usingEarlyData);
- }
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsession-send-fd.js b/test/parallel/test-quic-quicsession-send-fd.js
deleted file mode 100644
index 6694052d86..0000000000
--- a/test/parallel/test-quic-quicsession-send-fd.js
+++ /dev/null
@@ -1,99 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-const { once } = require('events');
-const fs = require('fs');
-const qlog = process.env.NODE_QLOG === '1';
-
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'meow', qlog };
-
-const variants = [];
-for (const variant of ['sendFD', 'sendFile', 'sendFD+fileHandle']) {
- for (const offset of [-1, 0, 100]) {
- for (const length of [-1, 100]) {
- variants.push({ variant, offset, length });
- }
- }
-}
-
-(async function() {
- await Promise.all(variants.map(test));
-})().then(common.mustCall());
-
-async function test({ variant, offset, length }) {
- const server = createQuicSocket({ qlog, server: options });
- const client = createQuicSocket({ qlog, client: options });
- let fd;
-
- server.on('session', common.mustCall(async (session) => {
- if (qlog) {
- session.qlog.pipe(
- fs.createWriteStream(`server-${variant}-${offset}-${length}.qlog`));
- }
-
- const stream = await session.openStream({ halfOpen: true });
-
- // The data and end events won't emit because
- // the stream is never readable.
- stream.on('data', common.mustNotCall());
- stream.on('end', common.mustNotCall());
- stream.on('finish', common.mustCall());
- stream.on('close', common.mustCall());
-
- if (variant === 'sendFD') {
- fd = fs.openSync(__filename, 'r');
- stream.sendFD(fd, { offset, length });
- } else if (variant === 'sendFD+fileHandle') {
- fs.promises.open(__filename, 'r').then(common.mustCall((handle) => {
- fd = handle;
- stream.sendFD(handle, { offset, length });
- }));
- } else {
- assert.strictEqual(variant, 'sendFile');
- stream.sendFile(__filename, { offset, length });
- }
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
- if (qlog) {
- req.qlog.pipe(
- fs.createWriteStream(`client-${variant}-${offset}-${length}.qlog`));
- }
-
- req.on('stream', common.mustCall((stream) => {
- const data = [];
- stream.on('data', (chunk) => data.push(chunk));
- stream.on('end', common.mustCall(() => {
- let expectedContent = fs.readFileSync(__filename);
- if (offset !== -1) expectedContent = expectedContent.slice(offset);
- if (length !== -1) expectedContent = expectedContent.slice(0, length);
- assert.deepStrictEqual(Buffer.concat(data), expectedContent);
- if (fd !== undefined) {
- if (fd.close) fd.close().then(common.mustCall());
- else fs.closeSync(fd);
- }
- }));
- stream.on('close', common.mustCall(() => {
- client.close();
- server.close();
- }));
- }));
-
- await Promise.all([
- once(client, 'close'),
- once(server, 'close')
- ]);
-}
diff --git a/test/parallel/test-quic-quicsession-send-file-close-before-open.js b/test/parallel/test-quic-quicsession-send-file-close-before-open.js
deleted file mode 100644
index 368a8d046e..0000000000
--- a/test/parallel/test-quic-quicsession-send-file-close-before-open.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { createQuicSocket } = require('net');
-const { once } = require('events');
-const fs = require('fs');
-
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'meow' };
-
-const server = createQuicSocket({ server: options });
-const client = createQuicSocket({ client: options });
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: false });
-
- fs.open = common.mustCall(fs.open);
- fs.close = common.mustCall(fs.close);
-
- stream.sendFile(__filename);
- stream.destroy(); // Destroy the stream before opening the fd finishes.
-
- session.close();
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustNotCall());
-
- req.on('close', common.mustCall(() => {
- client.close();
- server.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
-})().then(common.mustCall());
-
-server.on('close', common.mustCall());
diff --git a/test/parallel/test-quic-quicsession-send-file-open-error-handled.js b/test/parallel/test-quic-quicsession-send-file-open-error-handled.js
deleted file mode 100644
index 96257b9892..0000000000
--- a/test/parallel/test-quic-quicsession-send-file-open-error-handled.js
+++ /dev/null
@@ -1,51 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const path = require('path');
-const { createQuicSocket } = require('net');
-const { once } = require('events');
-
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'meow' };
-
-const server = createQuicSocket({ server: options });
-const client = createQuicSocket({ client: options });
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: true });
- const nonexistentPath = path.resolve(__dirname, 'nonexistent.file');
- stream.sendFile(nonexistentPath, {
- onError: common.expectsError({
- code: 'ENOENT',
- syscall: 'open',
- path: nonexistentPath
- })
- });
- session.close();
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustNotCall());
-
- req.on('close', common.mustCall(() => {
- client.close();
- server.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsession-send-file-open-error.js b/test/parallel/test-quic-quicsession-send-file-open-error.js
deleted file mode 100644
index 5d96c5c82b..0000000000
--- a/test/parallel/test-quic-quicsession-send-file-open-error.js
+++ /dev/null
@@ -1,51 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const path = require('path');
-const { createQuicSocket } = require('net');
-const { once } = require('events');
-
-const { key, cert, ca } = require('../common/quic');
-const options = { key, cert, ca, alpn: 'meow' };
-
-const server = createQuicSocket({ server: options });
-const client = createQuicSocket({ client: options });
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- const stream = await session.openStream({ halfOpen: false });
- const nonexistentPath = path.resolve(__dirname, 'nonexistent.file');
- stream.on('error', common.expectsError({
- code: 'ENOENT',
- syscall: 'open',
- path: nonexistentPath
- }));
- stream.sendFile(nonexistentPath);
- session.close();
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustNotCall());
-
- req.on('close', common.mustCall(() => {
- server.close();
- client.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsession-server-destroy-early.js b/test/parallel/test-quic-quicsession-server-destroy-early.js
deleted file mode 100644
index 011afea837..0000000000
--- a/test/parallel/test-quic-quicsession-server-destroy-early.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Test that destroying a QuicStream immediately and synchronously
-// after creation does not crash the process and closes the streams
-// abruptly on both ends of the connection.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { once } = require('events');
-const { key, cert, ca } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-
-const server = createQuicSocket({ server: options });
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('stream', common.mustNotCall());
- session.on('close', common.mustCall(async () => {
- await Promise.all([
- client.close(),
- server.close()
- ]);
- assert.rejects(server.close(), {
- code: 'ERR_INVALID_STATE',
- name: 'Error'
- });
- }));
- session.destroy();
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
- req.on('secure', common.mustNotCall());
- req.on('close', common.mustCall());
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsocket-close.js b/test/parallel/test-quic-quicsocket-close.js
deleted file mode 100644
index 03aaf5281f..0000000000
--- a/test/parallel/test-quic-quicsocket-close.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-
-const socket = createQuicSocket();
-socket.on('close', common.mustCall());
-
-(async function() {
- await socket.close();
- assert.rejects(() => socket.close(), {
- code: 'ERR_INVALID_STATE'
- });
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsocket-packetloss-stream-rx.js b/test/parallel/test-quic-quicsocket-packetloss-stream-rx.js
deleted file mode 100644
index d3730423b3..0000000000
--- a/test/parallel/test-quic-quicsocket-packetloss-stream-rx.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests that stream data is successfully transmitted under
-// packet loss conditions on the receiving end.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-common.skip('temporarily skip packetloss tests for refactoring');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
- debug
-} = require('../common/quic');
-const { once } = require('events');
-const { pipeline } = require('stream');
-
-const { createQuicSocket } = require('net');
-
-const kData = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-const options = { key, cert, ca, alpn: 'echo' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-// Both client and server will drop received packets about 20% of the time
-// It is important to keep in mind that this will make the runtime of the
-// test non-deterministic. If we encounter flaky timeouts with this test,
-// the randomized packet loss will be the reason, but random packet loss
-// is exactly what is being tested. So if flaky timeouts do occur, it will
-// be best to extend the failure timeout for this test.
-server.setDiagnosticPacketLoss({ rx: 0.2 });
-client.setDiagnosticPacketLoss({ rx: 0.2 });
-
-const countdown = new Countdown(1, () => {
- debug('Countdown expired. Destroying sockets');
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- debug('QuicServerSession Created');
- session.on('stream', common.mustCall((stream) => {
- debug('Bidirectional, Client-initiated stream %d received', stream.id);
- pipeline(stream, stream, common.mustSucceed());
- }));
- }));
-
- await server.listen();
-
- debug('Server is listening on port %d', server.endpoints[0].address.port);
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- const stream = await req.openStream();
-
- let n = 0;
- // This forces multiple stream packets to be sent out
- // rather than all the data being written in a single
- // packet.
- function sendChunk() {
- if (n < kData.length) {
- stream.write(kData[n++], common.mustCall());
- setImmediate(sendChunk);
- } else {
- stream.end();
- }
- }
- sendChunk();
-
- let data = '';
- stream.resume();
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- debug('Received data: %s', kData);
- assert.strictEqual(data, kData);
- }));
-
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsocket-packetloss-stream-tx.js b/test/parallel/test-quic-quicsocket-packetloss-stream-tx.js
deleted file mode 100644
index d33bbf6aef..0000000000
--- a/test/parallel/test-quic-quicsocket-packetloss-stream-tx.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests that stream data is successfully transmitted under
-// packet loss conditions on the transmitting end.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-common.skip('temporarily skip packetloss tests for refactoring');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
- debug
-} = require('../common/quic');
-const { once } = require('events');
-const { pipeline } = require('stream');
-
-const { createQuicSocket } = require('net');
-
-const kData = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-const options = { key, cert, ca, alpn: 'echo' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-// Both client and server will drop received packets about 20% of the time
-// It is important to keep in mind that this will make the runtime of the
-// test non-deterministic. If we encounter flaky timeouts with this test,
-// the randomized packet loss will be the reason, but random packet loss
-// is exactly what is being tested. So if flaky timeouts do occur, it will
-// be best to extend the failure timeout for this test.
-server.setDiagnosticPacketLoss({ tx: 0.2 });
-client.setDiagnosticPacketLoss({ tx: 0.2 });
-
-const countdown = new Countdown(1, () => {
- debug('Countdown expired. Destroying sockets');
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- debug('QuicServerSession Created');
- session.on('stream', common.mustCall((stream) => {
- debug('Bidirectional, Client-initiated stream %d received', stream.id);
- pipeline(stream, stream, common.mustSucceed());
- }));
- }));
-
- await server.listen();
-
- debug('Server is listening on port %d', server.endpoints[0].address.port);
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- const stream = await req.openStream();
-
- let n = 0;
- // This forces multiple stream packets to be sent out
- // rather than all the data being written in a single
- // packet.
- function sendChunk() {
- if (n < kData.length) {
- stream.write(kData[n++], common.mustCall());
- setImmediate(sendChunk);
- } else {
- stream.end();
- }
- }
- sendChunk();
-
- let data = '';
- stream.resume();
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- debug('Received data: %s', kData);
- assert.strictEqual(data, kData);
- }));
-
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsocket-serverbusy.js b/test/parallel/test-quic-quicsocket-serverbusy.js
deleted file mode 100644
index d3fd399344..0000000000
--- a/test/parallel/test-quic-quicsocket-serverbusy.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Tests QUIC server busy support
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { once } = require('events');
-const { key, cert, ca } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-client.on('close', common.mustCall());
-server.on('close', common.mustCall());
-server.on('listening', common.mustCall());
-server.on('busy', common.mustCall((busy) => {
- assert.strictEqual(busy, true);
-}));
-
-// When the server is set as busy, all connections
-// will be rejected with a SERVER_BUSY response.
-server.serverBusy = true;
-
-(async function() {
- server.on('session', common.mustNotCall());
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- req.on('secure', common.mustNotCall());
-
- req.on('close', common.mustCall(() => {
- assert.strictEqual(req.closeCode.code, 2);
- server.close();
- client.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicsocket.js b/test/parallel/test-quic-quicsocket.js
deleted file mode 100644
index e4ee489506..0000000000
--- a/test/parallel/test-quic-quicsocket.js
+++ /dev/null
@@ -1,150 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Test QuicSocket constructor option errors.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-
-const { createQuicSocket } = require('net');
-
-const socket = createQuicSocket();
-assert(socket);
-
-// Before listen is called, serverSecureContext is always undefined.
-assert.strictEqual(socket.serverSecureContext, undefined);
-
-assert.deepStrictEqual(socket.endpoints.length, 1);
-
-// Socket is not bound, so address should be empty
-assert.deepStrictEqual(socket.endpoints[0].address, {});
-
-// Socket is not bound
-assert(!socket.bound);
-
-// Socket is not pending
-assert(!socket.pending);
-
-// Socket is not destroyed
-assert(!socket.destroyed);
-
-assert.strictEqual(typeof socket.duration, 'number');
-assert.strictEqual(typeof socket.boundDuration, 'number');
-assert.strictEqual(typeof socket.listenDuration, 'number');
-assert.strictEqual(typeof socket.bytesReceived, 'number');
-assert.strictEqual(socket.bytesReceived, 0);
-assert.strictEqual(socket.bytesSent, 0);
-assert.strictEqual(socket.packetsReceived, 0);
-assert.strictEqual(socket.packetsSent, 0);
-assert.strictEqual(socket.serverSessions, 0);
-assert.strictEqual(socket.clientSessions, 0);
-
-const endpoint = socket.endpoints[0];
-assert(endpoint);
-
-// Will throw because the QuicSocket is not bound
-{
- const err = { code: 'EBADF' };
- assert.throws(() => endpoint.setTTL(1), err);
- assert.throws(() => endpoint.setMulticastTTL(1), err);
- assert.throws(() => endpoint.setBroadcast(), err);
- assert.throws(() => endpoint.setMulticastLoopback(), err);
- assert.throws(() => endpoint.setMulticastInterface('0.0.0.0'), err);
- // TODO(@jasnell): Verify behavior of add/drop membership then test
- // assert.throws(() => endpoint.addMembership(
- // '127.0.0.1', '127.0.0.1'), err);
- // assert.throws(() => endpoint.dropMembership(
- // '127.0.0.1', '127.0.0.1'), err);
-}
-
-['test', null, {}, [], 1n, false].forEach((rx) => {
- assert.throws(() => socket.setDiagnosticPacketLoss({ rx }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-['test', null, {}, [], 1n, false].forEach((tx) => {
- assert.throws(() => socket.setDiagnosticPacketLoss({ tx }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-[
- { rx: -1 },
- { rx: 1.1 },
- { tx: -1 },
- { tx: 1.1 }
-].forEach((options) => {
- assert.throws(() => socket.setDiagnosticPacketLoss(options), {
- code: 'ERR_OUT_OF_RANGE'
- });
-});
-
-[1, 1n, [], {}, null].forEach((arg) => {
- assert.throws(() => socket.serverBusy = arg, {
- code: 'ERR_INVALID_ARG_TYPE'
- });
-});
-
-(async function() {
- const p = socket.listen({ alpn: 'zzz' });
- assert(socket.pending);
-
- await p;
-
- assert(endpoint.bound);
-
- // QuicSocket is already listening.
- await assert.rejects(socket.listen(), {
- code: 'ERR_INVALID_STATE'
- });
-
- assert.strictEqual(typeof endpoint.address.address, 'string');
- assert.strictEqual(typeof endpoint.address.port, 'number');
- assert.strictEqual(typeof endpoint.address.family, 'string');
-
- if (!common.isWindows)
- assert.strictEqual(typeof endpoint.fd, 'number');
-
- endpoint.setTTL(1);
- endpoint.setMulticastTTL(1);
- endpoint.setBroadcast();
- endpoint.setBroadcast(true);
- endpoint.setBroadcast(false);
-
- endpoint.setMulticastLoopback();
- endpoint.setMulticastLoopback(true);
- endpoint.setMulticastLoopback(false);
-
- endpoint.setMulticastInterface('0.0.0.0');
-
- socket.setDiagnosticPacketLoss({ rx: 0.5, tx: 0.5 });
-
- socket.destroy();
- assert(socket.destroyed);
-})().then(common.mustCall());
-
-socket.on('close', common.mustCall(() => {
- [
- 'ref',
- 'unref',
- 'setTTL',
- 'setMulticastTTL',
- 'setBroadcast',
- 'setMulticastLoopback',
- 'setMulticastInterface',
- 'addMembership',
- 'dropMembership'
- ].forEach((op) => {
- assert.throws(() => endpoint[op](), {
- code: 'ERR_INVALID_STATE'
- });
- });
-
- assert.throws(() => { socket.serverBusy = true; }, {
- code: 'ERR_INVALID_STATE'
- });
-}));
diff --git a/test/parallel/test-quic-quicstream-close-early.js b/test/parallel/test-quic-quicstream-close-early.js
deleted file mode 100644
index b134b39e2f..0000000000
--- a/test/parallel/test-quic-quicstream-close-early.js
+++ /dev/null
@@ -1,84 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const { key, cert, ca } = require('../common/quic');
-const { once } = require('events');
-const { createQuicSocket } = require('net');
-
-const qlog = process.env.NODE_QLOG === '1';
-const { createWriteStream } = require('fs');
-
-const options = { key, cert, ca, alpn: 'zzz', qlog };
-
-const client = createQuicSocket({ qlog, client: options });
-const server = createQuicSocket({ qlog, server: options });
-
-const countdown = new Countdown(2, () => {
- server.close();
- client.close();
-});
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- if (qlog) session.qlog.pipe(createWriteStream('server.qlog'));
- const uni = await session.openStream({ halfOpen: true });
- uni.write('hi', common.mustSucceed());
- uni.on('error', common.mustNotCall());
- uni.on('data', common.mustNotCall());
- uni.on('close', common.mustCall());
- uni.close();
-
- session.on('stream', common.mustCall((stream) => {
- assert(stream.bidirectional);
- assert(stream.readable);
- assert(stream.writable);
- stream.on('close', common.mustCall());
- stream.end();
- stream.resume();
- }));
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- });
- if (qlog) req.qlog.pipe(createWriteStream('client.qlog'));
-
- req.on('stream', common.mustCall((stream) => {
- assert(stream.unidirectional);
- assert(stream.readable);
- assert(!stream.writable);
- stream.on('data', common.mustCall((chunk) => {
- assert.strictEqual(chunk.toString(), 'hi');
- }));
- stream.on('end', common.mustCall());
- stream.on('close', common.mustCall(() => {
- countdown.dec();
- }));
- }));
-
- const stream = await req.openStream();
- stream.write('hello', common.mustSucceed());
- stream.write('there', common.mustSucceed());
- stream.resume();
- stream.on('error', common.mustNotCall());
- stream.on('end', common.mustCall());
- stream.on('close', common.mustCall());
- await stream.close();
- countdown.dec();
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicstream-destroy.js b/test/parallel/test-quic-quicstream-destroy.js
deleted file mode 100644
index 3f0b0bf49e..0000000000
--- a/test/parallel/test-quic-quicstream-destroy.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Test that destroying a QuicStream immediately and synchronously
-// after creation does not crash the process and closes the streams
-// abruptly on both ends of the connection.
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { once } = require('events');
-const { key, cert, ca } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('stream', common.mustCall((stream) => {
- stream.destroy();
- stream.on('close', common.mustCall());
- stream.on('error', common.mustNotCall());
- assert(stream.destroyed);
- }));
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port
- });
-
- const stream = await req.openStream();
- stream.end('foo');
- // Do not explicitly end the stream here.
-
- stream.resume();
- stream.on('end', common.mustCall());
-
- stream.on('close', common.mustCall(() => {
- assert(stream.destroyed);
- client.close();
- server.close();
- }));
-
- req.on('close', common.mustCall());
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-quicstream-identifiers.js b/test/parallel/test-quic-quicstream-identifiers.js
deleted file mode 100644
index 98ffc3e9a0..0000000000
--- a/test/parallel/test-quic-quicstream-identifiers.js
+++ /dev/null
@@ -1,141 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-// Tests that both client and server can open
-// bidirectional and unidirectional streams,
-// and that the properties for each are set
-// accordingly.
-//
-// +------+----------------------------------+
-// | ID | Stream Type |
-// +------+----------------------------------+
-// | 0 | Client-Initiated, Bidirectional |
-// | | |
-// | 1 | Server-Initiated, Bidirectional |
-// | | |
-// | 2 | Client-Initiated, Unidirectional |
-// | | |
-// | 3 | Server-Initiated, Unidirectional |
-// +------+----------------------------------+
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const Countdown = require('../common/countdown');
-const assert = require('assert');
-const { once } = require('events');
-const { key, cert, ca } = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-const countdown = new Countdown(4, () => {
- server.close();
- client.close();
-});
-
-const closeHandler = common.mustCall(() => countdown.dec(), 4);
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- ([3, 1n, [], {}, null, 'meow']).forEach((halfOpen) => {
- assert.rejects(
- session.openStream({ halfOpen }), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- });
-
- const uni = await session.openStream({ halfOpen: true });
- uni.end('test');
-
- const bidi = await session.openStream();
- bidi.end('test');
- bidi.resume();
- bidi.on('end', common.mustCall());
-
- assert.strictEqual(uni.id, 3);
- assert(uni.unidirectional);
- assert(uni.serverInitiated);
- assert(!uni.bidirectional);
- assert(!uni.clientInitiated);
-
- assert.strictEqual(bidi.id, 1);
- assert(bidi.bidirectional);
- assert(bidi.serverInitiated);
- assert(!bidi.unidirectional);
- assert(!bidi.clientInitiated);
-
- session.on('stream', common.mustCall((stream) => {
- assert(stream.clientInitiated);
- assert(!stream.serverInitiated);
- switch (stream.id) {
- case 0:
- assert(stream.bidirectional);
- assert(!stream.unidirectional);
- stream.end('test');
- break;
- case 2:
- assert(stream.unidirectional);
- assert(!stream.bidirectional);
- break;
- }
- stream.resume();
- stream.on('end', common.mustCall());
- }, 2));
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- const bidi = await req.openStream();
- bidi.end('test');
- bidi.resume();
- bidi.on('close', closeHandler);
- assert.strictEqual(bidi.id, 0);
-
- assert(bidi.clientInitiated);
- assert(bidi.bidirectional);
- assert(!bidi.serverInitiated);
- assert(!bidi.unidirectional);
-
- const uni = await req.openStream({ halfOpen: true });
- uni.end('test');
- uni.on('close', closeHandler);
- assert.strictEqual(uni.id, 2);
-
- assert(uni.clientInitiated);
- assert(!uni.bidirectional);
- assert(!uni.serverInitiated);
- assert(uni.unidirectional);
-
- req.on('stream', common.mustCall((stream) => {
- assert(stream.serverInitiated);
- assert(!stream.clientInitiated);
- switch (stream.id) {
- case 1:
- assert(!stream.unidirectional);
- assert(stream.bidirectional);
- stream.end();
- break;
- case 3:
- assert(stream.unidirectional);
- assert(!stream.bidirectional);
- }
- stream.resume();
- stream.on('end', common.mustCall());
- stream.on('close', closeHandler);
- }, 2));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-server-busy-event-error-async.js b/test/parallel/test-quic-server-busy-event-error-async.js
deleted file mode 100644
index 7e8f86b689..0000000000
--- a/test/parallel/test-quic-server-busy-event-error-async.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('busy', common.mustCall(async () => {
- throw new Error('boom');
-}));
-
-server.on('close', common.mustCall());
-
-server.on('error', common.mustCall((err) => {
- assert.strictEqual(err.message, 'boom');
-}));
-
-assert.strictEqual(server.serverBusy, false);
-server.serverBusy = true;
diff --git a/test/parallel/test-quic-server-busy-event-error.js b/test/parallel/test-quic-server-busy-event-error.js
deleted file mode 100644
index d71e9d25e7..0000000000
--- a/test/parallel/test-quic-server-busy-event-error.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('busy', common.mustCall(() => {
- throw new Error('boom');
-}));
-
-server.on('close', common.mustCall());
-
-server.on('error', common.mustCall((err) => {
- assert.strictEqual(err.message, 'boom');
-}));
-
-assert.strictEqual(server.serverBusy, false);
-server.serverBusy = true;
diff --git a/test/parallel/test-quic-server-listening-event-error-async.js b/test/parallel/test-quic-server-listening-event-error-async.js
deleted file mode 100644
index f4c5440735..0000000000
--- a/test/parallel/test-quic-server-listening-event-error-async.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('session', common.mustNotCall());
-
-server.on('error', common.mustCall((error) => {
- assert.strictEqual(error.message, 'boom');
-}));
-
-server.on('ready', common.mustCall());
-
-server.on('listening', common.mustCall(async () => {
- throw new Error('boom');
-}));
-
-server.listen();
diff --git a/test/parallel/test-quic-server-listening-event-error.js b/test/parallel/test-quic-server-listening-event-error.js
deleted file mode 100644
index e91b4bb41c..0000000000
--- a/test/parallel/test-quic-server-listening-event-error.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('session', common.mustNotCall());
-
-server.on('error', common.mustCall((error) => {
- assert.strictEqual(error.message, 'boom');
-}));
-
-server.on('ready', common.mustCall());
-
-server.on('listening', common.mustCall(() => {
- throw new Error('boom');
-}));
-
-server.listen();
diff --git a/test/parallel/test-quic-server-ready-event-error-async.js b/test/parallel/test-quic-server-ready-event-error-async.js
deleted file mode 100644
index 4d42d4725d..0000000000
--- a/test/parallel/test-quic-server-ready-event-error-async.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('session', common.mustNotCall());
-
-server.listen();
-
-server.on('error', common.mustCall((error) => {
- assert.strictEqual(error.message, 'boom');
-}));
-
-server.on('ready', common.mustCall(async () => {
- throw new Error('boom');
-}));
diff --git a/test/parallel/test-quic-server-ready-event-error.js b/test/parallel/test-quic-server-ready-event-error.js
deleted file mode 100644
index df3e626530..0000000000
--- a/test/parallel/test-quic-server-ready-event-error.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('session', common.mustNotCall());
-
-server.listen();
-
-server.on('error', common.mustCall((error) => {
- assert.strictEqual(error.message, 'boom');
-}));
-
-server.on('ready', common.mustCall(() => {
- throw new Error('boom');
-}));
diff --git a/test/parallel/test-quic-server-session-event-error-async.js b/test/parallel/test-quic-server-session-event-error-async.js
deleted file mode 100644
index b5c039846c..0000000000
--- a/test/parallel/test-quic-server-session-event-error-async.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { once } = require('events');
-const { internalBinding } = require('internal/test/binding');
-const {
- constants: {
- NGTCP2_CONNECTION_REFUSED
- }
-} = internalBinding('quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- session.on('close', common.mustCall());
- session.on('error', common.mustCall((err) => {
- assert.strictEqual(err.message, 'boom');
- }));
- // Throwing inside the session event handler should cause
- // the session to be destroyed immediately. This should
- // cause the client side to be closed also.
- throw new Error('boom');
- }));
-
- server.on('sessionError', common.mustCall((err, session) => {
- assert.strictEqual(err.message, 'boom');
- assert(session.destroyed);
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('close', common.mustCall(() => {
- assert.strictEqual(req.closeCode.code, NGTCP2_CONNECTION_REFUSED);
- assert.strictEqual(req.closeCode.silent, true);
- server.close();
- client.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-server-session-event-error.js b/test/parallel/test-quic-server-session-event-error.js
deleted file mode 100644
index 09c9046a79..0000000000
--- a/test/parallel/test-quic-server-session-event-error.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { once } = require('events');
-const { internalBinding } = require('internal/test/binding');
-const {
- constants: {
- NGTCP2_CONNECTION_REFUSED
- }
-} = internalBinding('quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('close', common.mustCall());
- session.on('error', common.mustCall((err) => {
- assert.strictEqual(err.message, 'boom');
- }));
- // Throwing inside the session event handler should cause
- // the session to be destroyed immediately. This should
- // cause the client side to be closed also.
- throw new Error('boom');
- }));
-
- server.on('sessionError', common.mustCall((err, session) => {
- assert.strictEqual(err.message, 'boom');
- assert(session.destroyed);
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('close', common.mustCall(() => {
- assert.strictEqual(req.closeCode.code, NGTCP2_CONNECTION_REFUSED);
- assert.strictEqual(req.closeCode.silent, true);
- server.close();
- client.close();
- }));
-
- await Promise.all([
- once(server, 'close'),
- once(client, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-simple-client-migrate.js b/test/parallel/test-quic-simple-client-migrate.js
deleted file mode 100644
index 2aed15704a..0000000000
--- a/test/parallel/test-quic-simple-client-migrate.js
+++ /dev/null
@@ -1,96 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const { key, cert, ca } = require('../common/quic');
-
-const { once } = require('events');
-const { createQuicSocket } = require('net');
-const { pipeline } = require('stream');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-let req;
-const client = createQuicSocket({ client: options });
-const client2 = createQuicSocket({ client: options });
-const server = createQuicSocket({ server: options });
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('stream', common.mustCall(async (stream) => {
- pipeline(stream, stream, common.mustSucceed());
- (await session.openStream({ halfOpen: true }))
- .end('Hello from the server');
- }));
- }));
-
- await server.listen();
-
- req = await client.connect({
- address: common.localhostIPv4,
- port: server.endpoints[0].address.port,
- });
-
- req.on('close', () => {
- client2.close();
- server.close();
- });
-
- req.on('stream', common.mustCall((stream) => {
- let data = '';
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, 'Hello from the server');
- }));
- stream.on('close', common.mustCall());
- }));
-
- let data = '';
- const stream = await req.openStream();
- stream.setEncoding('utf8');
- stream.on('data', (chunk) => data += chunk);
- stream.on('end', common.mustCall(() => {
- assert.strictEqual(data, 'Hello from the client');
- }));
- stream.on('close', common.mustCall(() => {
- req.close();
- }));
- // Send some data on one connection...
- stream.write('Hello ');
-
- // Wait just a bit, then migrate to a different
- // QuicSocket and continue sending.
- setTimeout(common.mustCall(async () => {
- const s1 = req.socket;
- const a1 = req.socket.endpoints[0].address;
-
- await Promise.all([1, {}, 'test', false, null, undefined].map((i) => {
- return assert.rejects(req.setSocket(i), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
- await Promise.all([1, {}, 'test', null].map((i) => {
- return assert.rejects(req.setSocket(req.socket, i), {
- code: 'ERR_INVALID_ARG_TYPE'
- });
- }));
-
- await req.setSocket(client2);
-
- // Verify that it is using a different network endpoint
- assert.notStrictEqual(s1, req.socket);
- assert.notDeepStrictEqual(a1, req.socket.endpoints[0].address);
- client.close();
- stream.end('from the client');
- }), common.platformTimeout(100));
-
- await Promise.all([
- once(server, 'close'),
- once(client2, 'close')
- ]);
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-simple-server-bidi.js b/test/parallel/test-quic-simple-server-bidi.js
deleted file mode 100644
index 0b12a9d545..0000000000
--- a/test/parallel/test-quic-simple-server-bidi.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { key, cert, ca } = require('../common/quic');
-
-const { createWriteStream } = require('fs');
-const { createQuicSocket } = require('net');
-const { strictEqual } = require('assert');
-
-const qlog = process.env.NODE_QLOG === '1';
-
-const options = { key, cert, ca, alpn: 'zzz', qlog };
-
-const client = createQuicSocket({ qlog, client: options });
-const server = createQuicSocket({ qlog, server: options });
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- if (qlog) session.qlog.pipe(createWriteStream('server.qlog'));
- const stream = await session.openStream();
- stream.resume();
- stream.write('from the ');
- setTimeout(() => stream.end('server'), common.platformTimeout(10));
-
- session.on('close', common.mustCall(() => {
- server.close();
- }));
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
- if (qlog) req.qlog.pipe(createWriteStream('client.qlog'));
-
- req.on('stream', common.mustCall(async (stream) => {
- let data = '';
- stream.setEncoding('utf8');
-
- stream.end('foo');
-
- for await (const chunk of stream)
- data += chunk;
- strictEqual(data, 'from the server');
-
- await req.close();
- client.close();
- }));
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-simple-server-uni.js b/test/parallel/test-quic-simple-server-uni.js
deleted file mode 100644
index 19498f0f34..0000000000
--- a/test/parallel/test-quic-simple-server-uni.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { key, cert, ca } = require('../common/quic');
-
-const { createWriteStream } = require('fs');
-const { createQuicSocket } = require('net');
-const { strictEqual } = require('assert');
-
-const qlog = process.env.NODE_QLOG === '1';
-
-const options = { key, cert, ca, alpn: 'zzz', qlog };
-
-const client = createQuicSocket({ qlog, client: options });
-const server = createQuicSocket({ qlog, server: options });
-
-server.on('close', common.mustCall());
-client.on('close', common.mustCall());
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- if (qlog) session.qlog.pipe(createWriteStream('server.qlog'));
- const stream = await session.openStream({ halfOpen: true });
- stream.write('from the ');
- setTimeout(() => stream.end('server'), common.platformTimeout(10));
- stream.on('close', common.mustCall());
- session.on('close', common.mustCall(() => {
- server.close();
- }));
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
- if (qlog) req.qlog.pipe(createWriteStream('client.qlog'));
-
- req.on('close', common.mustCall());
-
- req.on('stream', common.mustCall(async (stream) => {
- let data = '';
- stream.setEncoding('utf8');
- stream.on('close', common.mustCall());
-
- for await (const chunk of stream)
- data += chunk;
-
- strictEqual(data, 'from the server');
-
- await req.close();
-
- client.close();
- }));
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-socket-close-event-error-async.js b/test/parallel/test-quic-socket-close-event-error-async.js
deleted file mode 100644
index 3b4baf595a..0000000000
--- a/test/parallel/test-quic-socket-close-event-error-async.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('error', common.mustNotCall());
-
-server.on('close', common.mustCall(async () => {
- throw new Error('boom');
-}));
-
-process.on('uncaughtException', (error) => {
- assert.strictEqual(error.message, 'boom');
-});
-
-server.destroy();
diff --git a/test/parallel/test-quic-socket-close-event-error.js b/test/parallel/test-quic-socket-close-event-error.js
deleted file mode 100644
index 5160698518..0000000000
--- a/test/parallel/test-quic-socket-close-event-error.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Flags: --no-warnings
-'use strict';
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const assert = require('assert');
-const {
- key,
- cert,
- ca,
-} = require('../common/quic');
-
-const { createQuicSocket } = require('net');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const server = createQuicSocket({ server: options });
-
-server.on('error', common.mustNotCall());
-
-server.on('close', common.mustCall(() => {
- throw new Error('boom');
-}));
-
-process.on('uncaughtException', (error) => {
- assert.strictEqual(error.message, 'boom');
-});
-
-server.destroy();
diff --git a/test/parallel/test-quic-statelessreset.js b/test/parallel/test-quic-statelessreset.js
deleted file mode 100644
index 70fc8c0fd0..0000000000
--- a/test/parallel/test-quic-statelessreset.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-
-// Testing stateless reset
-
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { internalBinding } = require('internal/test/binding');
-const assert = require('assert');
-
-const { key, cert, ca } = require('../common/quic');
-
-const {
- kHandle,
-} = require('internal/stream_base_commons');
-const { silentCloseSession } = internalBinding('quic');
-
-const { createQuicSocket } = require('net');
-
-const kStatelessResetToken =
- Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex');
-
-const options = { key, cert, ca, alpn: 'zzz' };
-
-const client = createQuicSocket({ client: options });
-const server = createQuicSocket({
- statelessResetSecret: kStatelessResetToken,
- server: options
-});
-
-server.on('close', common.mustCall(() => {
- // Verify stats recording
- assert(server.statelessResetCount >= 1);
-}));
-
-(async function() {
- server.on('session', common.mustCall((session) => {
- session.on('stream', common.mustCall((stream) => {
- // silentCloseSession is an internal-only testing tool
- // that allows us to prematurely destroy a QuicSession
- // without the proper communication flow with the connected
- // peer. We call this to simulate a local crash that loses
- // state, which should trigger the server to send a
- // stateless reset token to the client.
- silentCloseSession(session[kHandle]);
- }));
-
- session.on('close', common.mustCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port,
- });
-
- req.on('close', common.mustCall(() => {
- assert.strictEqual(req.statelessReset, true);
- server.close();
- client.close();
- }));
-
- const stream = await req.openStream();
- stream.end('hello');
- stream.resume();
- stream.on('close', common.mustCall());
-
-})().then(common.mustCall());
diff --git a/test/parallel/test-quic-with-fake-udp.js b/test/parallel/test-quic-with-fake-udp.js
deleted file mode 100644
index 3baf4ec4a6..0000000000
--- a/test/parallel/test-quic-with-fake-udp.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// Flags: --expose-internals --no-warnings
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-// Tests that QUIC works properly when using a pair of mocked UDP ports.
-
-const { makeUDPPair } = require('../common/udppair');
-const assert = require('assert');
-const { createQuicSocket } = require('net');
-const { kUDPHandleForTesting } = require('internal/quic/core');
-
-const { key, cert, ca } = require('../common/quic');
-
-const options = { key, cert, ca, alpn: 'meow' };
-
-const { serverSide, clientSide } = makeUDPPair();
-
-const server = createQuicSocket({
- endpoint: { [kUDPHandleForTesting]: serverSide._handle },
- server: options
-});
-serverSide.afterBind();
-
-const client = createQuicSocket({
- endpoint: { [kUDPHandleForTesting]: clientSide._handle },
- client: options
-});
-clientSide.afterBind();
-
-(async function() {
- server.on('session', common.mustCall(async (session) => {
- session.on('close', common.mustNotCall());
- const stream = await session.openStream({ halfOpen: false });
- stream.end('Hi!');
- stream.on('data', common.mustNotCall());
- stream.on('finish', common.mustCall());
- stream.on('close', common.mustNotCall());
- stream.on('end', common.mustNotCall());
- }));
-
- await server.listen();
-
- const req = await client.connect({
- address: 'localhost',
- port: server.endpoints[0].address.port
- });
-
- req.on('stream', common.mustCall((stream) => {
- stream.on('data', common.mustCall((data) => {
- assert.strictEqual(data.toString(), 'Hi!');
- }));
-
- stream.on('end', common.mustCall());
- }));
-
- req.on('close', common.mustNotCall());
-
-})().then(common.mustCall());
diff --git a/test/pummel/test-heapdump-quic.js b/test/pummel/test-heapdump-quic.js
deleted file mode 100644
index a3e5f95166..0000000000
--- a/test/pummel/test-heapdump-quic.js
+++ /dev/null
@@ -1,152 +0,0 @@
-// Flags: --expose-internals
-'use strict';
-const common = require('../common');
-if (!common.hasQuic)
- common.skip('missing quic');
-
-const { createQuicSocket } = require('net');
-
-const { recordState } = require('../common/heap');
-const fixtures = require('../common/fixtures');
-const key = fixtures.readKey('agent1-key.pem', 'binary');
-const cert = fixtures.readKey('agent1-cert.pem', 'binary');
-const ca = fixtures.readKey('ca1-cert.pem', 'binary');
-
-{
- const state = recordState();
- state.validateSnapshotNodes('Node / QuicStream', []);
- state.validateSnapshotNodes('Node / QuicSession', []);
- state.validateSnapshotNodes('Node / QuicSocket', []);
-}
-
-const server = createQuicSocket({ port: 0, validateAddress: true });
-
-server.listen({
- key,
- cert,
- ca,
- rejectUnauthorized: false,
- maxCryptoBuffer: 4096,
- alpn: 'meow'
-});
-
-server.on('session', common.mustCall((session) => {
- session.on('secure', common.mustCall((servername, alpn, cipher) => {
- // eslint-disable-next-line no-unused-vars
- const stream = session.openStream({ halfOpen: false });
-
- const state = recordState();
-
- state.validateSnapshotNodes('Node / QuicSocket', [
- {
- children: [
- { node_name: 'QuicSocket', edge_name: 'wrapped' },
- { node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
- { node_name: 'Node / sessions', edge_name: 'sessions' },
- { node_name: 'Node / dcid_to_scid', edge_name: 'dcid_to_scid' },
- ]
- }
- ], { loose: true });
-
- state.validateSnapshotNodes('Node / QuicStream', [
- {
- children: [
- { node_name: 'QuicStream', edge_name: 'wrapped' },
- { node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
- { node_name: 'Node / QuicBuffer', edge_name: 'buffer' },
- { node_name: 'Node / HistogramBase', edge_name: 'data_rx_rate' },
- { node_name: 'Node / HistogramBase', edge_name: 'data_rx_size' },
- { node_name: 'Node / HistogramBase', edge_name: 'data_rx_ack' }
- ]
- }
- ], { loose: true });
-
- state.validateSnapshotNodes('Node / QuicBuffer', [
- {
- children: [
- { node_name: 'Node / length', edge_name: 'length' }
- ]
- }
- ], { loose: true });
-
- state.validateSnapshotNodes('Node / QuicSession', [
- {
- children: [
- { node_name: 'QuicServerSession', edge_name: 'wrapped' },
- { node_name: 'Node / QuicCryptoContext',
- edge_name: 'crypto_context' },
- { node_name: 'Node / HistogramBase', edge_name: 'crypto_rx_ack' },
- { node_name: 'Node / HistogramBase',
- edge_name: 'crypto_handshake_rate' },
- { node_name: 'Node / Timer', edge_name: 'retransmit' },
- { node_name: 'Node / Timer', edge_name: 'idle' },
- { node_name: 'Node / QuicBuffer', edge_name: 'sendbuf' },
- { node_name: 'Node / QuicBuffer', edge_name: 'txbuf' },
- { node_name: 'Float64Array', edge_name: 'recovery_stats_buffer' },
- { node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
- { node_name: 'Node / current_ngtcp2_memory',
- edge_name: 'current_ngtcp2_memory' },
- { node_name: 'Node / streams', edge_name: 'streams' },
- { node_name: 'Node / std::basic_string', edge_name: 'alpn' },
- { node_name: 'Node / std::basic_string', edge_name: 'hostname' },
- { node_name: 'Float64Array', edge_name: 'state' },
- ]
- },
- {
- children: [
- { node_name: 'QuicClientSession', edge_name: 'wrapped' },
- { node_name: 'Node / QuicCryptoContext',
- edge_name: 'crypto_context' },
- { node_name: 'Node / HistogramBase', edge_name: 'crypto_rx_ack' },
- { node_name: 'Node / HistogramBase',
- edge_name: 'crypto_handshake_rate' },
- { node_name: 'Node / Timer', edge_name: 'retransmit' },
- { node_name: 'Node / Timer', edge_name: 'idle' },
- { node_name: 'Node / QuicBuffer', edge_name: 'sendbuf' },
- { node_name: 'Node / QuicBuffer', edge_name: 'txbuf' },
- { node_name: 'Float64Array', edge_name: 'recovery_stats_buffer' },
- { node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
- { node_name: 'Node / current_ngtcp2_memory',
- edge_name: 'current_ngtcp2_memory' },
- { node_name: 'Node / streams', edge_name: 'streams' },
- { node_name: 'Node / std::basic_string', edge_name: 'alpn' },
- { node_name: 'Node / std::basic_string', edge_name: 'hostname' },
- { node_name: 'Float64Array', edge_name: 'state' },
- ]
- }
- ], { loose: true });
-
- state.validateSnapshotNodes('Node / QuicCryptoContext', [
- {
- children: [
- { node_name: 'Node / rx_secret', edge_name: 'rx_secret' },
- { node_name: 'Node / tx_secret', edge_name: 'tx_secret' },
- { node_name: 'Node / QuicBuffer', edge_name: 'initial_crypto' },
- { node_name: 'Node / QuicBuffer',
- edge_name: 'handshake_crypto' },
- { node_name: 'Node / QuicBuffer', edge_name: 'app_crypto' },
- ]
- }
- ], { loose: true });
-
- session.destroy();
- server.close();
- }));
-}));
-
-server.on('ready', common.mustCall(() => {
- const client = createQuicSocket({
- port: 0,
- client: {
- key,
- cert,
- ca,
- alpn: 'meow'
- }
- });
-
- client.connect({
- address: 'localhost',
- port: server.address.port
- }).on('close', common.mustCall(() => client.close()));
-}));
diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js
index f89b546344..e6464466aa 100644
--- a/test/sequential/test-async-wrap-getasyncid.js
+++ b/test/sequential/test-async-wrap-getasyncid.js
@@ -46,12 +46,6 @@ const { getSystemErrorName } = require('util');
delete providers.MESSAGEPORT;
delete providers.WORKER;
// TODO(danbev): Test for these
- delete providers.QUICCLIENTSESSION;
- delete providers.QUICSERVERSESSION;
- delete providers.QUICSENDWRAP;
- delete providers.QUICSOCKET;
- delete providers.QUICSTREAM;
- delete providers.QLOGSTREAM;
delete providers.JSUDPWRAP;
if (!common.isMainThread)
delete providers.INSPECTORJSBINDING;
diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js
index 41e6086bf0..70a3fede3d 100644
--- a/tools/doc/type-parser.js
+++ b/tools/doc/type-parser.js
@@ -189,10 +189,6 @@ const customTypesMap = {
'perf_hooks.html#perf_hooks_class_perf_hooks_performanceobserver',
'PerformanceObserverEntryList':
'perf_hooks.html#perf_hooks_class_performanceobserverentrylist',
- 'QuicEndpoint': 'quic.html#quic_class_quicendpoint',
- 'QuicSession': 'quic.html#quic_class_quicserversession_extends_quicsession',
- 'QuicSocket': 'quic.html#quic_net_createquicsocket_options',
- 'QuicStream': 'quic.html#quic_class_quicstream_extends_stream_duplex',
'readline.Interface': 'readline.html#readline_class_interface',
diff --git a/tools/license-builder.sh b/tools/license-builder.sh
index 0f5fd6a155..d1d173943c 100755
--- a/tools/license-builder.sh
+++ b/tools/license-builder.sh
@@ -89,12 +89,6 @@ addlicense "gtest" "test/cctest/gtest" "$(cat "${rootdir}"/test/cctest/gtest/LIC
# nghttp2
addlicense "nghttp2" "deps/nghttp2" "$(cat "${rootdir}"/deps/nghttp2/COPYING)"
-# ngtcp2
-addlicense "ngtcp2" "deps/ngtcp2" "$(cat "${rootdir}"/deps/ngtcp2/COPYING)"
-
-# nghttp3
-addlicense "nghttp3" "deps/nghttp3" "$(cat "${rootdir}"/deps/nghttp3/COPYING)"
-
# node-inspect
addlicense "node-inspect" "deps/node-inspect" "$(cat "${rootdir}"/deps/node-inspect/LICENSE)"
diff --git a/vcbuild.bat b/vcbuild.bat
index 777842de20..369e8574be 100644
--- a/vcbuild.bat
+++ b/vcbuild.bat
@@ -70,7 +70,6 @@ set openssl_no_asm=
set doc=
set extra_msbuild_args=
set exit_code=0
-set experimental_quic=
:next-arg
if "%1"=="" goto args-done
@@ -145,7 +144,6 @@ if /i "%1"=="cctest" set cctest=1&goto arg-ok
if /i "%1"=="openssl-no-asm" set openssl_no_asm=1&goto arg-ok
if /i "%1"=="doc" set doc=1&goto arg-ok
if /i "%1"=="binlog" set extra_msbuild_args=/binaryLogger:%config%\node.binlog&goto arg-ok
-if /i "%1"=="experimental-quic" set experimental_quic=1&goto arg-ok
echo Error: invalid command line option `%1`.
exit /b 1
@@ -197,7 +195,6 @@ if defined config_flags set configure_flags=%configure_flags% %config_flags%
if defined target_arch set configure_flags=%configure_flags% --dest-cpu=%target_arch%
if defined openssl_no_asm set configure_flags=%configure_flags% --openssl-no-asm
if defined DEBUG_HELPER set configure_flags=%configure_flags% --verbose
-if defined experimental_quic set configure_flags=%configure_flags% --experimental-quic
if "%target_arch%"=="x86" if "%PROCESSOR_ARCHITECTURE%"=="AMD64" set configure_flags=%configure_flags% --no-cross-compiling
if "%target_arch%"=="arm64" set configure_flags=%configure_flags% --cross-compiling
@@ -688,7 +685,7 @@ set exit_code=1
goto exit
:help
-echo vcbuild.bat [debug/release] [msi] [doc] [test/test-all/test-addons/test-doc/test-js-native-api/test-node-api/test-benchmark/test-internet/test-pummel/test-simple/test-message/test-tick-processor/test-known-issues/test-node-inspect/test-check-deopts/test-npm/test-async-hooks/test-v8/test-v8-intl/test-v8-benchmarks/test-v8-all] [ignore-flaky] [static/dll] [noprojgen] [projgen] [small-icu/full-icu/without-intl] [nobuild] [nosnapshot] [noetw] [ltcg] [licensetf] [sign] [ia32/x86/x64/arm64] [vs2019] [download-all] [lint/lint-ci/lint-js/lint-md] [lint-md-build] [package] [build-release] [upload] [no-NODE-OPTIONS] [link-module path-to-module] [debug-http2] [debug-nghttp2] [clean] [cctest] [no-cctest] [openssl-no-asm] [experimental-quic]
+echo vcbuild.bat [debug/release] [msi] [doc] [test/test-all/test-addons/test-doc/test-js-native-api/test-node-api/test-benchmark/test-internet/test-pummel/test-simple/test-message/test-tick-processor/test-known-issues/test-node-inspect/test-check-deopts/test-npm/test-async-hooks/test-v8/test-v8-intl/test-v8-benchmarks/test-v8-all] [ignore-flaky] [static/dll] [noprojgen] [projgen] [small-icu/full-icu/without-intl] [nobuild] [nosnapshot] [noetw] [ltcg] [licensetf] [sign] [ia32/x86/x64/arm64] [vs2019] [download-all] [lint/lint-ci/lint-js/lint-md] [lint-md-build] [package] [build-release] [upload] [no-NODE-OPTIONS] [link-module path-to-module] [debug-http2] [debug-nghttp2] [clean] [cctest] [no-cctest] [openssl-no-asm]
echo Examples:
echo vcbuild.bat : builds release build
echo vcbuild.bat debug : builds debug build