diff options
| author | robot-contrib <[email protected]> | 2025-08-09 11:36:14 +0300 |
|---|---|---|
| committer | robot-contrib <[email protected]> | 2025-08-09 11:50:03 +0300 |
| commit | 98d3ec2e2be2fcfc4f304e8a1a7b879356e5cb5f (patch) | |
| tree | 6672396d292ef0ffbb77cae0f4759a3ff5a9b877 | |
| parent | 691348ad0a004b8664491555bd69989aa395bd66 (diff) | |
Update contrib/libs/nghttp3 to 1.11.0
commit_hash:9c9ca139032e946c3460b9abd351c29356354e2d
26 files changed, 1010 insertions, 217 deletions
diff --git a/contrib/libs/nghttp3/.yandex_meta/devtools.copyrights.report b/contrib/libs/nghttp3/.yandex_meta/devtools.copyrights.report index e0698d2f92c..c4c927bdb5b 100644 --- a/contrib/libs/nghttp3/.yandex_meta/devtools.copyrights.report +++ b/contrib/libs/nghttp3/.yandex_meta/devtools.copyrights.report @@ -229,7 +229,7 @@ BELONGS ya.make Match type : COPYRIGHT Files with this license: COPYING [3:3] - README.rst [73:73] + README.rst [75:75] lib/includes/nghttp3/version.h [4:5] lib/nghttp3_buf.c [4:5] lib/nghttp3_buf.h [4:5] @@ -346,3 +346,17 @@ BELONGS ya.make Files with this license: lib/nghttp3_mem.c [4:6] lib/nghttp3_mem.h [4:6] + +KEEP COPYRIGHT_SERVICE_LABEL e1da7d27cd25ca9798a246568e386a9c +BELONGS ya.make + License text: + * Copyright (c) 2025 nghttp3 contributors + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + lib/nghttp3_callbacks.c [4:4] + lib/nghttp3_callbacks.h [4:4] + lib/nghttp3_settings.c [4:4] + lib/nghttp3_settings.h [4:4] diff --git a/contrib/libs/nghttp3/.yandex_meta/devtools.licenses.report b/contrib/libs/nghttp3/.yandex_meta/devtools.licenses.report index 2bdd81ce7ad..6944e1b8260 100644 --- a/contrib/libs/nghttp3/.yandex_meta/devtools.licenses.report +++ b/contrib/libs/nghttp3/.yandex_meta/devtools.licenses.report @@ -71,11 +71,11 @@ BELONGS ya.make Match type : NOTICE Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT Files with this license: - README.rst [68:71] + README.rst [70:73] KEEP MIT a3a8f7feced3937b87cd090ba748e24b BELONGS ya.make -FILE_INCLUDE AUTHORS found in files: lib/includes/nghttp3/nghttp3.h at line 22, lib/includes/nghttp3/version.h at line 21, lib/nghttp3_balloc.c at line 21, lib/nghttp3_balloc.h at line 21, lib/nghttp3_buf.c at line 21, lib/nghttp3_buf.h at line 21, lib/nghttp3_conn.c at line 20, lib/nghttp3_conn.h at line 20, lib/nghttp3_conv.c at line 21, lib/nghttp3_conv.h at line 21, lib/nghttp3_debug.c at line 21, lib/nghttp3_debug.h at line 21, lib/nghttp3_err.c at line 20, lib/nghttp3_err.h at line 20, lib/nghttp3_frame.c at line 21, lib/nghttp3_frame.h at line 21, lib/nghttp3_gaptr.c at line 21, lib/nghttp3_gaptr.h at line 21, lib/nghttp3_http.c at line 21, lib/nghttp3_http.h at line 21, lib/nghttp3_idtr.c at line 21, lib/nghttp3_idtr.h at line 21, lib/nghttp3_ksl.c at line 21, lib/nghttp3_ksl.h at line 21, lib/nghttp3_macro.h at line 21, lib/nghttp3_map.c at line 22, lib/nghttp3_map.h at line 22, lib/nghttp3_mem.c at line 22, lib/nghttp3_mem.h at line 22, lib/nghttp3_objalloc.c at line 21, lib/nghttp3_objalloc.h at line 21, lib/nghttp3_opl.c at line 21, lib/nghttp3_opl.h at line 21, lib/nghttp3_pq.c at line 22, lib/nghttp3_pq.h at line 22, lib/nghttp3_qpack.c at line 21, lib/nghttp3_qpack.h at line 21, lib/nghttp3_qpack_huffman.c at line 21, lib/nghttp3_qpack_huffman.h at line 21, lib/nghttp3_qpack_huffman_data.c at line 21, lib/nghttp3_range.c at line 21, lib/nghttp3_range.h at line 21, lib/nghttp3_rcbuf.c at line 21, lib/nghttp3_rcbuf.h at line 21, lib/nghttp3_ringbuf.c at line 21, lib/nghttp3_ringbuf.h at line 21, lib/nghttp3_str.c at line 22, lib/nghttp3_str.h at line 22, lib/nghttp3_stream.c at line 20, lib/nghttp3_stream.h at line 20, lib/nghttp3_tnode.c at line 20, lib/nghttp3_tnode.h at line 20, lib/nghttp3_unreachable.c at line 21, lib/nghttp3_unreachable.h at line 21, lib/nghttp3_vec.c at line 21, lib/nghttp3_vec.h at line 21, lib/nghttp3_version.c at line 20, lib/sfparse/sfparse.c at line 22, lib/sfparse/sfparse.h at line 22 +FILE_INCLUDE AUTHORS found in files: lib/includes/nghttp3/nghttp3.h at line 22, lib/includes/nghttp3/version.h at line 21, lib/nghttp3_balloc.c at line 21, lib/nghttp3_balloc.h at line 21, lib/nghttp3_buf.c at line 21, lib/nghttp3_buf.h at line 21, lib/nghttp3_callbacks.c at line 20, lib/nghttp3_callbacks.h at line 20, lib/nghttp3_conn.c at line 20, lib/nghttp3_conn.h at line 20, lib/nghttp3_conv.c at line 21, lib/nghttp3_conv.h at line 21, lib/nghttp3_debug.c at line 21, lib/nghttp3_debug.h at line 21, lib/nghttp3_err.c at line 20, lib/nghttp3_err.h at line 20, lib/nghttp3_frame.c at line 21, lib/nghttp3_frame.h at line 21, lib/nghttp3_gaptr.c at line 21, lib/nghttp3_gaptr.h at line 21, lib/nghttp3_http.c at line 21, lib/nghttp3_http.h at line 21, lib/nghttp3_idtr.c at line 21, lib/nghttp3_idtr.h at line 21, lib/nghttp3_ksl.c at line 21, lib/nghttp3_ksl.h at line 21, lib/nghttp3_macro.h at line 21, lib/nghttp3_map.c at line 22, lib/nghttp3_map.h at line 22, lib/nghttp3_mem.c at line 22, lib/nghttp3_mem.h at line 22, lib/nghttp3_objalloc.c at line 21, lib/nghttp3_objalloc.h at line 21, lib/nghttp3_opl.c at line 21, lib/nghttp3_opl.h at line 21, lib/nghttp3_pq.c at line 22, lib/nghttp3_pq.h at line 22, lib/nghttp3_qpack.c at line 21, lib/nghttp3_qpack.h at line 21, lib/nghttp3_qpack_huffman.c at line 21, lib/nghttp3_qpack_huffman.h at line 21, lib/nghttp3_qpack_huffman_data.c at line 21, lib/nghttp3_range.c at line 21, lib/nghttp3_range.h at line 21, lib/nghttp3_rcbuf.c at line 21, lib/nghttp3_rcbuf.h at line 21, lib/nghttp3_ringbuf.c at line 21, lib/nghttp3_ringbuf.h at line 21, lib/nghttp3_settings.c at line 20, lib/nghttp3_settings.h at line 20, lib/nghttp3_str.c at line 22, lib/nghttp3_str.h at line 22, lib/nghttp3_stream.c at line 20, lib/nghttp3_stream.h at line 20, lib/nghttp3_tnode.c at line 20, lib/nghttp3_tnode.h at line 20, lib/nghttp3_unreachable.c at line 21, lib/nghttp3_unreachable.h at line 21, lib/nghttp3_vec.c at line 21, lib/nghttp3_vec.h at line 21, lib/nghttp3_version.c at line 20, lib/sfparse/sfparse.c at line 22, lib/sfparse/sfparse.h at line 22 Note: matched license text is too long. Read it in the source files. Scancode info: Original SPDX id: MIT @@ -89,6 +89,8 @@ FILE_INCLUDE AUTHORS found in files: lib/includes/nghttp3/nghttp3.h at line 22, lib/nghttp3_balloc.h [7:24] lib/nghttp3_buf.c [7:24] lib/nghttp3_buf.h [7:24] + lib/nghttp3_callbacks.c [6:23] + lib/nghttp3_callbacks.h [6:23] lib/nghttp3_conn.c [6:23] lib/nghttp3_conn.h [6:23] lib/nghttp3_conv.c [7:24] @@ -129,6 +131,8 @@ FILE_INCLUDE AUTHORS found in files: lib/includes/nghttp3/nghttp3.h at line 22, lib/nghttp3_rcbuf.h [7:24] lib/nghttp3_ringbuf.c [7:24] lib/nghttp3_ringbuf.h [7:24] + lib/nghttp3_settings.c [6:23] + lib/nghttp3_settings.h [6:23] lib/nghttp3_str.c [8:25] lib/nghttp3_str.h [8:25] lib/nghttp3_stream.c [6:23] diff --git a/contrib/libs/nghttp3/.yandex_meta/licenses.list.txt b/contrib/libs/nghttp3/.yandex_meta/licenses.list.txt index 4d518d5a5f5..bcc82d59efc 100644 --- a/contrib/libs/nghttp3/.yandex_meta/licenses.list.txt +++ b/contrib/libs/nghttp3/.yandex_meta/licenses.list.txt @@ -61,6 +61,10 @@ Software Foundation, Inc. ====================COPYRIGHT==================== + * Copyright (c) 2025 nghttp3 contributors + + +====================COPYRIGHT==================== /* Copyright (c) 2008-2010 Bjoern Hoehrmann <[email protected]> * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. diff --git a/contrib/libs/nghttp3/.yandex_meta/override.nix b/contrib/libs/nghttp3/.yandex_meta/override.nix index 92cea24a4dd..b3aba598120 100644 --- a/contrib/libs/nghttp3/.yandex_meta/override.nix +++ b/contrib/libs/nghttp3/.yandex_meta/override.nix @@ -1,6 +1,6 @@ pkgs: attrs: with pkgs; with attrs; rec { pname = "nghttp3"; - version = "1.10.1"; + version = "1.11.0"; nativeBuildInputs = [ cmake pkg-config autoconf libtool automake @@ -10,6 +10,6 @@ pkgs: attrs: with pkgs; with attrs; rec { src = fetchurl { url = "https://github.com/ngtcp2/nghttp3/releases/download/v${version}/nghttp3-${version}.tar.xz"; - hash = "sha256-5rjrqt+OV8unej407o3kZf6VJIH793xPmNSHN731DgM="; + hash = "sha256-J9CEUY8G14J5sFDMnN/yQY+A+3U9oBlCfOhTzskg8z8="; }; } diff --git a/contrib/libs/nghttp3/README.rst b/contrib/libs/nghttp3/README.rst index 950c7c59f72..8c0e29eb78a 100644 --- a/contrib/libs/nghttp3/README.rst +++ b/contrib/libs/nghttp3/README.rst @@ -38,6 +38,8 @@ The following extensions have been implemented: <https://datatracker.ietf.org/doc/html/rfc9218>`_ - `Bootstrapping WebSockets with HTTP/3 <https://datatracker.ietf.org/doc/html/rfc9220>`_ +- `The ORIGIN Extension in HTTP/3 + <https://datatracker.ietf.org/doc/html/rfc9412>`_ It can also send and receive `SETTINGS_H3_DATAGRAM` from `HTTP Datagrams and the Capsule Protocol diff --git a/contrib/libs/nghttp3/lib/includes/nghttp3/nghttp3.h b/contrib/libs/nghttp3/lib/includes/nghttp3/nghttp3.h index addbceb701c..cb4625eaa1b 100644 --- a/contrib/libs/nghttp3/lib/includes/nghttp3/nghttp3.h +++ b/contrib/libs/nghttp3/lib/includes/nghttp3/nghttp3.h @@ -1116,6 +1116,10 @@ typedef struct nghttp3_qpack_encoder nghttp3_qpack_encoder; * * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. + * + * See also `nghttp3_qpack_encoder_new2`. This function calls + * `nghttp3_qpack_encoder_new2` with the given parameters and 0 as + * seed. */ NGHTTP3_EXTERN int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, size_t hard_max_dtable_capacity, @@ -1124,6 +1128,34 @@ NGHTTP3_EXTERN int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, /** * @function * + * `nghttp3_qpack_encoder_new2` initializes QPACK encoder. |pencoder| + * must be non-NULL pointer. |hard_max_dtable_capacity| is the upper + * bound of the dynamic table capacity. |seed| must be unpredictable + * value, and is used to seed the internal data structure. |mem| is a + * memory allocator. This function allocates memory for + * :type:`nghttp3_qpack_encoder` itself, and assigns its pointer to + * |*pencoder| if it succeeds. + * + * The maximum dynamic table capacity is still 0. In order to change + * the maximum dynamic table capacity, call + * `nghttp3_qpack_encoder_set_max_dtable_capacity`. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :macro:`NGHTTP3_ERR_NOMEM` + * Out of memory. + * + * This function is available since v1.11.0. + */ +NGHTTP3_EXTERN int nghttp3_qpack_encoder_new2(nghttp3_qpack_encoder **pencoder, + size_t hard_max_dtable_capacity, + uint64_t seed, + const nghttp3_mem *mem); + +/** + * @function + * * `nghttp3_qpack_encoder_del` frees memory allocated for |encoder|. * This function also frees memory pointed by |encoder| itself. This * function does nothing if |encoder| is NULL. @@ -1605,7 +1637,8 @@ NGHTTP3_EXTERN void nghttp3_set_debug_vprintf_callback( typedef struct nghttp3_conn nghttp3_conn; #define NGHTTP3_SETTINGS_V1 1 -#define NGHTTP3_SETTINGS_VERSION NGHTTP3_SETTINGS_V1 +#define NGHTTP3_SETTINGS_V2 2 +#define NGHTTP3_SETTINGS_VERSION NGHTTP3_SETTINGS_V2 /** * @struct @@ -1652,6 +1685,21 @@ typedef struct nghttp3_settings { * Datagrams (see :rfc:`9297`). */ uint8_t h3_datagram; + /* The following fields have been added since NGHTTP3_SETTINGS_V2. */ + /** + * :member:`origin_list`, if set, must contain a serialized HTTP/3 + * ORIGIN frame (see :rfc:`9412`) payload. The ORIGIN frame payload + * is a sequence of zero or more of a length prefixed byte string. + * The length is encoded in 2 bytes in network byte order. If + * :member:`origin_list->len <nghttp3_vec.len>` is zero, an empty + * ORIGIN frame is sent. An application must keep the buffer + * pointed by :member:`origin_list->base <nghttp3_vec.base>` alive + * until the :type:`nghttp3_conn` to which this field was passed is + * freed by `nghttp3_conn_del`. The object pointed to by this field + * is copied internally, and does not need to be kept alive. Only + * server uses this field. This field is available since v1.11.0. + */ + const nghttp3_vec *origin_list; } nghttp3_settings; /** @@ -1891,8 +1939,47 @@ typedef int (*nghttp3_recv_settings)(nghttp3_conn *conn, const nghttp3_settings *settings, void *conn_user_data); +/** + * @functypedef + * + * :type:`nghttp3_recv_origin` is a callback function which is invoked + * when a single origin in ORIGIN frame is received. |origin| is a + * received origin of length |originlen|. |originlen| never be 0. + * + * The implementation of this callback must return 0 if it succeeds. + * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the + * caller immediately. Any values other than 0 is treated as + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE`. + */ +typedef int (*nghttp3_recv_origin)(nghttp3_conn *conn, const uint8_t *origin, + size_t originlen, void *conn_user_data); + +/** + * @functypedef + * + * :type:`nghttp3_end_origin` is a callback function which is invoked + * when an ORIGIN frame has been completely processed. + * + * The implementation of this callback must return 0 if it succeeds. + * Returning :macro:`NGHTTP3_ERR_CALLBACK_FAILURE` will return to the + * caller immediately. Any values other than 0 is treated as + * :macro:`NGHTTP3_ERR_CALLBACK_FAILURE`. + */ +typedef int (*nghttp3_end_origin)(nghttp3_conn *conn, void *conn_user_data); + +/** + * @functypedef + * + * :type:`nghttp3_rand` is a callback function which is invoked when + * unpredictable data of |destlen| bytes are needed. The + * implementation must write unpredictable data of |destlen| bytes + * into the buffer pointed by |dest|. + */ +typedef void (*nghttp3_rand)(uint8_t *dest, size_t destlen); + #define NGHTTP3_CALLBACKS_V1 1 -#define NGHTTP3_CALLBACKS_VERSION NGHTTP3_CALLBACKS_V1 +#define NGHTTP3_CALLBACKS_V2 2 +#define NGHTTP3_CALLBACKS_VERSION NGHTTP3_CALLBACKS_V2 /** * @struct @@ -1986,6 +2073,28 @@ typedef struct nghttp3_callbacks { * when SETTINGS frame is received. */ nghttp3_recv_settings recv_settings; + /* The following fields have been added since NGHTTP3_CALLBACKS_V2. */ + /** + * :member:`recv_origin` is a callback function which is invoked + * when a single origin in an ORIGIN frame is received. This field + * is available since v1.11.0. + */ + nghttp3_recv_origin recv_origin; + /** + * :member:`end_origin` is a callback function which is invoked when + * an ORIGIN frame has been completely processed. This field is + * available since v1.11.0. + */ + nghttp3_end_origin end_origin; + /** + * :member:`rand` is a callback function which is invoked when + * unpredictable data are needed. Although this field is optional + * due to the backward compatibility, it is recommended to specify + * this field to harden the runtime behavior against suspicious + * activities of a remote endpoint. This field is available since + * v1.11.0. + */ + nghttp3_rand rand; } nghttp3_callbacks; /** diff --git a/contrib/libs/nghttp3/lib/includes/nghttp3/version.h b/contrib/libs/nghttp3/lib/includes/nghttp3/version.h index 4061c155876..bd442b8be63 100644 --- a/contrib/libs/nghttp3/lib/includes/nghttp3/version.h +++ b/contrib/libs/nghttp3/lib/includes/nghttp3/version.h @@ -31,7 +31,7 @@ * * Version number of the nghttp3 library release. */ -#define NGHTTP3_VERSION "1.10.1" +#define NGHTTP3_VERSION "1.11.0" /** * @macro @@ -41,6 +41,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGHTTP3_VERSION_NUM 0x010a01 +#define NGHTTP3_VERSION_NUM 0x010b00 #endif /* !defined(NGHTTP3_VERSION_H) */ diff --git a/contrib/libs/nghttp3/lib/nghttp3_buf.h b/contrib/libs/nghttp3/lib/nghttp3_buf.h index c7abd0d3af7..abc59b92a97 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_buf.h +++ b/contrib/libs/nghttp3/lib/nghttp3_buf.h @@ -63,8 +63,12 @@ typedef enum nghttp3_buf_type { memory. */ NGHTTP3_BUF_TYPE_SHARED, /* NGHTTP3_BUF_TYPE_ALIEN indicates that the buffer points to a - memory which comes from outside of the library. */ + memory which comes from outside of the library. When + acknowledged, acked_data callback is called. */ NGHTTP3_BUF_TYPE_ALIEN, + /* NGHTTP3_BUF_TYPE_ALIEN_NO_ACK is like NGHTTP3_BUF_TYPE_ALIEN, but + acked_data callback is not called. */ + NGHTTP3_BUF_TYPE_ALIEN_NO_ACK, } nghttp3_buf_type; typedef struct nghttp3_typed_buf { diff --git a/contrib/libs/nghttp3/lib/nghttp3_callbacks.c b/contrib/libs/nghttp3/lib/nghttp3_callbacks.c new file mode 100644 index 00000000000..5db8376ad22 --- /dev/null +++ b/contrib/libs/nghttp3/lib/nghttp3_callbacks.c @@ -0,0 +1,75 @@ +/* + * nghttp3 + * + * Copyright (c) 2025 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_callbacks.h" + +#include <string.h> +#include <assert.h> + +#include "nghttp3_unreachable.h" + +static void callbacks_copy(nghttp3_callbacks *dest, + const nghttp3_callbacks *src, + int callbacks_version) { + assert(callbacks_version != NGHTTP3_CALLBACKS_VERSION); + + memcpy(dest, src, nghttp3_callbackslen_version(callbacks_version)); +} + +const nghttp3_callbacks * +nghttp3_callbacks_convert_to_latest(nghttp3_callbacks *dest, + int callbacks_version, + const nghttp3_callbacks *src) { + if (callbacks_version == NGHTTP3_CALLBACKS_VERSION) { + return src; + } + + memset(dest, 0, sizeof(*dest)); + + callbacks_copy(dest, src, callbacks_version); + + return dest; +} + +void nghttp3_callbacks_convert_to_old(int callbacks_version, + nghttp3_callbacks *dest, + const nghttp3_callbacks *src) { + assert(callbacks_version != NGHTTP3_CALLBACKS_VERSION); + + callbacks_copy(dest, src, callbacks_version); +} + +size_t nghttp3_callbackslen_version(int callbacks_version) { + nghttp3_callbacks callbacks; + + switch (callbacks_version) { + case NGHTTP3_CALLBACKS_VERSION: + return sizeof(callbacks); + case NGHTTP3_CALLBACKS_V1: + return offsetof(nghttp3_callbacks, recv_settings) + + sizeof(callbacks.recv_settings); + default: + nghttp3_unreachable(); + } +} diff --git a/contrib/libs/nghttp3/lib/nghttp3_callbacks.h b/contrib/libs/nghttp3/lib/nghttp3_callbacks.h new file mode 100644 index 00000000000..6bebb3a98dd --- /dev/null +++ b/contrib/libs/nghttp3/lib/nghttp3_callbacks.h @@ -0,0 +1,74 @@ +/* + * nghttp3 + * + * Copyright (c) 2025 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_CALLBACKS_H +#define NGHTTP3_CALLBACKS_H + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* defined(HAVE_CONFIG_H) */ + +#include <nghttp3/nghttp3.h> + +/* + * nghttp3_callbacks_convert_to_latest converts |src| of version + * |callbacks_version| to the latest version + * NGHTTP3_CALLBACKS_VERSION. + * + * |dest| must point to the latest version. |src| may be the older + * version, and if so, it may have fewer fields. Accessing those + * fields causes undefined behavior. + * + * If |callbacks_version| == NGHTTP3_CALLBACKS_VERSION, no conversion + * is made, and |src| is returned. Otherwise, first |dest| is + * zero-initialized, and then all valid fields in |src| are copied + * into |dest|. Finally, |dest| is returned. + */ +const nghttp3_callbacks *nghttp3_callbacks_convert_to_latest( + nghttp3_callbacks *dest, int callbacks_version, const nghttp3_callbacks *src); + +/* + * nghttp3_callbacks_convert_to_old converts |src| of the latest + * version to |dest| of version |callbacks_version|. + * + * |callbacks_version| must not be the latest version + * NGHTTP3_CALLBACKS_VERSION. + * + * |dest| points to the older version, and it may have fewer fields. + * Accessing those fields causes undefined behavior. + * + * This function copies all valid fields in version + * |callbacks_version| from |src| to |dest|. + */ +void nghttp3_callbacks_convert_to_old(int callbacks_version, + nghttp3_callbacks *dest, + const nghttp3_callbacks *src); + +/* + * nghttp3_callbackslen_version returns the effective length of + * nghttp3_callbacks at the version |callbacks_version|. + */ +size_t nghttp3_callbackslen_version(int callbacks_version); + +#endif /* !defined(NGHTTP3_CALLBACKS_H) */ diff --git a/contrib/libs/nghttp3/lib/nghttp3_conn.c b/contrib/libs/nghttp3/lib/nghttp3_conn.c index 1eec936a895..8c0e94dc768 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_conn.c +++ b/contrib/libs/nghttp3/lib/nghttp3_conn.c @@ -34,10 +34,8 @@ #include "nghttp3_conv.h" #include "nghttp3_http.h" #include "nghttp3_unreachable.h" - -/* NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY is the upper bound of the - dynamic table capacity that QPACK encoder is willing to use. */ -#define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096 +#include "nghttp3_settings.h" +#include "nghttp3_callbacks.h" nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent) @@ -207,6 +205,32 @@ static int conn_call_recv_settings(nghttp3_conn *conn) { return 0; } +static int conn_call_recv_origin(nghttp3_conn *conn, const uint8_t *origin, + size_t originlen) { + if (!conn->callbacks.recv_origin) { + return 0; + } + + if (conn->callbacks.recv_origin(conn, origin, originlen, conn->user_data) != + 0) { + return NGHTTP3_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int conn_call_end_origin(nghttp3_conn *conn) { + if (!conn->callbacks.end_origin) { + return 0; + } + + if (conn->callbacks.end_origin(conn, conn->user_data) != 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 = @@ -234,9 +258,16 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version, const nghttp3_settings *settings, const nghttp3_mem *mem, void *user_data) { nghttp3_conn *conn; + nghttp3_settings settings_latest; + nghttp3_callbacks callbacks_latest; + uint64_t map_seed; size_t i; (void)callbacks_version; - (void)settings_version; + + settings = nghttp3_settings_convert_to_latest(&settings_latest, + settings_version, settings); + callbacks = nghttp3_callbacks_convert_to_latest(&callbacks_latest, + callbacks_version, callbacks); assert(settings->max_field_section_size <= NGHTTP3_VARINT_MAX); assert(settings->qpack_max_dtable_capacity <= NGHTTP3_VARINT_MAX); @@ -256,13 +287,19 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version, NGHTTP3_STREAM_MIN_CHUNK_SIZE * 16, mem); nghttp3_objalloc_stream_init(&conn->stream_objalloc, 8, mem); - nghttp3_map_init(&conn->streams, mem); + if (callbacks->rand) { + callbacks->rand((uint8_t *)&map_seed, sizeof(map_seed)); + } else { + map_seed = 0; + } + + nghttp3_map_init(&conn->streams, map_seed, mem); nghttp3_qpack_decoder_init(&conn->qdec, settings->qpack_max_dtable_capacity, settings->qpack_blocked_streams, mem); - nghttp3_qpack_encoder_init(&conn->qenc, - settings->qpack_encoder_max_dtable_capacity, mem); + nghttp3_qpack_encoder_init( + &conn->qenc, settings->qpack_encoder_max_dtable_capacity, ++map_seed, mem); nghttp3_pq_init(&conn->qpack_blocked_streams, ricnt_less, mem); @@ -274,8 +311,14 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version, conn->callbacks = *callbacks; conn->local.settings = *settings; - if (!server) { + if (server) { + if (settings->origin_list) { + conn->local.settings.origin_list = &conn->local.origin_list; + conn->local.origin_list = *settings->origin_list; + } + } else { conn->local.settings.enable_connect_protocol = 0; + conn->local.settings.origin_list = NULL; } nghttp3_settings_default(&conn->remote.settings); conn->mem = mem; @@ -361,6 +404,8 @@ void nghttp3_conn_del(nghttp3_conn *conn) { nghttp3_objalloc_free(&conn->stream_objalloc); nghttp3_objalloc_free(&conn->out_chunk_objalloc); + nghttp3_mem_free(conn->mem, conn->rx.originbuf); + nghttp3_mem_free(conn->mem, conn); } @@ -621,6 +666,11 @@ nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream, return nread + nconsumed; } +static void conn_reset_rx_originlen(nghttp3_conn *conn) { + conn->rx.originlen_offset = 0; + conn->rx.originlen = 0; +} + static int frame_fin(nghttp3_stream_read_state *rstate, size_t len) { return (int64_t)len >= rstate->left; } @@ -657,7 +707,7 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, return (nghttp3_ssize)nconsumed; } - rstate->fr.hd.type = rvint->acc; + rstate->fr.type = rvint->acc; nghttp3_varint_read_state_reset(rvint); rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH; if (p == end) { @@ -677,19 +727,19 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, return (nghttp3_ssize)nconsumed; } - rstate->left = rstate->fr.hd.length = rvint->acc; + rstate->left = rvint->acc; nghttp3_varint_read_state_reset(rvint); if (!(conn->flags & NGHTTP3_CONN_FLAG_SETTINGS_RECVED)) { - if (rstate->fr.hd.type != NGHTTP3_FRAME_SETTINGS) { + if (rstate->fr.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) { + } else if (rstate->fr.type == NGHTTP3_FRAME_SETTINGS) { return NGHTTP3_ERR_H3_FRAME_UNEXPECTED; } - switch (rstate->fr.hd.type) { + switch (rstate->fr.type) { case NGHTTP3_FRAME_SETTINGS: /* SETTINGS frame might be empty. */ if (rstate->left == 0) { @@ -730,6 +780,31 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, case NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID: /* We do not support push */ return NGHTTP3_ERR_H3_ID_ERROR; + case NGHTTP3_FRAME_ORIGIN: + if (conn->server || + (!conn->callbacks.recv_origin && !conn->callbacks.end_origin)) { + busy = 1; + rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME; + break; + } + + /* ORIGIN frame might be empty */ + if (rstate->left == 0) { + rv = conn_call_end_origin(conn); + if (rv != 0) { + return rv; + } + + nghttp3_stream_read_state_reset(rstate); + + break; + } + + conn_reset_rx_originlen(conn); + + rstate->state = NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ORIGIN_LEN; + + break; case NGHTTP3_FRAME_CANCEL_PUSH: /* We do not support push */ case NGHTTP3_FRAME_DATA: case NGHTTP3_FRAME_HEADERS: @@ -967,6 +1042,8 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, break; } + conn->rx.pri_fieldbuflen = 0; + rstate->state = NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE; if (p == end) { @@ -1027,9 +1104,134 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, return rv; } - conn->rx.pri_fieldbuflen = 0; + nghttp3_stream_read_state_reset(rstate); + break; + case NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ORIGIN_LEN: + /* client side only */ + len = (size_t)nghttp3_min_int64(rstate->left, (int64_t)(end - p)); + + assert(len > 0); + + for (;;) { + nread = 0; + + for (; conn->rx.originlen_offset < sizeof(conn->rx.originlen) && + (size_t)nread < len; + ++conn->rx.originlen_offset, ++nread) { + conn->rx.originlen <<= 8; + conn->rx.originlen += *p++; + } + + nconsumed += (size_t)nread; + rstate->left -= nread; + len -= (size_t)nread; + + if (conn->rx.originlen_offset < sizeof(conn->rx.originlen)) { + /* Needs another byte to parse Origin-Len */ + if (rstate->left == 0) { + return NGHTTP3_ERR_H3_FRAME_ERROR; + } + + return (nghttp3_ssize)nconsumed; + } + + if (conn->rx.originlen == 0 || rstate->left < conn->rx.originlen) { + /* While this seems OK in very loose RFC, allowing this + sounds like an atack vector. */ + return NGHTTP3_ERR_H3_FRAME_ERROR; + } + + if (len < conn->rx.originlen) { + /* ASCII-Origin does not fit into this buffer. Needs + buffering. */ + if (conn->rx.originbuf == NULL) { + conn->rx.originbuf = nghttp3_mem_malloc(conn->mem, UINT16_MAX); + if (conn->rx.originbuf == NULL) { + return NGHTTP3_ERR_NOMEM; + } + } + + memcpy(conn->rx.originbuf, p, len); + + /* No need to update p because we will return very soon. */ + nconsumed += len; + rstate->left -= (int64_t)len; + + conn->rx.originbuflen = len; + + rstate->state = NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ASCII_ORIGIN; + + return (nghttp3_ssize)nconsumed; + } + + rv = conn_call_recv_origin(conn, p, conn->rx.originlen); + if (rv != 0) { + return rv; + } + + p += conn->rx.originlen; + nconsumed += conn->rx.originlen; + rstate->left -= conn->rx.originlen; + + if (rstate->left == 0) { + rv = conn_call_end_origin(conn); + if (rv != 0) { + return rv; + } + + nghttp3_stream_read_state_reset(rstate); + + break; + } + + len -= conn->rx.originlen; + + conn_reset_rx_originlen(conn); + + if (p == end) { + return (nghttp3_ssize)nconsumed; + } + } + + break; + case NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ASCII_ORIGIN: + /* client side only */ + len = nghttp3_min_size(conn->rx.originlen - conn->rx.originbuflen, + (size_t)(end - p)); + + assert(len > 0); + + memcpy(conn->rx.originbuf + conn->rx.originbuflen, p, len); + + conn->rx.originbuflen += len; + p += len; + nconsumed += len; + rstate->left -= (int64_t)len; + + if (conn->rx.originbuflen < conn->rx.originlen) { + return (nghttp3_ssize)nconsumed; + } + + rv = conn_call_recv_origin(conn, conn->rx.originbuf, conn->rx.originlen); + if (rv != 0) { + return rv; + } + + if (rstate->left) { + conn_reset_rx_originlen(conn); + + rstate->state = NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ORIGIN_LEN; + + break; + } + + rv = conn_call_end_origin(conn); + if (rv != 0) { + return rv; + } nghttp3_stream_read_state_reset(rstate); + break; case NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME: len = (size_t)nghttp3_min_int64(rstate->left, (int64_t)(end - p)); @@ -1251,7 +1453,7 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, goto almost_done; } - rstate->fr.hd.type = rvint->acc; + rstate->fr.type = rvint->acc; nghttp3_varint_read_state_reset(rvint); rstate->state = NGHTTP3_REQ_STREAM_STATE_FRAME_LENGTH; if (p == end) { @@ -1271,10 +1473,10 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, goto almost_done; } - rstate->left = rstate->fr.hd.length = rvint->acc; + rstate->left = rvint->acc; nghttp3_varint_read_state_reset(rvint); - switch (rstate->fr.hd.type) { + switch (rstate->fr.type) { case NGHTTP3_FRAME_DATA: rv = nghttp3_stream_transit_rx_http_state( stream, NGHTTP3_HTTP_EVENT_DATA_BEGIN); @@ -1374,10 +1576,6 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, nread = nghttp3_conn_on_headers(conn, stream, p, len, (int64_t)len == rstate->left); if (nread < 0) { - if (nread == NGHTTP3_ERR_MALFORMED_HTTP_HEADER) { - goto http_header_error; - } - return nread; } @@ -1416,10 +1614,6 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, } if (rv != 0) { - if (rv == NGHTTP3_ERR_MALFORMED_HTTP_HEADER) { - goto http_header_error; - } - return rv; } @@ -1459,24 +1653,6 @@ nghttp3_ssize nghttp3_conn_read_bidi(nghttp3_conn *conn, size_t *pnproc, nghttp3_stream_read_state_reset(rstate); break; - - http_header_error: - stream->flags |= NGHTTP3_STREAM_FLAG_HTTP_ERROR; - - busy = 1; - rstate->state = NGHTTP3_REQ_STREAM_STATE_IGN_REST; - - rv = conn_call_stop_sending(conn, stream, NGHTTP3_H3_MESSAGE_ERROR); - if (rv != 0) { - return rv; - } - - rv = conn_call_reset_stream(conn, stream, NGHTTP3_H3_MESSAGE_ERROR); - if (rv != 0) { - return rv; - } - - break; case NGHTTP3_REQ_STREAM_STATE_IGN_FRAME: len = (size_t)nghttp3_min_int64(rstate->left, (int64_t)(end - p)); p += len; @@ -1810,7 +1986,7 @@ conn_on_priority_update_stream(nghttp3_conn *conn, int nghttp3_conn_on_priority_update(nghttp3_conn *conn, const nghttp3_frame_priority_update *fr) { assert(conn->server); - assert(fr->hd.type == NGHTTP3_FRAME_PRIORITY_UPDATE); + assert(fr->type == NGHTTP3_FRAME_PRIORITY_UPDATE); return conn_on_priority_update_stream(conn, fr); } @@ -1899,10 +2075,27 @@ int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, int64_t stream_id) { return rv; } - frent.fr.hd.type = NGHTTP3_FRAME_SETTINGS; + frent.fr.type = NGHTTP3_FRAME_SETTINGS; frent.aux.settings.local_settings = &conn->local.settings; - return nghttp3_stream_frq_add(stream, &frent); + rv = nghttp3_stream_frq_add(stream, &frent); + if (rv != 0) { + return rv; + } + + if (conn->local.settings.origin_list) { + assert(conn->server); + + frent.fr.origin.type = NGHTTP3_FRAME_ORIGIN; + frent.fr.origin.origin_list = *conn->local.settings.origin_list; + + rv = nghttp3_stream_frq_add(stream, &frent); + if (rv != 0) { + return rv; + } + } + + return 0; } int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, int64_t qenc_stream_id, @@ -2126,14 +2319,14 @@ static int conn_submit_headers_data(nghttp3_conn *conn, nghttp3_stream *stream, const nghttp3_data_reader *dr) { int rv; nghttp3_nv *nnva; - nghttp3_frame_entry frent = {0}; + 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.type = NGHTTP3_FRAME_HEADERS; frent.fr.headers.nva = nnva; frent.fr.headers.nvlen = nvlen; @@ -2144,7 +2337,7 @@ static int conn_submit_headers_data(nghttp3_conn *conn, nghttp3_stream *stream, } if (dr) { - frent.fr.hd.type = NGHTTP3_FRAME_DATA; + frent.fr.type = NGHTTP3_FRAME_DATA; frent.aux.data.dr = *dr; rv = nghttp3_stream_frq_add(stream, &frent); @@ -2294,12 +2487,12 @@ int nghttp3_conn_submit_trailers(nghttp3_conn *conn, int64_t stream_id, } int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn) { - nghttp3_frame_entry frent = {0}; + nghttp3_frame_entry frent; int rv; assert(conn->tx.ctrl); - frent.fr.hd.type = NGHTTP3_FRAME_GOAWAY; + frent.fr.type = NGHTTP3_FRAME_GOAWAY; frent.fr.goaway.id = conn->server ? NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID : NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID; @@ -2317,12 +2510,12 @@ int nghttp3_conn_submit_shutdown_notice(nghttp3_conn *conn) { } int nghttp3_conn_shutdown(nghttp3_conn *conn) { - nghttp3_frame_entry frent = {0}; + nghttp3_frame_entry frent; int rv; assert(conn->tx.ctrl); - frent.fr.hd.type = NGHTTP3_FRAME_GOAWAY; + frent.fr.type = NGHTTP3_FRAME_GOAWAY; if (conn->server) { frent.fr.goaway.id = nghttp3_min_int64((1ll << 62) - 4, conn->rx.max_stream_id_bidi + 4); @@ -2576,7 +2769,7 @@ int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn, const uint8_t *data, size_t datalen) { nghttp3_stream *stream; - nghttp3_frame_entry frent = {0}; + nghttp3_frame_entry frent; uint8_t *buf = NULL; assert(!conn->server); @@ -2601,7 +2794,7 @@ int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn, memcpy(buf, data, datalen); } - frent.fr.hd.type = NGHTTP3_FRAME_PRIORITY_UPDATE; + frent.fr.type = NGHTTP3_FRAME_PRIORITY_UPDATE; frent.fr.priority_update.pri_elem_id = stream_id; frent.fr.priority_update.data = buf; frent.fr.priority_update.datalen = datalen; @@ -2644,13 +2837,3 @@ int nghttp3_conn_is_drained(nghttp3_conn *conn) { nghttp3_stream_outq_write_done(conn->tx.ctrl) && nghttp3_ringbuf_len(&conn->tx.ctrl->frq) == 0; } - -void nghttp3_settings_default_versioned(int settings_version, - nghttp3_settings *settings) { - (void)settings_version; - - memset(settings, 0, sizeof(nghttp3_settings)); - settings->max_field_section_size = NGHTTP3_VARINT_MAX; - settings->qpack_encoder_max_dtable_capacity = - NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY; -} diff --git a/contrib/libs/nghttp3/lib/nghttp3_conn.h b/contrib/libs/nghttp3/lib/nghttp3_conn.h index 3ab6d34422f..80c26f80322 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_conn.h +++ b/contrib/libs/nghttp3/lib/nghttp3_conn.h @@ -38,8 +38,6 @@ #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 @@ -95,6 +93,11 @@ struct nghttp3_conn { uint16_t flags; struct { + /* origin_list contains the shallow copy of + nghttp3_settings.origin_list passed from an application if this + object is initialized as server. settings.origin_list may + point to the address of this field. */ + nghttp3_vec origin_list; nghttp3_settings settings; struct { /* max_pushes is the number of push IDs that local endpoint can @@ -125,12 +128,36 @@ struct nghttp3_conn { int64_t max_stream_id_bidi; - /* pri_fieldbuf is a buffer to store incoming Priority Field Value - in PRIORITY_UPDATE frame. */ - uint8_t pri_fieldbuf[8]; - /* pri_fieldlen is the number of bytes written into - pri_fieldbuf. */ - size_t pri_fieldbuflen; + union { + struct { + /* pri_fieldbuf is a buffer to store incoming Priority Field Value + in PRIORITY_UPDATE frame. */ + uint8_t pri_fieldbuf[8]; + /* pri_fieldlen is the number of bytes written into + pri_fieldbuf. */ + size_t pri_fieldbuflen; + }; + /* ORIGIN frame */ + struct { + /* originlen_offset is the offset to Origin-Len that is going + to be added to originlen. If this value equals + sizeof(originlen), Origin-Len is fully read, and the length + of ASCII-Origin is determined. */ + size_t originlen_offset; + /* originlen is Origin-Len of ASCII-Origin currently read. */ + uint16_t originlen; + }; + }; + + /* originbuf points to the buffer that contains ASCII-Origin that + is not fully available in a single input buffer. If it is + fully available in the input buffer, it is emitted to an + application without using this field. Otherwise, partial + ASCII-Origin is copied to this field, and the complete + ASCII-Origin is emitted when the assembly finishes. */ + uint8_t *originbuf; + /* originbuflen is the length of bytes written to originbuf. */ + size_t originbuflen; } rx; struct { diff --git a/contrib/libs/nghttp3/lib/nghttp3_conv.h b/contrib/libs/nghttp3/lib/nghttp3_conv.h index f70802ce600..8895fe8d341 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_conv.h +++ b/contrib/libs/nghttp3/lib/nghttp3_conv.h @@ -56,6 +56,8 @@ #include <nghttp3/nghttp3.h> +#define NGHTTP3_VARINT_MAX ((1ull << 62) - 1) + #if HAVE_DECL_BE64TOH # define nghttp3_ntohl64(N) be64toh(N) # define nghttp3_htonl64(N) htobe64(N) diff --git a/contrib/libs/nghttp3/lib/nghttp3_frame.c b/contrib/libs/nghttp3/lib/nghttp3_frame.c index 1d87e448d88..da88b54f96d 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_frame.c +++ b/contrib/libs/nghttp3/lib/nghttp3_frame.c @@ -31,21 +31,22 @@ #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); +uint8_t *nghttp3_frame_write_hd(uint8_t *p, int64_t type, int64_t payloadlen) { + p = nghttp3_put_varint(p, type); + p = nghttp3_put_varint(p, payloadlen); return p; } -size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd) { - return nghttp3_put_varintlen(hd->type) + nghttp3_put_varintlen(hd->length); +size_t nghttp3_frame_write_hd_len(int64_t type, int64_t payloadlen) { + return nghttp3_put_varintlen(type) + nghttp3_put_varintlen(payloadlen); } uint8_t *nghttp3_frame_write_settings(uint8_t *p, - const nghttp3_frame_settings *fr) { + const nghttp3_frame_settings *fr, + int64_t payloadlen) { size_t i; - p = nghttp3_frame_write_hd(p, &fr->hd); + p = nghttp3_frame_write_hd(p, fr->type, payloadlen); for (i = 0; i < fr->niv; ++i) { p = nghttp3_put_varint(p, (int64_t)fr->iv[i].id); @@ -71,9 +72,9 @@ size_t nghttp3_frame_write_settings_len(int64_t *ppayloadlen, nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } -uint8_t *nghttp3_frame_write_goaway(uint8_t *p, - const nghttp3_frame_goaway *fr) { - p = nghttp3_frame_write_hd(p, &fr->hd); +uint8_t *nghttp3_frame_write_goaway(uint8_t *p, const nghttp3_frame_goaway *fr, + int64_t payloadlen) { + p = nghttp3_frame_write_hd(p, fr->type, payloadlen); p = nghttp3_put_varint(p, fr->id); return p; @@ -89,10 +90,9 @@ size_t nghttp3_frame_write_goaway_len(int64_t *ppayloadlen, nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } -uint8_t * -nghttp3_frame_write_priority_update(uint8_t *p, - const nghttp3_frame_priority_update *fr) { - p = nghttp3_frame_write_hd(p, &fr->hd); +uint8_t *nghttp3_frame_write_priority_update( + uint8_t *p, const nghttp3_frame_priority_update *fr, int64_t payloadlen) { + p = nghttp3_frame_write_hd(p, fr->type, payloadlen); p = nghttp3_put_varint(p, fr->pri_elem_id); if (fr->datalen) { p = nghttp3_cpymem(p, fr->data, fr->datalen); @@ -107,7 +107,27 @@ size_t nghttp3_frame_write_priority_update_len( *ppayloadlen = (int64_t)payloadlen; - return nghttp3_put_varintlen(fr->hd.type) + + return nghttp3_put_varintlen(fr->type) + + nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; +} + +uint8_t *nghttp3_frame_write_origin(uint8_t *p, const nghttp3_frame_origin *fr, + int64_t payloadlen) { + p = nghttp3_frame_write_hd(p, fr->type, payloadlen); + if (fr->origin_list.len) { + p = nghttp3_cpymem(p, fr->origin_list.base, fr->origin_list.len); + } + + return p; +} + +size_t nghttp3_frame_write_origin_len(int64_t *ppayloadlen, + const nghttp3_frame_origin *fr) { + size_t payloadlen = fr->origin_list.len; + + *ppayloadlen = (int64_t)payloadlen; + + return nghttp3_put_varintlen(fr->type) + nghttp3_put_varintlen((int64_t)payloadlen) + payloadlen; } diff --git a/contrib/libs/nghttp3/lib/nghttp3_frame.h b/contrib/libs/nghttp3/lib/nghttp3_frame.h index e216967d740..cca7ed0d6c9 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_frame.h +++ b/contrib/libs/nghttp3/lib/nghttp3_frame.h @@ -44,6 +44,8 @@ /* PRIORITY_UPDATE: https://datatracker.ietf.org/doc/html/rfc9218 */ #define NGHTTP3_FRAME_PRIORITY_UPDATE 0x0f0700 #define NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID 0x0f0701 +/* ORIGIN: https://datatracker.ietf.org/doc/html/rfc9412 */ +#define NGHTTP3_FRAME_ORIGIN 0x0c /* Frame types that are reserved for HTTP/2, and must not be used in HTTP/3. */ @@ -52,17 +54,12 @@ #define NGHTTP3_H2_FRAME_WINDOW_UPDATE 0x08 #define NGHTTP3_H2_FRAME_CONTINUATION 0x9 -typedef struct nghttp3_frame_hd { - int64_t type; - int64_t length; -} nghttp3_frame_hd; - typedef struct nghttp3_frame_data { - nghttp3_frame_hd hd; + int64_t type; } nghttp3_frame_data; typedef struct nghttp3_frame_headers { - nghttp3_frame_hd hd; + int64_t type; nghttp3_nv *nva; size_t nvlen; } nghttp3_frame_headers; @@ -84,20 +81,20 @@ typedef struct nghttp3_settings_entry { } nghttp3_settings_entry; typedef struct nghttp3_frame_settings { - nghttp3_frame_hd hd; + int64_t type; size_t niv; nghttp3_settings_entry iv[1]; } nghttp3_frame_settings; typedef struct nghttp3_frame_goaway { - nghttp3_frame_hd hd; + int64_t type; int64_t id; } nghttp3_frame_goaway; typedef struct nghttp3_frame_priority_update { - nghttp3_frame_hd hd; - /* pri_elem_id is stream ID if hd.type == - NGHTTP3_FRAME_PRIORITY_UPDATE. It is push ID if hd.type == + int64_t type; + /* pri_elem_id is stream ID if type == + NGHTTP3_FRAME_PRIORITY_UPDATE. It is push ID if type == NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID. It is undefined otherwise. */ int64_t pri_elem_id; @@ -114,42 +111,54 @@ typedef struct nghttp3_frame_priority_update { }; } nghttp3_frame_priority_update; +typedef struct nghttp3_frame_origin { + int64_t type; + /* These fields are only used by server to send ORIGIN frame. + Client never use them. */ + nghttp3_vec origin_list; +} nghttp3_frame_origin; + typedef union nghttp3_frame { - nghttp3_frame_hd hd; + int64_t type; nghttp3_frame_data data; nghttp3_frame_headers headers; nghttp3_frame_settings settings; nghttp3_frame_goaway goaway; nghttp3_frame_priority_update priority_update; + nghttp3_frame_origin origin; } nghttp3_frame; /* - * nghttp3_frame_write_hd writes frame header |hd| to |dest|. This - * function assumes that |dest| has enough space to write |hd|. + * nghttp3_frame_write_hd writes frame header consisting of |type| and + * |payloadlen| to |dest|. This function assumes that |dest| has + * enough space to write the frame header. * * This function returns |dest| plus the number of bytes written. */ -uint8_t *nghttp3_frame_write_hd(uint8_t *dest, const nghttp3_frame_hd *hd); +uint8_t *nghttp3_frame_write_hd(uint8_t *dest, int64_t type, + int64_t payloadlen); /* * nghttp3_frame_write_hd_len returns the number of bytes required to - * write |hd|. hd->length must be set. + * write a frame header consisting of |type| and |payloadlen|. */ -size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd); +size_t nghttp3_frame_write_hd_len(int64_t type, int64_t payloadlen); /* * nghttp3_frame_write_settings writes SETTINGS frame |fr| to |dest|. * This function assumes that |dest| has enough space to write |fr|. + * |payloadlen| is the length of the frame payload. * * This function returns |dest| plus the number of bytes written. */ uint8_t *nghttp3_frame_write_settings(uint8_t *dest, - const nghttp3_frame_settings *fr); + const nghttp3_frame_settings *fr, + int64_t payloadlen); /* * 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|. + * required to write |fr|. This function stores the frame payload + * length in |*ppayloadlen|. */ size_t nghttp3_frame_write_settings_len(int64_t *pppayloadlen, const nghttp3_frame_settings *fr); @@ -157,16 +166,18 @@ size_t nghttp3_frame_write_settings_len(int64_t *pppayloadlen, /* * nghttp3_frame_write_goaway writes GOAWAY frame |fr| to |dest|. * This function assumes that |dest| has enough space to write |fr|. + * |payloadlen| is the length of the frame payload. * * This function returns |dest| plus the number of bytes written. */ uint8_t *nghttp3_frame_write_goaway(uint8_t *dest, - const nghttp3_frame_goaway *fr); + const nghttp3_frame_goaway *fr, + int64_t payloadlen); /* * nghttp3_frame_write_goaway_len returns the number of bytes required - * to write |fr|. fr->hd.length is ignored. This function stores - * payload length in |*ppayloadlen|. + * to write |fr|. This function stores the frame payload length in + * |*ppayloadlen|. */ size_t nghttp3_frame_write_goaway_len(int64_t *ppayloadlen, const nghttp3_frame_goaway *fr); @@ -174,23 +185,41 @@ size_t nghttp3_frame_write_goaway_len(int64_t *ppayloadlen, /* * nghttp3_frame_write_priority_update writes PRIORITY_UPDATE frame * |fr| to |dest|. This function assumes that |dest| has enough space - * to write |fr|. + * to write |fr|. |payloadlen| is the length of the frame payload. * * This function returns |dest| plus the number of bytes written; */ -uint8_t * -nghttp3_frame_write_priority_update(uint8_t *dest, - const nghttp3_frame_priority_update *fr); +uint8_t *nghttp3_frame_write_priority_update( + uint8_t *dest, const nghttp3_frame_priority_update *fr, int64_t payloadlen); /* * nghttp3_frame_write_priority_update_len returns the number of bytes - * required to write |fr|. fr->hd.length is ignored. This function - * stores payload length in |*ppayloadlen|. + * required to write |fr|. This function stores the frame payload + * length in |*ppayloadlen|. */ size_t nghttp3_frame_write_priority_update_len( int64_t *ppayloadlen, const nghttp3_frame_priority_update *fr); /* + * nghttp3_frame_write_origin writes ORIGIN frame |fr| to |dest|. + * This function assumes that |dest| has enough space to write |fr|. + * |payloadlen| is the length of the frame payload. + * + * This function returns |dest| plus the number of bytes written; + */ +uint8_t *nghttp3_frame_write_origin(uint8_t *dest, + const nghttp3_frame_origin *fr, + int64_t payloadlen); + +/* + * nghttp3_frame_write_origin_len returns the number of bytes required + * to write |fr|. This function stores the frame payload length in + * |*ppayloadlen|. + */ +size_t nghttp3_frame_write_origin_len(int64_t *ppayloadlen, + const nghttp3_frame_origin *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 diff --git a/contrib/libs/nghttp3/lib/nghttp3_ksl.h b/contrib/libs/nghttp3/lib/nghttp3_ksl.h index d0ce8cd664d..be7469baa99 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_ksl.h +++ b/contrib/libs/nghttp3/lib/nghttp3_ksl.h @@ -295,8 +295,11 @@ 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))) +static inline nghttp3_ksl_node *nghttp3_ksl_nth_node(const nghttp3_ksl *ksl, + const nghttp3_ksl_blk *blk, + size_t n) { + return (nghttp3_ksl_node *)(void *)(blk->nodes + ksl->nodelen * n); +} #ifndef WIN32 /* @@ -318,18 +321,21 @@ void nghttp3_ksl_it_init(nghttp3_ksl_it *it, const nghttp3_ksl *ksl, * |it| points to. It is undefined to call this function when * nghttp3_ksl_it_end(it) returns nonzero. */ -#define nghttp3_ksl_it_get(IT) \ - nghttp3_ksl_nth_node((IT)->ksl, (IT)->blk, (IT)->i)->data +static inline void *nghttp3_ksl_it_get(const nghttp3_ksl_it *it) { + return nghttp3_ksl_nth_node(it->ksl, it->blk, it->i)->data; +} /* * 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) +static inline void nghttp3_ksl_it_next(nghttp3_ksl_it *it) { + if (++it->i == it->blk->n && it->blk->next) { + it->blk = it->blk->next; + it->i = 0; + } +} /* * nghttp3_ksl_it_prev moves backward the iterator by one. It is @@ -342,8 +348,9 @@ void nghttp3_ksl_it_prev(nghttp3_ksl_it *it); * nghttp3_ksl_it_end returns nonzero if |it| points to the one beyond * the last node. */ -#define nghttp3_ksl_it_end(IT) \ - ((IT)->blk->n == (IT)->i && (IT)->blk->next == NULL) +static inline int nghttp3_ksl_it_end(const nghttp3_ksl_it *it) { + return it->blk->n == it->i && it->blk->next == NULL; +} /* * nghttp3_ksl_it_begin returns nonzero if |it| points to the first @@ -357,8 +364,9 @@ int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it); * 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) +static inline nghttp3_ksl_key *nghttp3_ksl_it_key(const nghttp3_ksl_it *it) { + return (nghttp3_ksl_key *)nghttp3_ksl_nth_node(it->ksl, it->blk, it->i)->key; +} /* * nghttp3_ksl_range_compar is an implementation of diff --git a/contrib/libs/nghttp3/lib/nghttp3_map.c b/contrib/libs/nghttp3/lib/nghttp3_map.c index 829f9e83eeb..f3165c81e61 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_map.c +++ b/contrib/libs/nghttp3/lib/nghttp3_map.c @@ -32,12 +32,13 @@ #include "nghttp3_conv.h" -#define NGHTTP3_INITIAL_TABLE_LENBITS 4 +#define NGHTTP3_INITIAL_HASHBITS 4 -void nghttp3_map_init(nghttp3_map *map, const nghttp3_mem *mem) { +void nghttp3_map_init(nghttp3_map *map, uint64_t seed, const nghttp3_mem *mem) { map->mem = mem; map->hashbits = 0; map->table = NULL; + map->seed = seed; map->size = 0; } @@ -78,8 +79,14 @@ int nghttp3_map_each(const nghttp3_map *map, int (*func)(void *data, void *ptr), return 0; } -static size_t hash(nghttp3_map_key_type key, size_t bits) { - return (size_t)((key * 11400714819323198485llu) >> (64 - bits)); +static size_t map_hash(const nghttp3_map *map, nghttp3_map_key_type key) { + /* hasher from + https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs + We do not perform finalization here because we use top bits + anyway. */ + key += map->seed; + key *= 0xf1357aea2e62a9c5ull; + return (size_t)((key * 11400714819323198485llu) >> (64 - map->hashbits)); } static void map_bucket_swap(nghttp3_map_bucket *a, nghttp3_map_bucket *b) { @@ -110,28 +117,28 @@ void nghttp3_map_print_distance(const nghttp3_map *map) { continue; } - idx = hash(bkt->key, map->hashbits); + idx = map_hash(map, bkt->key); fprintf(stderr, "@%zu hash=%zu key=%" PRIu64 " base=%zu distance=%u\n", i, - hash(bkt->key, map->hashbits), bkt->key, idx, bkt->psl); + map_hash(map, bkt->key), bkt->key, idx, bkt->psl); } } #endif /* !defined(WIN32) */ -static int insert(nghttp3_map_bucket *table, size_t hashbits, - nghttp3_map_key_type key, void *data) { - size_t idx = hash(key, hashbits); +static int map_insert(nghttp3_map *map, nghttp3_map_key_type key, void *data) { + size_t idx = map_hash(map, key); nghttp3_map_bucket b = { .key = key, .data = data, }; nghttp3_map_bucket *bkt; - size_t mask = (1u << hashbits) - 1; + size_t mask = (1u << map->hashbits) - 1; for (;;) { - bkt = &table[idx]; + bkt = &map->table[idx]; if (bkt->data == NULL) { *bkt = b; + ++map->size; return 0; } @@ -152,15 +159,19 @@ static int insert(nghttp3_map_bucket *table, size_t hashbits, static int map_resize(nghttp3_map *map, size_t new_hashbits) { size_t i; - nghttp3_map_bucket *new_table; nghttp3_map_bucket *bkt; size_t tablelen; int rv; + nghttp3_map new_map = { + .table = nghttp3_mem_calloc(map->mem, 1u << new_hashbits, + sizeof(nghttp3_map_bucket)), + .mem = map->mem, + .seed = map->seed, + .hashbits = new_hashbits, + }; (void)rv; - new_table = nghttp3_mem_calloc(map->mem, 1u << new_hashbits, - sizeof(nghttp3_map_bucket)); - if (new_table == NULL) { + if (new_map.table == NULL) { return NGHTTP3_ERR_NOMEM; } @@ -173,15 +184,15 @@ static int map_resize(nghttp3_map *map, size_t new_hashbits) { continue; } - rv = insert(new_table, new_hashbits, bkt->key, bkt->data); + rv = map_insert(&new_map, bkt->key, bkt->data); assert(0 == rv); } } nghttp3_mem_free(map->mem, map->table); + map->table = new_map.table; map->hashbits = new_hashbits; - map->table = new_table; return 0; } @@ -191,30 +202,28 @@ int nghttp3_map_insert(nghttp3_map *map, nghttp3_map_key_type key, void *data) { assert(data); - /* Load factor is 0.75 */ + /* Load factor is 7/8 */ /* Under the very initial condition, that is map->size == 0 and - map->hashbits == 0, 4 > 3 still holds nicely. */ - if ((map->size + 1) * 4 > (1u << map->hashbits) * 3) { + map->hashbits == 0, 8 > 7 still holds nicely. */ + if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) { if (map->hashbits) { rv = map_resize(map, map->hashbits + 1); if (rv != 0) { return rv; } } else { - rv = map_resize(map, NGHTTP3_INITIAL_TABLE_LENBITS); + rv = map_resize(map, NGHTTP3_INITIAL_HASHBITS); if (rv != 0) { return rv; } } } - rv = insert(map->table, map->hashbits, key, data); + rv = map_insert(map, key, data); if (rv != 0) { return rv; } - ++map->size; - return 0; } @@ -228,7 +237,7 @@ void *nghttp3_map_find(const nghttp3_map *map, nghttp3_map_key_type key) { return NULL; } - idx = hash(key, map->hashbits); + idx = map_hash(map, key); mask = (1u << map->hashbits) - 1; for (;;) { @@ -257,7 +266,7 @@ int nghttp3_map_remove(nghttp3_map *map, nghttp3_map_key_type key) { return NGHTTP3_ERR_INVALID_ARGUMENT; } - idx = hash(key, map->hashbits); + idx = map_hash(map, key); mask = (1u << map->hashbits) - 1; for (;;) { diff --git a/contrib/libs/nghttp3/lib/nghttp3_map.h b/contrib/libs/nghttp3/lib/nghttp3_map.h index 2b1a6ecab5c..7496b486e17 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_map.h +++ b/contrib/libs/nghttp3/lib/nghttp3_map.h @@ -48,6 +48,7 @@ typedef struct nghttp3_map_bucket { typedef struct nghttp3_map { nghttp3_map_bucket *table; const nghttp3_mem *mem; + uint64_t seed; size_t size; size_t hashbits; } nghttp3_map; @@ -55,7 +56,7 @@ typedef struct nghttp3_map { /* * nghttp3_map_init initializes the map |map|. */ -void nghttp3_map_init(nghttp3_map *map, const nghttp3_mem *mem); +void nghttp3_map_init(nghttp3_map *map, uint64_t seed, const nghttp3_mem *mem); /* * nghttp3_map_free deallocates any resources allocated for |map|. diff --git a/contrib/libs/nghttp3/lib/nghttp3_qpack.c b/contrib/libs/nghttp3/lib/nghttp3_qpack.c index c41fc53b8f5..d2bac483004 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_qpack.c +++ b/contrib/libs/nghttp3/lib/nghttp3_qpack.c @@ -897,11 +897,11 @@ static int max_cnt_greater(const nghttp3_ksl_key *lhs, nghttp3_ksl_search_def(max_cnt_greater, max_cnt_greater) void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder, - size_t hard_max_dtable_capacity, + size_t hard_max_dtable_capacity, uint64_t seed, const nghttp3_mem *mem) { qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem); - nghttp3_map_init(&encoder->streams, mem); + nghttp3_map_init(&encoder->streams, seed, mem); nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater, ksl_max_cnt_greater_search, @@ -4072,9 +4072,9 @@ void nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder, sctx->rstate.value = NULL; } -int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, - size_t hard_max_dtable_capacity, - const nghttp3_mem *mem) { +int nghttp3_qpack_encoder_new2(nghttp3_qpack_encoder **pencoder, + size_t hard_max_dtable_capacity, uint64_t seed, + const nghttp3_mem *mem) { nghttp3_qpack_encoder *p; p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder)); @@ -4082,13 +4082,19 @@ int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, return NGHTTP3_ERR_NOMEM; } - nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem); + nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, seed, mem); *pencoder = p; return 0; } +int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder, + size_t hard_max_dtable_capacity, + const nghttp3_mem *mem) { + return nghttp3_qpack_encoder_new2(pencoder, hard_max_dtable_capacity, 0, mem); +} + void nghttp3_qpack_encoder_del(nghttp3_qpack_encoder *encoder) { const nghttp3_mem *mem; diff --git a/contrib/libs/nghttp3/lib/nghttp3_qpack.h b/contrib/libs/nghttp3/lib/nghttp3_qpack.h index cb82333abc4..77d264a533f 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_qpack.h +++ b/contrib/libs/nghttp3/lib/nghttp3_qpack.h @@ -269,10 +269,11 @@ struct nghttp3_qpack_encoder { /* * nghttp3_qpack_encoder_init initializes |encoder|. * |hard_max_dtable_capacity| is the upper bound of the dynamic table - * capacity. |mem| is a memory allocator. + * capacity. |seed| is used to initialize nghttp3_map. |mem| is a + * memory allocator. */ void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder, - size_t hard_max_dtable_capacity, + size_t hard_max_dtable_capacity, uint64_t seed, const nghttp3_mem *mem); /* diff --git a/contrib/libs/nghttp3/lib/nghttp3_ringbuf.h b/contrib/libs/nghttp3/lib/nghttp3_ringbuf.h index b154290a51d..691c40b93d6 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_ringbuf.h +++ b/contrib/libs/nghttp3/lib/nghttp3_ringbuf.h @@ -103,7 +103,9 @@ void nghttp3_ringbuf_resize(nghttp3_ringbuf *rb, size_t len); 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) +static inline size_t nghttp3_ringbuf_len(const nghttp3_ringbuf *rb) { + return rb->len; +} /* nghttp3_ringbuf_full returns nonzero if |rb| is full. */ int nghttp3_ringbuf_full(nghttp3_ringbuf *rb); diff --git a/contrib/libs/nghttp3/lib/nghttp3_settings.c b/contrib/libs/nghttp3/lib/nghttp3_settings.c new file mode 100644 index 00000000000..2b7cd2892b3 --- /dev/null +++ b/contrib/libs/nghttp3/lib/nghttp3_settings.c @@ -0,0 +1,95 @@ +/* + * nghttp3 + * + * Copyright (c) 2025 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_settings.h" + +#include <string.h> +#include <assert.h> + +#include "nghttp3_conv.h" +#include "nghttp3_unreachable.h" + +/* NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY is the upper bound of the + dynamic table capacity that QPACK encoder is willing to use. */ +#define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096 + +void nghttp3_settings_default_versioned(int settings_version, + nghttp3_settings *settings) { + size_t len = nghttp3_settingslen_version(settings_version); + + memset(settings, 0, len); + + switch (settings_version) { + case NGHTTP3_SETTINGS_VERSION: + case NGHTTP3_SETTINGS_V1: + settings->max_field_section_size = NGHTTP3_VARINT_MAX; + settings->qpack_encoder_max_dtable_capacity = + NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY; + + break; + } +} + +static void settings_copy(nghttp3_settings *dest, const nghttp3_settings *src, + int settings_version) { + assert(settings_version != NGHTTP3_SETTINGS_VERSION); + + memcpy(dest, src, nghttp3_settingslen_version(settings_version)); +} + +const nghttp3_settings * +nghttp3_settings_convert_to_latest(nghttp3_settings *dest, int settings_version, + const nghttp3_settings *src) { + if (settings_version == NGHTTP3_SETTINGS_VERSION) { + return src; + } + + nghttp3_settings_default(dest); + + settings_copy(dest, src, settings_version); + + return dest; +} + +void nghttp3_settings_convert_to_old(int settings_version, + nghttp3_settings *dest, + const nghttp3_settings *src) { + assert(settings_version != NGHTTP3_SETTINGS_VERSION); + + settings_copy(dest, src, settings_version); +} + +size_t nghttp3_settingslen_version(int settings_version) { + nghttp3_settings settings; + + switch (settings_version) { + case NGHTTP3_SETTINGS_VERSION: + return sizeof(settings); + case NGHTTP3_SETTINGS_V1: + return offsetof(nghttp3_settings, h3_datagram) + + sizeof(settings.h3_datagram); + default: + nghttp3_unreachable(); + } +} diff --git a/contrib/libs/nghttp3/lib/nghttp3_settings.h b/contrib/libs/nghttp3/lib/nghttp3_settings.h new file mode 100644 index 00000000000..0632aafc489 --- /dev/null +++ b/contrib/libs/nghttp3/lib/nghttp3_settings.h @@ -0,0 +1,74 @@ +/* + * nghttp3 + * + * Copyright (c) 2025 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_SETTINGS_H +#define NGHTTP3_SETTINGS_H + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* defined(HAVE_CONFIG_H) */ + +#include <nghttp3/nghttp3.h> + +/* + * nghttp3_settings_convert_to_latest converts |src| of version + * |settings_version| to the latest version NGHTTP3_SETTINGS_VERSION. + * + * |dest| must point to the latest version. |src| may be the older + * version, and if so, it may have fewer fields. Accessing those + * fields causes undefined behavior. + * + * If |settings_version| == NGHTTP3_SETTINGS_VERSION, no conversion is + * made, and |src| is returned. Otherwise, first |dest| is + * initialized via nghttp3_settings_default, and then all valid fields + * in |src| are copied into |dest|. Finally, |dest| is returned. + */ +const nghttp3_settings * +nghttp3_settings_convert_to_latest(nghttp3_settings *dest, int settings_version, + const nghttp3_settings *src); + +/* + * nghttp3_settings_convert_to_old converts |src| of the latest + * version to |dest| of version |settings_version|. + * + * |settings_version| must not be the latest version + * NGHTTP3_SETTINGS_VERSION. + * + * |dest| points to the older version, and it may have fewer fields. + * Accessing those fields causes undefined behavior. + * + * This function copies all valid fields in version |settings_version| + * from |src| to |dest|. + */ +void nghttp3_settings_convert_to_old(int settings_version, + nghttp3_settings *dest, + const nghttp3_settings *src); + +/* + * nghttp3_settingslen_version returns the effective length of + * nghttp3_settings at the version |settings_version|. + */ +size_t nghttp3_settingslen_version(int settings_version); + +#endif /* !defined(NGHTTP3_SETTINGS_H) */ diff --git a/contrib/libs/nghttp3/lib/nghttp3_stream.c b/contrib/libs/nghttp3/lib/nghttp3_stream.c index 9ae9d4850d0..d6f8fac3c52 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_stream.c +++ b/contrib/libs/nghttp3/lib/nghttp3_stream.c @@ -57,10 +57,19 @@ int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, return NGHTTP3_ERR_NOMEM; } - memset(stream, 0, sizeof(*stream)); - - stream->out_chunk_objalloc = out_chunk_objalloc; - stream->stream_objalloc = stream_objalloc; + *stream = (nghttp3_stream){ + .out_chunk_objalloc = out_chunk_objalloc, + .stream_objalloc = stream_objalloc, + .qpack_blocked_pe.index = NGHTTP3_PQ_BAD_INDEX, + .mem = mem, + .rx = + { + .http.status_code = -1, + .http.content_length = -1, + .http.pri.urgency = NGHTTP3_DEFAULT_URGENCY, + }, + .error_code = NGHTTP3_H3_NO_ERROR, + }; nghttp3_tnode_init(&stream->node, stream_id); @@ -71,13 +80,6 @@ int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id, nghttp3_qpack_stream_context_init(&stream->qpack_sctx, stream_id, mem); - 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.urgency = NGHTTP3_DEFAULT_URGENCY; - stream->error_code = NGHTTP3_H3_NO_ERROR; - if (callbacks) { stream->callbacks = *callbacks; } @@ -140,7 +142,7 @@ static void delete_frq(nghttp3_ringbuf *frq, const nghttp3_mem *mem) { for (i = 0; i < len; ++i) { frent = nghttp3_ringbuf_get(frq, i); - switch (frent->fr.hd.type) { + switch (frent->fr.type) { case NGHTTP3_FRAME_HEADERS: nghttp3_frame_headers_free(&frent->fr.headers, mem); break; @@ -253,7 +255,7 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) { stream->unsent_bytes < NGHTTP3_MIN_UNSENT_BYTES;) { frent = nghttp3_ringbuf_get(frq, 0); - switch (frent->fr.hd.type) { + switch (frent->fr.type) { case NGHTTP3_FRAME_SETTINGS: rv = nghttp3_stream_write_settings(stream, frent); if (rv != 0) { @@ -293,6 +295,13 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) { nghttp3_frame_priority_update_free(&frent->fr.priority_update, stream->mem); break; + case NGHTTP3_FRAME_ORIGIN: + rv = nghttp3_stream_write_origin(stream, frent); + if (rv != 0) { + return rv; + } + + break; default: /* TODO Not implemented */ break; @@ -336,15 +345,13 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream, } fr = { .settings = { - .hd = - { - .type = NGHTTP3_FRAME_SETTINGS, - }, + .type = NGHTTP3_FRAME_SETTINGS, .niv = 3, }, }; nghttp3_settings_entry *iv; nghttp3_settings *local_settings = frent->aux.settings.local_settings; + int64_t payloadlen; iv = &fr.settings.iv[0]; @@ -369,7 +376,7 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream, ++fr.settings.niv; } - len = nghttp3_frame_write_settings_len(&fr.settings.hd.length, &fr.settings); + len = nghttp3_frame_write_settings_len(&payloadlen, &fr.settings); rv = nghttp3_stream_ensure_chunk(stream, len); if (rv != 0) { @@ -379,7 +386,8 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream, chunk = nghttp3_stream_get_chunk(stream); nghttp3_typed_buf_shared_init(&tbuf, chunk); - chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings); + chunk->last = + nghttp3_frame_write_settings(chunk->last, &fr.settings, payloadlen); tbuf.buf.last = chunk->last; @@ -393,8 +401,9 @@ int nghttp3_stream_write_goaway(nghttp3_stream *stream, int rv; nghttp3_buf *chunk; nghttp3_typed_buf tbuf; + int64_t payloadlen; - len = nghttp3_frame_write_goaway_len(&fr->hd.length, fr); + len = nghttp3_frame_write_goaway_len(&payloadlen, fr); rv = nghttp3_stream_ensure_chunk(stream, len); if (rv != 0) { @@ -404,7 +413,7 @@ int nghttp3_stream_write_goaway(nghttp3_stream *stream, chunk = nghttp3_stream_get_chunk(stream); nghttp3_typed_buf_shared_init(&tbuf, chunk); - chunk->last = nghttp3_frame_write_goaway(chunk->last, fr); + chunk->last = nghttp3_frame_write_goaway(chunk->last, fr, payloadlen); tbuf.buf.last = chunk->last; @@ -418,8 +427,9 @@ int nghttp3_stream_write_priority_update(nghttp3_stream *stream, int rv; nghttp3_buf *chunk; nghttp3_typed_buf tbuf; + int64_t payloadlen; - len = nghttp3_frame_write_priority_update_len(&fr->hd.length, fr); + len = nghttp3_frame_write_priority_update_len(&payloadlen, fr); rv = nghttp3_stream_ensure_chunk(stream, len); if (rv != 0) { @@ -429,13 +439,53 @@ int nghttp3_stream_write_priority_update(nghttp3_stream *stream, chunk = nghttp3_stream_get_chunk(stream); nghttp3_typed_buf_shared_init(&tbuf, chunk); - chunk->last = nghttp3_frame_write_priority_update(chunk->last, fr); + chunk->last = + nghttp3_frame_write_priority_update(chunk->last, fr, payloadlen); tbuf.buf.last = chunk->last; return nghttp3_stream_outq_add(stream, &tbuf); } +int nghttp3_stream_write_origin(nghttp3_stream *stream, + nghttp3_frame_entry *frent) { + nghttp3_frame_origin *fr = &frent->fr.origin; + nghttp3_buf *chunk; + nghttp3_buf buf; + nghttp3_typed_buf tbuf; + int rv; + + rv = nghttp3_stream_ensure_chunk( + stream, nghttp3_frame_write_hd_len(fr->type, (int64_t)fr->origin_list.len)); + if (rv != 0) { + return rv; + } + + chunk = nghttp3_stream_get_chunk(stream); + nghttp3_typed_buf_shared_init(&tbuf, chunk); + + chunk->last = + nghttp3_frame_write_hd(chunk->last, fr->type, (int64_t)fr->origin_list.len); + + tbuf.buf.last = chunk->last; + + rv = nghttp3_stream_outq_add(stream, &tbuf); + if (rv != 0) { + return rv; + } + + if (fr->origin_list.len == 0) { + return 0; + } + + nghttp3_buf_wrap_init(&buf, (uint8_t *)fr->origin_list.base, + fr->origin_list.len); + buf.last = buf.end; + nghttp3_typed_buf_init(&tbuf, &buf, NGHTTP3_BUF_TYPE_ALIEN_NO_ACK); + + 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; @@ -459,9 +509,9 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream, size_t len; nghttp3_buf *chunk; nghttp3_typed_buf tbuf; - nghttp3_frame_hd hd; uint8_t raw_pbuf[16]; size_t pbuflen, rbuflen, ebuflen; + int64_t payloadlen; nghttp3_buf_wrap_init(&pbuf, raw_pbuf, sizeof(raw_pbuf)); @@ -475,10 +525,9 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream, rbuflen = nghttp3_buf_len(rbuf); ebuflen = nghttp3_buf_len(ebuf); - hd.type = frame_type; - hd.length = (int64_t)(pbuflen + rbuflen); + payloadlen = (int64_t)(pbuflen + rbuflen); - len = nghttp3_frame_write_hd_len(&hd) + pbuflen; + len = nghttp3_frame_write_hd_len(frame_type, payloadlen) + pbuflen; if (rbuflen <= NGHTTP3_STREAM_MAX_COPY_THRES) { len += rbuflen; @@ -492,7 +541,7 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream, chunk = nghttp3_stream_get_chunk(stream); nghttp3_typed_buf_shared_init(&tbuf, chunk); - chunk->last = nghttp3_frame_write_hd(chunk->last, &hd); + chunk->last = nghttp3_frame_write_hd(chunk->last, frame_type, payloadlen); chunk->last = nghttp3_cpymem(chunk->last, pbuf.pos, pbuflen); nghttp3_buf_init(&pbuf); @@ -570,7 +619,6 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof, nghttp3_conn *conn = stream->conn; int64_t datalen; uint32_t flags = 0; - nghttp3_frame_hd hd; nghttp3_vec vec[8]; nghttp3_vec *v; nghttp3_ssize sveccnt; @@ -624,10 +672,7 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof, } } - hd.type = NGHTTP3_FRAME_DATA; - hd.length = datalen; - - len = nghttp3_frame_write_hd_len(&hd); + len = nghttp3_frame_write_hd_len(NGHTTP3_FRAME_DATA, datalen); rv = nghttp3_stream_ensure_chunk(stream, len); if (rv != 0) { @@ -637,7 +682,8 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof, chunk = nghttp3_stream_get_chunk(stream); nghttp3_typed_buf_shared_init(&tbuf, chunk); - chunk->last = nghttp3_frame_write_hd(chunk->last, &hd); + chunk->last = + nghttp3_frame_write_hd(chunk->last, NGHTTP3_FRAME_DATA, datalen); tbuf.buf.last = chunk->last; @@ -888,6 +934,7 @@ static void stream_pop_outq_entry(nghttp3_stream *stream, nghttp3_buf_free(&tbuf->buf, stream->mem); break; case NGHTTP3_BUF_TYPE_ALIEN: + case NGHTTP3_BUF_TYPE_ALIEN_NO_ACK: break; case NGHTTP3_BUF_TYPE_SHARED: assert(nghttp3_ringbuf_len(chunks)); diff --git a/contrib/libs/nghttp3/lib/nghttp3_stream.h b/contrib/libs/nghttp3/lib/nghttp3_stream.h index d24cae04470..759cf687a0c 100644 --- a/contrib/libs/nghttp3/lib/nghttp3_stream.h +++ b/contrib/libs/nghttp3/lib/nghttp3_stream.h @@ -69,6 +69,8 @@ typedef enum nghttp3_ctrl_stream_state { NGHTTP3_CTRL_STREAM_STATE_SETTINGS_VALUE, NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE_PRI_ELEM_ID, NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE, + NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ORIGIN_LEN, + NGHTTP3_CTRL_STREAM_STATE_ORIGIN_ASCII_ORIGIN, } nghttp3_ctrl_stream_state; typedef enum nghttp3_req_stream_state { @@ -129,10 +131,6 @@ typedef struct nghttp3_stream_read_state { /* NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED indicates that server received PRIORITY_UPDATE frame for this stream. */ #define NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED 0x0800u -/* NGHTTP3_STREAM_FLAG_HTTP_ERROR indicates that - NGHTTP3_ERR_MALFORMED_HTTP_HEADER error is encountered while - processing incoming HTTP fields. */ -#define NGHTTP3_STREAM_FLAG_HTTP_ERROR 0x1000u typedef enum nghttp3_stream_http_state { NGHTTP3_HTTP_STATE_NONE, @@ -319,6 +317,9 @@ int nghttp3_stream_write_goaway(nghttp3_stream *stream, int nghttp3_stream_write_priority_update(nghttp3_stream *stream, nghttp3_frame_entry *frent); +int nghttp3_stream_write_origin(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); diff --git a/contrib/libs/nghttp3/ya.make b/contrib/libs/nghttp3/ya.make index 51aa802b67b..7d8478a3168 100644 --- a/contrib/libs/nghttp3/ya.make +++ b/contrib/libs/nghttp3/ya.make @@ -2,9 +2,9 @@ LIBRARY() -VERSION(1.10.1) +VERSION(1.11.0) -ORIGINAL_SOURCE(https://github.com/ngtcp2/nghttp3/releases/download/v1.10.1/nghttp3-1.10.1.tar.xz) +ORIGINAL_SOURCE(https://github.com/ngtcp2/nghttp3/releases/download/v1.11.0/nghttp3-1.11.0.tar.xz) LICENSE( FSFAP AND @@ -39,6 +39,7 @@ CFLAGS( SRCS( lib/nghttp3_balloc.c lib/nghttp3_buf.c + lib/nghttp3_callbacks.c lib/nghttp3_conn.c lib/nghttp3_conv.c lib/nghttp3_debug.c @@ -59,6 +60,7 @@ SRCS( lib/nghttp3_range.c lib/nghttp3_rcbuf.c lib/nghttp3_ringbuf.c + lib/nghttp3_settings.c lib/nghttp3_str.c lib/nghttp3_stream.c lib/nghttp3_tnode.c |
