mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
deps: update nghttp2 to 1.65.0
PR-URL: https://github.com/nodejs/node/pull/57269 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
26ebedf9ef
commit
d74daeab96
11 changed files with 1226 additions and 2498 deletions
241
deps/nghttp2/lib/includes/nghttp2/nghttp2.h
vendored
241
deps/nghttp2/lib/includes/nghttp2/nghttp2.h
vendored
|
@ -3133,14 +3133,12 @@ nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
|
|||
/**
|
||||
* @function
|
||||
*
|
||||
* This option prevents the library from retaining closed streams to
|
||||
* maintain the priority tree. If this option is set to nonzero,
|
||||
* applications can discard closed stream completely to save memory.
|
||||
* .. warning::
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is submitted via `nghttp2_submit_settings()`, any
|
||||
* closed streams are not retained regardless of this option.
|
||||
* Deprecated. Closed streams are not retained anymore.
|
||||
*
|
||||
* This function works as before, but it does not take any effect
|
||||
* against :type:`nghttp2_session`.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
|
||||
int val);
|
||||
|
@ -3170,16 +3168,11 @@ NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
|
|||
/**
|
||||
* @function
|
||||
*
|
||||
* This option, if set to nonzero, allows server to fallback to
|
||||
* :rfc:`7540` priorities if SETTINGS_NO_RFC7540_PRIORITIES was not
|
||||
* received from client, and server submitted
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* = 1 via `nghttp2_submit_settings()`. Most of the advanced
|
||||
* functionality for RFC 7540 priorities are still disabled. This
|
||||
* fallback only enables the minimal feature set of RFC 7540
|
||||
* priorities to deal with priority signaling from client.
|
||||
* .. warning::
|
||||
* Deprecated. :rfc:`7540` priorities have been removed.
|
||||
*
|
||||
* Client session ignores this option.
|
||||
* This function works as before, but it does not take any effect
|
||||
* against :type:`nghttp2_session`.
|
||||
*/
|
||||
NGHTTP2_EXTERN void
|
||||
nghttp2_option_set_server_fallback_rfc7540_priorities(nghttp2_option *option,
|
||||
|
@ -4179,39 +4172,9 @@ NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session,
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return 0 without doing anything.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Changes priority of existing stream denoted by |stream_id|. The
|
||||
* new priority specification is |pri_spec|.
|
||||
*
|
||||
* The priority is changed silently and instantly, and no PRIORITY
|
||||
* frame will be sent to notify the peer of this change. This
|
||||
* function may be useful for server to change the priority of pushed
|
||||
* stream.
|
||||
*
|
||||
* If |session| is initialized as server, and ``pri_spec->stream_id``
|
||||
* points to the idle stream, the idle stream is created if it does
|
||||
* not exist. The created idle stream will depend on root stream
|
||||
* (stream 0) with weight 16.
|
||||
*
|
||||
* Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
|
||||
* found, we use default priority instead of given |pri_spec|. That
|
||||
* is make stream depend on root stream with weight 16.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is submitted via `nghttp2_submit_settings()`, this
|
||||
* function does nothing and returns 0.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* Attempted to depend on itself; or no stream exist for the given
|
||||
* |stream_id|; or |stream_id| is 0
|
||||
* This function is noop. It always returns 0.
|
||||
*/
|
||||
NGHTTP2_EXTERN int
|
||||
nghttp2_session_change_stream_priority(nghttp2_session *session,
|
||||
|
@ -4225,51 +4188,9 @@ nghttp2_session_change_stream_priority(nghttp2_session *session,
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return 0 without doing anything.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Creates idle stream with the given |stream_id|, and priority
|
||||
* |pri_spec|.
|
||||
*
|
||||
* The stream creation is done without sending PRIORITY frame, which
|
||||
* means that peer does not know about the existence of this idle
|
||||
* stream in the local endpoint.
|
||||
*
|
||||
* RFC 7540 does not disallow the use of creation of idle stream with
|
||||
* odd or even stream ID regardless of client or server. So this
|
||||
* function can create odd or even stream ID regardless of client or
|
||||
* server. But probably it is a bit safer to use the stream ID the
|
||||
* local endpoint can initiate (in other words, use odd stream ID for
|
||||
* client, and even stream ID for server), to avoid potential
|
||||
* collision from peer's instruction. Also we can use
|
||||
* `nghttp2_session_set_next_stream_id()` to avoid to open created
|
||||
* idle streams accidentally if we follow this recommendation.
|
||||
*
|
||||
* If |session| is initialized as server, and ``pri_spec->stream_id``
|
||||
* points to the idle stream, the idle stream is created if it does
|
||||
* not exist. The created idle stream will depend on root stream
|
||||
* (stream 0) with weight 16.
|
||||
*
|
||||
* Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
|
||||
* found, we use default priority instead of given |pri_spec|. That
|
||||
* is make stream depend on root stream with weight 16.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is submitted via `nghttp2_submit_settings()`, this
|
||||
* function does nothing and returns 0.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* Attempted to depend on itself; or stream denoted by |stream_id|
|
||||
* already exists; or |stream_id| cannot be used to create idle
|
||||
* stream (in other words, local endpoint has already opened
|
||||
* stream ID greater than or equal to the given stream ID; or
|
||||
* |stream_id| is 0
|
||||
* This function is noop. It always returns 0.
|
||||
*/
|
||||
NGHTTP2_EXTERN int
|
||||
nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id,
|
||||
|
@ -4505,23 +4426,7 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
|||
*
|
||||
* Submits HEADERS frame and optionally one or more DATA frames.
|
||||
*
|
||||
* The |pri_spec| is a deprecated priority specification of this
|
||||
* request. ``NULL`` means the default priority (see
|
||||
* `nghttp2_priority_spec_default_init()`). To specify the priority,
|
||||
* use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
|
||||
* this function will copy its data members.
|
||||
*
|
||||
* The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight``
|
||||
* is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is received by a remote endpoint, |pri_spec| is
|
||||
* ignored, and treated as if ``NULL`` is specified.
|
||||
* The |pri_spec| is ignored.
|
||||
*
|
||||
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
|
||||
* |nvlen| elements. The application is responsible to include
|
||||
|
@ -4564,9 +4469,6 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
|||
* :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
|
||||
* No stream ID is available because maximum stream ID was
|
||||
* reached.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* Trying to depend on itself (new stream ID equals
|
||||
* ``pri_spec->stream_id``).
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_PROTO`
|
||||
* The |session| is server session.
|
||||
*
|
||||
|
@ -4594,25 +4496,7 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_request(
|
|||
*
|
||||
* Submits HEADERS frame and optionally one or more DATA frames.
|
||||
*
|
||||
* The |pri_spec| is a deprecated priority specification of this
|
||||
* request. ``NULL`` means the default priority (see
|
||||
* `nghttp2_priority_spec_default_init()`). To specify the priority,
|
||||
* use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
|
||||
* this function will copy its data members. In the future release
|
||||
* after the end of 2024, this function will ignore |pri_spec| and
|
||||
* behave as if ``NULL`` is given.
|
||||
*
|
||||
* The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight``
|
||||
* is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is received by a remote endpoint, |pri_spec| is
|
||||
* ignored, and treated as if ``NULL`` is specified.
|
||||
* The |pri_spec| is ignored.
|
||||
*
|
||||
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
|
||||
* |nvlen| elements. The application is responsible to include
|
||||
|
@ -4655,9 +4539,6 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_request(
|
|||
* :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
|
||||
* No stream ID is available because maximum stream ID was
|
||||
* reached.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* Trying to depend on itself (new stream ID equals
|
||||
* ``pri_spec->stream_id``).
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_PROTO`
|
||||
* The |session| is server session.
|
||||
*
|
||||
|
@ -4899,24 +4780,7 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
|
|||
* assigned stream ID will be returned. Otherwise, specify stream ID
|
||||
* in |stream_id|.
|
||||
*
|
||||
* The |pri_spec| is a deprecated priority specification of this
|
||||
* request. ``NULL`` means the default priority (see
|
||||
* `nghttp2_priority_spec_default_init()`). To specify the priority,
|
||||
* use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
|
||||
* this function will copy its data members. In the future release
|
||||
* after the end of 2024, this function will ignore |pri_spec| and
|
||||
* behave as if ``NULL`` is given.
|
||||
*
|
||||
* The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight``
|
||||
* is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`, it becomes :macro:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is received by a remote endpoint, |pri_spec| is
|
||||
* ignored, and treated as if ``NULL`` is specified.
|
||||
* The |pri_spec| is ignored.
|
||||
*
|
||||
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
|
||||
* |nvlen| elements. The application is responsible to include
|
||||
|
@ -4956,8 +4820,7 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
|
|||
* No stream ID is available because maximum stream ID was
|
||||
* reached.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |stream_id| is 0; or trying to depend on itself (stream ID
|
||||
* equals ``pri_spec->stream_id``).
|
||||
* The |stream_id| is 0.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST`
|
||||
* DATA or HEADERS has been already submitted and not fully
|
||||
* processed yet. This happens if stream denoted by |stream_id|
|
||||
|
@ -5083,40 +4946,9 @@ NGHTTP2_EXTERN int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags,
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return 0 without doing anything.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Submits PRIORITY frame to change the priority of stream |stream_id|
|
||||
* to the priority specification |pri_spec|.
|
||||
*
|
||||
* The |flags| is currently ignored and should be
|
||||
* :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`.
|
||||
*
|
||||
* The |pri_spec| is a deprecated priority specification of this
|
||||
* request. ``NULL`` is not allowed for this function. To specify the
|
||||
* priority, use `nghttp2_priority_spec_init()`. This function will
|
||||
* copy its data members.
|
||||
*
|
||||
* The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight``
|
||||
* is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`, it becomes
|
||||
* :macro:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* If
|
||||
* :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
|
||||
* of value of 1 is received by a remote endpoint, this function does
|
||||
* nothing and returns 0.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |stream_id| is 0; or the |pri_spec| is NULL; or trying to
|
||||
* depend on itself.
|
||||
* This function is noop. It always returns 0.
|
||||
*/
|
||||
NGHTTP2_EXTERN int
|
||||
nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
||||
|
@ -6885,11 +6717,9 @@ nghttp2_session_get_root_stream(nghttp2_session *session);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return NULL.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns the parent stream of |stream| in dependency tree. Returns
|
||||
* NULL if there is no such stream.
|
||||
* This function always returns NULL.
|
||||
*/
|
||||
NGHTTP2_EXTERN nghttp2_stream *
|
||||
nghttp2_stream_get_parent(nghttp2_stream *stream);
|
||||
|
@ -6903,11 +6733,9 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return NULL.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns the next sibling stream of |stream| in dependency tree.
|
||||
* Returns NULL if there is no such stream.
|
||||
* This function always returns NULL.
|
||||
*/
|
||||
NGHTTP2_EXTERN nghttp2_stream *
|
||||
nghttp2_stream_get_next_sibling(nghttp2_stream *stream);
|
||||
|
@ -6919,11 +6747,9 @@ nghttp2_stream_get_next_sibling(nghttp2_stream *stream);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return NULL.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns the previous sibling stream of |stream| in dependency tree.
|
||||
* Returns NULL if there is no such stream.
|
||||
* This function always returns NULL.
|
||||
*/
|
||||
NGHTTP2_EXTERN nghttp2_stream *
|
||||
nghttp2_stream_get_previous_sibling(nghttp2_stream *stream);
|
||||
|
@ -6935,11 +6761,9 @@ nghttp2_stream_get_previous_sibling(nghttp2_stream *stream);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return NULL.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns the first child stream of |stream| in dependency tree.
|
||||
* Returns NULL if there is no such stream.
|
||||
* This function always returns NULL.
|
||||
*/
|
||||
NGHTTP2_EXTERN nghttp2_stream *
|
||||
nghttp2_stream_get_first_child(nghttp2_stream *stream);
|
||||
|
@ -6951,11 +6775,9 @@ nghttp2_stream_get_first_child(nghttp2_stream *stream);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return
|
||||
* :macro:`NGHTTP2_DEFAULT_WEIGHT`.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns dependency weight to the parent stream of |stream|.
|
||||
* This function always returns :macro:`NGHTTP2_DEFAULT_WEIGHT`.
|
||||
*/
|
||||
NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
|
||||
|
||||
|
@ -6966,10 +6788,9 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
|
|||
*
|
||||
* Deprecated. :rfc:`7540` priorities are deprecated by
|
||||
* :rfc:`9113`. Consider migrating to :rfc:`9218` extensible
|
||||
* prioritization scheme. In the future release after the end of
|
||||
* 2024, this function will always return 0.
|
||||
* prioritization scheme.
|
||||
*
|
||||
* Returns the sum of the weight for |stream|'s children.
|
||||
* This function always returns 0.
|
||||
*/
|
||||
NGHTTP2_EXTERN int32_t
|
||||
nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* @macro
|
||||
* Version number of the nghttp2 library release
|
||||
*/
|
||||
#define NGHTTP2_VERSION "1.64.0"
|
||||
#define NGHTTP2_VERSION "1.65.0"
|
||||
|
||||
/**
|
||||
* @macro
|
||||
|
@ -37,6 +37,6 @@
|
|||
* release. This is a 24 bit number with 8 bits for major number, 8 bits
|
||||
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
|
||||
*/
|
||||
#define NGHTTP2_VERSION_NUM 0x014000
|
||||
#define NGHTTP2_VERSION_NUM 0x014100
|
||||
|
||||
#endif /* NGHTTP2VER_H */
|
||||
|
|
11
deps/nghttp2/lib/nghttp2_hd.c
vendored
11
deps/nghttp2/lib/nghttp2_hd.c
vendored
|
@ -594,8 +594,19 @@ static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
|
|||
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
|
||||
nghttp2_mem *mem) {
|
||||
size_t size;
|
||||
const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
|
||||
|
||||
if (bufsize > max_size) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
for (size = 1; size < bufsize; size <<= 1)
|
||||
;
|
||||
|
||||
if (size > max_size) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
|
||||
if (ringbuf->buffer == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
|
|
17
deps/nghttp2/lib/nghttp2_http.c
vendored
17
deps/nghttp2/lib/nghttp2_http.c
vendored
|
@ -207,7 +207,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||
if (!trailer &&
|
||||
/* Do not parse the header field in PUSH_PROMISE. */
|
||||
(stream->stream_id & 1) &&
|
||||
(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
|
||||
!(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) {
|
||||
nghttp2_extpri_from_uint8(&extpri, stream->http_extpri);
|
||||
if (nghttp2_http_parse_priority(&extpri, nv->value->base,
|
||||
|
@ -660,17 +659,17 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream,
|
|||
int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||
size_t valuelen) {
|
||||
nghttp2_extpri pri = *dest;
|
||||
sf_parser sfp;
|
||||
sf_vec key;
|
||||
sf_value val;
|
||||
sfparse_parser sfp;
|
||||
sfparse_vec key;
|
||||
sfparse_value val;
|
||||
int rv;
|
||||
|
||||
sf_parser_init(&sfp, value, valuelen);
|
||||
sfparse_parser_init(&sfp, value, valuelen);
|
||||
|
||||
for (;;) {
|
||||
rv = sf_parser_dict(&sfp, &key, &val);
|
||||
rv = sfparse_parser_dict(&sfp, &key, &val);
|
||||
if (rv != 0) {
|
||||
if (rv == SF_ERR_EOF) {
|
||||
if (rv == SFPARSE_ERR_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -683,7 +682,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
|||
|
||||
switch (key.base[0]) {
|
||||
case 'i':
|
||||
if (val.type != SF_TYPE_BOOLEAN) {
|
||||
if (val.type != SFPARSE_TYPE_BOOLEAN) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -691,7 +690,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
|||
|
||||
break;
|
||||
case 'u':
|
||||
if (val.type != SF_TYPE_INTEGER ||
|
||||
if (val.type != SFPARSE_TYPE_INTEGER ||
|
||||
val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH ||
|
||||
NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
|
|
707
deps/nghttp2/lib/nghttp2_session.c
vendored
707
deps/nghttp2/lib/nghttp2_session.c
vendored
File diff suppressed because it is too large
Load diff
120
deps/nghttp2/lib/nghttp2_session.h
vendored
120
deps/nghttp2/lib/nghttp2_session.h
vendored
|
@ -45,6 +45,8 @@
|
|||
preface handling. */
|
||||
extern int nghttp2_enable_strict_preface;
|
||||
|
||||
extern nghttp2_stream root;
|
||||
|
||||
/*
|
||||
* Option flags.
|
||||
*/
|
||||
|
@ -53,8 +55,6 @@ typedef enum {
|
|||
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
|
||||
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
|
||||
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
|
||||
NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4,
|
||||
NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5,
|
||||
NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
|
||||
} nghttp2_optmask;
|
||||
|
||||
|
@ -89,10 +89,6 @@ typedef struct {
|
|||
/* The default maximum number of incoming reserved streams */
|
||||
#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200
|
||||
|
||||
/* Even if we have less SETTINGS_MAX_CONCURRENT_STREAMS than this
|
||||
number, we keep NGHTTP2_MIN_IDLE_STREAMS streams in idle state */
|
||||
#define NGHTTP2_MIN_IDLE_STREAMS 16
|
||||
|
||||
/* The maximum number of items in outbound queue, which is considered
|
||||
as flooding caused by peer. All frames are not considered here.
|
||||
We only consider PING + ACK and SETTINGS + ACK. This is because
|
||||
|
@ -205,8 +201,6 @@ typedef struct nghttp2_inflight_settings nghttp2_inflight_settings;
|
|||
|
||||
struct nghttp2_session {
|
||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||
/* root of dependency tree*/
|
||||
nghttp2_stream root;
|
||||
/* Queue for outbound urgent frames (PING and SETTINGS) */
|
||||
nghttp2_outbound_queue ob_urgent;
|
||||
/* Queue for non-DATA frames */
|
||||
|
@ -229,20 +223,6 @@ struct nghttp2_session {
|
|||
/* Memory allocator */
|
||||
nghttp2_mem mem;
|
||||
void *user_data;
|
||||
/* Points to the latest incoming closed stream. NULL if there is no
|
||||
closed stream. Only used when session is initialized as
|
||||
server. */
|
||||
nghttp2_stream *closed_stream_head;
|
||||
/* Points to the oldest incoming closed stream. NULL if there is no
|
||||
closed stream. Only used when session is initialized as
|
||||
server. */
|
||||
nghttp2_stream *closed_stream_tail;
|
||||
/* Points to the latest idle stream. NULL if there is no idle
|
||||
stream. Only used when session is initialized as server .*/
|
||||
nghttp2_stream *idle_stream_head;
|
||||
/* Points to the oldest idle stream. NULL if there is no idle
|
||||
stream. Only used when session is initialized as erver. */
|
||||
nghttp2_stream *idle_stream_tail;
|
||||
/* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not
|
||||
considered as in-flight. */
|
||||
nghttp2_inflight_settings *inflight_settings_head;
|
||||
|
@ -276,10 +256,9 @@ struct nghttp2_session {
|
|||
|closed_stream_head|. The current implementation only keeps
|
||||
incoming streams and session is initialized as server. */
|
||||
size_t num_closed_streams;
|
||||
/* The number of idle streams kept in |streams| hash. The idle
|
||||
streams can be accessed through doubly linked list
|
||||
|idle_stream_head|. The current implementation only keeps idle
|
||||
streams if session is initialized as server. */
|
||||
/* The number of idle streams kept in |streams| hash. The current
|
||||
implementation only keeps idle streams if session is initialized
|
||||
as server. */
|
||||
size_t num_idle_streams;
|
||||
/* The number of bytes allocated for nvbuf */
|
||||
size_t nvbuflen;
|
||||
|
@ -362,8 +341,6 @@ struct nghttp2_session {
|
|||
/* Unacked local SETTINGS_NO_RFC7540_PRIORITIES value, which is
|
||||
effective before it is acknowledged. */
|
||||
uint8_t pending_no_rfc7540_priorities;
|
||||
/* Turn on fallback to RFC 7540 priorities; for server use only. */
|
||||
uint8_t fallback_rfc7540_priorities;
|
||||
/* Nonzero if the session is server side. */
|
||||
uint8_t server;
|
||||
/* Flags indicating GOAWAY is sent and/or received. The flags are
|
||||
|
@ -527,15 +504,9 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
|||
*
|
||||
* This function returns a pointer to created new stream object, or
|
||||
* NULL.
|
||||
*
|
||||
* This function adjusts neither the number of closed streams or idle
|
||||
* streams. The caller should manually call
|
||||
* nghttp2_session_adjust_closed_stream() or
|
||||
* nghttp2_session_adjust_idle_stream() respectively.
|
||||
*/
|
||||
nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
|
||||
int32_t stream_id, uint8_t flags,
|
||||
nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_stream_state initial_state,
|
||||
void *stream_user_data);
|
||||
|
||||
|
@ -544,11 +515,6 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
|
|||
* is indicated by the |error_code|. When closing the stream,
|
||||
* on_stream_close_callback will be called.
|
||||
*
|
||||
* If the session is initialized as server and |stream| is incoming
|
||||
* stream, stream is just marked closed and this function calls
|
||||
* nghttp2_session_keep_closed_stream() with |stream|. Otherwise,
|
||||
* |stream| will be deleted from memory.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
|
@ -565,63 +531,9 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
|
|||
/*
|
||||
* Deletes |stream| from memory. After this function returns, stream
|
||||
* cannot be accessed.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Tries to keep incoming closed stream |stream|. Due to the
|
||||
* limitation of maximum number of streams in memory, |stream| is not
|
||||
* closed and just deleted from memory (see
|
||||
* nghttp2_session_destroy_stream).
|
||||
*/
|
||||
void nghttp2_session_keep_closed_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Appends |stream| to linked list |session->idle_stream_head|. We
|
||||
* apply fixed limit for list size. To fit into that limit, one or
|
||||
* more oldest streams are removed from list as necessary.
|
||||
*/
|
||||
void nghttp2_session_keep_idle_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Detaches |stream| from idle streams linked list.
|
||||
*/
|
||||
void nghttp2_session_detach_idle_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Deletes closed stream to ensure that number of incoming streams
|
||||
* including active and closed is in the maximum number of allowed
|
||||
* stream.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_adjust_closed_stream(nghttp2_session *session);
|
||||
|
||||
/*
|
||||
* Deletes idle stream to ensure that number of idle streams is in
|
||||
* certain limit.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_adjust_idle_stream(nghttp2_session *session);
|
||||
void nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* If further receptions and transmissions over the stream |stream_id|
|
||||
|
@ -915,24 +827,6 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
|
|||
nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Re-prioritize |stream|. The new priority specification is
|
||||
* |pri_spec|. Caller must ensure that stream->hd.stream_id !=
|
||||
* pri_spec->stream_id.
|
||||
*
|
||||
* This function does not adjust the number of idle streams. The
|
||||
* caller should call nghttp2_session_adjust_idle_stream() later.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_reprioritize_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream,
|
||||
const nghttp2_priority_spec *pri_spec);
|
||||
|
||||
/*
|
||||
* Terminates current |session| with the |error_code|. The |reason|
|
||||
* is NULL-terminated debug string.
|
||||
|
|
849
deps/nghttp2/lib/nghttp2_stream.c
vendored
849
deps/nghttp2/lib/nghttp2_stream.c
vendored
|
@ -25,45 +25,17 @@
|
|||
#include "nghttp2_stream.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nghttp2_session.h"
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_debug.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
/* Maximum distance between any two stream's cycle in the same
|
||||
priority queue. Imagine stream A's cycle is A, and stream B's
|
||||
cycle is B, and A < B. The cycle is unsigned 32 bit integer, it
|
||||
may get overflow. Because of how we calculate the next cycle
|
||||
value, if B - A is less than or equals to
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other
|
||||
words, B is really greater than or equal to A. Otherwise, A is a
|
||||
result of overflow, and it is actually A > B if we consider that
|
||||
fact. */
|
||||
#define NGHTTP2_MAX_CYCLE_DISTANCE \
|
||||
((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX * 256 + 255)
|
||||
|
||||
static int stream_less(const void *lhsx, const void *rhsx) {
|
||||
const nghttp2_stream *lhs, *rhs;
|
||||
|
||||
lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
|
||||
rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
|
||||
|
||||
if (lhs->cycle == rhs->cycle) {
|
||||
return lhs->seq < rhs->seq;
|
||||
}
|
||||
|
||||
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||
}
|
||||
|
||||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags, nghttp2_stream_state initial_state,
|
||||
int32_t weight, int32_t remote_initial_window_size,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data, nghttp2_mem *mem) {
|
||||
nghttp2_pq_init(&stream->obq, stream_less, mem);
|
||||
|
||||
void *stream_user_data) {
|
||||
stream->stream_id = stream_id;
|
||||
stream->flags = flags;
|
||||
stream->state = initial_state;
|
||||
|
@ -77,428 +49,36 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||
stream->recv_reduction = 0;
|
||||
stream->window_update_queued = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
stream->closed_prev = NULL;
|
||||
stream->closed_next = NULL;
|
||||
|
||||
stream->weight = weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
|
||||
stream->content_length = -1;
|
||||
stream->recv_content_length = 0;
|
||||
stream->status_code = -1;
|
||||
|
||||
stream->queued = 0;
|
||||
stream->descendant_last_cycle = 0;
|
||||
stream->cycle = 0;
|
||||
stream->pending_penalty = 0;
|
||||
stream->descendant_next_seq = 0;
|
||||
stream->seq = 0;
|
||||
stream->last_writelen = 0;
|
||||
|
||||
stream->extpri = stream->http_extpri = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
|
||||
}
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream) {
|
||||
nghttp2_pq_free(&stream->obq);
|
||||
/* We don't free stream->item. If it is assigned to aob, then
|
||||
active_outbound_item_reset() will delete it. Otherwise,
|
||||
nghttp2_stream_close() or session_del() will delete it. */
|
||||
}
|
||||
void nghttp2_stream_free(nghttp2_stream *stream) { (void)stream; }
|
||||
|
||||
void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
|
||||
stream->shut_flags = (uint8_t)(stream->shut_flags | flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| is active. This function does not take
|
||||
* into account its descendants.
|
||||
*/
|
||||
static int stream_active(nghttp2_stream *stream) {
|
||||
return stream->item &&
|
||||
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| or one of its descendants is active
|
||||
*/
|
||||
static int stream_subtree_active(nghttp2_stream *stream) {
|
||||
return stream_active(stream) || !nghttp2_pq_empty(&stream->obq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns next cycle for |stream|.
|
||||
*/
|
||||
static void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
|
||||
uint64_t penalty;
|
||||
|
||||
penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
|
||||
stream->pending_penalty;
|
||||
|
||||
stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
|
||||
stream->pending_penalty = (uint32_t)(penalty % (uint32_t)stream->weight);
|
||||
}
|
||||
|
||||
static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
for (; dep_stream && !stream->queued;
|
||||
stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
||||
stream->seq = dep_stream->descendant_next_seq++;
|
||||
|
||||
DEBUGF("stream: stream=%d obq push cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
|
||||
DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
|
||||
dep_stream->stream_id);
|
||||
|
||||
rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
stream->queued = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes |stream| from parent's obq. If removal of |stream| makes
|
||||
* parent's obq empty, and parent is not active, then parent is also
|
||||
* removed. This process is repeated recursively.
|
||||
*/
|
||||
static void stream_obq_remove(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_stream;
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
if (!stream->queued) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id,
|
||||
dep_stream->stream_id);
|
||||
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
assert(stream->queued);
|
||||
|
||||
stream->queued = 0;
|
||||
stream->cycle = 0;
|
||||
stream->pending_penalty = 0;
|
||||
stream->descendant_last_cycle = 0;
|
||||
stream->last_writelen = 0;
|
||||
|
||||
if (stream_subtree_active(dep_stream)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves |stream| from |src|'s obq to |dest|'s obq. Removal from
|
||||
* |src|'s obq is just done calling nghttp2_pq_remove(), so it does
|
||||
* not recursively remove |src| and ancestors, like
|
||||
* stream_obq_remove().
|
||||
*/
|
||||
static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src,
|
||||
nghttp2_stream *stream) {
|
||||
if (!stream->queued) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id,
|
||||
src->stream_id);
|
||||
|
||||
nghttp2_pq_remove(&src->obq, &stream->pq_entry);
|
||||
stream->queued = 0;
|
||||
|
||||
return stream_obq_push(dest, stream);
|
||||
}
|
||||
|
||||
void nghttp2_stream_reschedule(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_stream;
|
||||
|
||||
assert(stream->queued);
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
||||
stream->seq = dep_stream->descendant_next_seq++;
|
||||
|
||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
|
||||
dep_stream->last_writelen = stream->last_writelen;
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
||||
nghttp2_stream *dep_stream;
|
||||
uint64_t last_cycle;
|
||||
int32_t old_weight;
|
||||
uint64_t wlen_penalty;
|
||||
|
||||
if (stream->weight == weight) {
|
||||
return;
|
||||
}
|
||||
|
||||
old_weight = stream->weight;
|
||||
stream->weight = weight;
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
if (!dep_stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
dep_stream->sum_dep_weight += weight - old_weight;
|
||||
|
||||
if (!stream->queued) {
|
||||
return;
|
||||
}
|
||||
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
wlen_penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
|
||||
|
||||
/* Compute old stream->pending_penalty we used to calculate
|
||||
stream->cycle */
|
||||
stream->pending_penalty =
|
||||
(uint32_t)((stream->pending_penalty + (uint32_t)old_weight -
|
||||
(wlen_penalty % (uint32_t)old_weight)) %
|
||||
(uint32_t)old_weight);
|
||||
|
||||
last_cycle = stream->cycle -
|
||||
(wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight;
|
||||
|
||||
/* Now we have old stream->pending_penalty and new stream->weight in
|
||||
place */
|
||||
stream_next_cycle(stream, last_cycle);
|
||||
|
||||
if (dep_stream->descendant_last_cycle - stream->cycle <=
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
||||
stream->cycle = dep_stream->descendant_last_cycle;
|
||||
}
|
||||
|
||||
/* Continue to use same stream->seq */
|
||||
|
||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
}
|
||||
|
||||
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
||||
for (; stream->sib_next; stream = stream->sib_next)
|
||||
;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight) {
|
||||
weight = stream->weight * weight / stream->sum_dep_weight;
|
||||
|
||||
return nghttp2_max_int32(1, weight);
|
||||
}
|
||||
|
||||
#ifdef STREAM_DEP_DEBUG
|
||||
|
||||
static void ensure_inactive(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
if (stream->queued) {
|
||||
fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream,
|
||||
stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (stream_active(stream)) {
|
||||
fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n",
|
||||
stream, stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream,
|
||||
stream->stream_id, nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_queued(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int queued;
|
||||
|
||||
if (stream->queued) {
|
||||
if (!stream_subtree_active(stream)) {
|
||||
fprintf(stderr,
|
||||
"stream(%p)=%d, stream->queued == 1, but "
|
||||
"stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n",
|
||||
stream, stream->stream_id, stream_active(stream),
|
||||
nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
if (!stream_active(stream)) {
|
||||
queued = 0;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->queued) {
|
||||
++queued;
|
||||
}
|
||||
}
|
||||
if (queued == 0) {
|
||||
fprintf(stderr,
|
||||
"stream(%p)=%d, stream->queued == 1, and "
|
||||
"!stream_active(), but no descendants is queued\n",
|
||||
stream, stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_queued(si);
|
||||
}
|
||||
} else {
|
||||
if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr,
|
||||
"stream(%p) = %d, stream->queued == 0, but "
|
||||
"stream_active(stream) == %d and "
|
||||
"nghttp2_pq_size(&stream->obq) = %zu\n",
|
||||
stream, stream->stream_id, stream_active(stream),
|
||||
nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_sum_dep(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int32_t n = 0;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
n += si->weight;
|
||||
}
|
||||
if (n != stream->sum_dep_weight) {
|
||||
fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream,
|
||||
stream->stream_id, n, stream->sum_dep_weight);
|
||||
assert(0);
|
||||
}
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_sum_dep(si);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_dep_prev(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->dep_prev != stream) {
|
||||
fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream);
|
||||
assert(0);
|
||||
}
|
||||
check_dep_prev(si);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STREAM_DEP_DEBUG */
|
||||
|
||||
#ifdef STREAM_DEP_DEBUG
|
||||
static void validate_tree(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; stream->dep_prev; stream = stream->dep_prev)
|
||||
;
|
||||
|
||||
assert(stream->stream_id == 0);
|
||||
assert(!stream->queued);
|
||||
|
||||
fprintf(stderr, "checking...\n");
|
||||
if (nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr, "root obq empty\n");
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
} else {
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_queued(si);
|
||||
}
|
||||
}
|
||||
|
||||
check_sum_dep(stream);
|
||||
check_dep_prev(stream);
|
||||
}
|
||||
#else /* !STREAM_DEP_DEBUG */
|
||||
static void validate_tree(nghttp2_stream *stream) { (void)stream; }
|
||||
#endif /* !STREAM_DEP_DEBUG*/
|
||||
|
||||
static int stream_update_dep_on_attach_item(nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
rv = stream_obq_push(stream->dep_prev, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stream_update_dep_on_detach_item(nghttp2_stream *stream) {
|
||||
if (nghttp2_pq_empty(&stream->obq)) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item) {
|
||||
int rv;
|
||||
|
||||
void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item) {
|
||||
assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
|
||||
assert(stream->item == NULL);
|
||||
|
||||
DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
|
||||
|
||||
stream->item = item;
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = stream_update_dep_on_attach_item(stream);
|
||||
if (rv != 0) {
|
||||
/* This may relave stream->queued == 1, but stream->item == NULL.
|
||||
But only consequence of this error is fatal one, and session
|
||||
destruction. In that execution path, these inconsistency does
|
||||
not matter. */
|
||||
stream->item = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||
|
@ -506,12 +86,6 @@ void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
|||
|
||||
stream->item = NULL;
|
||||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
|
@ -521,31 +95,16 @@ void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
|||
stream->item, flags);
|
||||
|
||||
stream->flags |= flags;
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
void nghttp2_stream_resume_deferred_item(nghttp2_stream *stream,
|
||||
uint8_t flags) {
|
||||
assert(stream->item);
|
||||
|
||||
DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
|
||||
stream->item, flags);
|
||||
|
||||
stream->flags = (uint8_t)(stream->flags & ~flags);
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stream_update_dep_on_attach_item(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) {
|
||||
|
@ -591,373 +150,11 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
|
|||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||
nghttp2_stream *target) {
|
||||
for (; stream; stream = stream->dep_prev) {
|
||||
if (stream == target) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
|
||||
dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
stream->sum_dep_weight = dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
for (si = dep_stream->dep_next; si; si = si->sib_next) {
|
||||
si->dep_prev = stream;
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream, dep_stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
stream->dep_next = dep_stream->dep_next;
|
||||
}
|
||||
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
validate_tree(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
|
||||
for (; stream; stream = stream->sib_next) {
|
||||
stream->dep_prev = dep;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
dep_stream->dep_next = stream;
|
||||
if (stream) {
|
||||
stream->dep_prev = dep_stream;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_sib(nghttp2_stream *a, nghttp2_stream *b) {
|
||||
a->sib_next = b;
|
||||
if (b) {
|
||||
b->sib_prev = a;
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_link_dep(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *sib_next;
|
||||
|
||||
assert(stream->sib_prev == NULL);
|
||||
|
||||
sib_next = dep_stream->dep_next;
|
||||
|
||||
link_sib(stream, sib_next);
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
static void unlink_sib(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_next;
|
||||
|
||||
prev = stream->sib_prev;
|
||||
dep_next = stream->dep_next;
|
||||
|
||||
assert(prev);
|
||||
|
||||
if (dep_next) {
|
||||
/*
|
||||
* prev--stream(--sib_next--...)
|
||||
* |
|
||||
* dep_next
|
||||
*/
|
||||
|
||||
link_sib(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* prev--stream(--sib_next--...)
|
||||
*/
|
||||
next = stream->sib_next;
|
||||
|
||||
prev->sib_next = next;
|
||||
|
||||
if (next) {
|
||||
next->sib_prev = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void unlink_dep(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_next;
|
||||
|
||||
prev = stream->dep_prev;
|
||||
dep_next = stream->dep_next;
|
||||
|
||||
assert(prev);
|
||||
|
||||
if (dep_next) {
|
||||
/*
|
||||
* prev
|
||||
* |
|
||||
* stream(--sib_next--...)
|
||||
* |
|
||||
* dep_next
|
||||
*/
|
||||
link_dep(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
|
||||
} else if (stream->sib_next) {
|
||||
/*
|
||||
* prev
|
||||
* |
|
||||
* stream--sib_next
|
||||
*/
|
||||
next = stream->sib_next;
|
||||
|
||||
next->sib_prev = NULL;
|
||||
|
||||
link_dep(prev, next);
|
||||
} else {
|
||||
prev->dep_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
|
||||
dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
if (dep_stream->dep_next == NULL) {
|
||||
link_dep(dep_stream, stream);
|
||||
} else {
|
||||
insert_link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_prev, *si;
|
||||
int32_t sum_dep_weight_delta;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id);
|
||||
|
||||
/* Distribute weight of |stream| to direct descendants */
|
||||
sum_dep_weight_delta = -stream->weight;
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
||||
|
||||
sum_dep_weight_delta += si->weight;
|
||||
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream->dep_prev, stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(stream->dep_prev);
|
||||
|
||||
dep_prev = stream->dep_prev;
|
||||
|
||||
dep_prev->sum_dep_weight += sum_dep_weight_delta;
|
||||
|
||||
if (stream->queued) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
if (stream->sib_prev) {
|
||||
unlink_sib(stream);
|
||||
} else {
|
||||
unlink_dep(stream);
|
||||
}
|
||||
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
validate_tree(dep_prev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *dep_next;
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
stream->sum_dep_weight += dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
dep_next = dep_stream->dep_next;
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
|
||||
if (stream->dep_next) {
|
||||
last_sib = stream_last_sib(stream->dep_next);
|
||||
|
||||
link_sib(last_sib, dep_next);
|
||||
} else {
|
||||
link_dep(stream, dep_next);
|
||||
}
|
||||
|
||||
for (si = dep_next; si; si = si->sib_next) {
|
||||
si->dep_prev = stream;
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream, dep_stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
validate_tree(dep_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
insert_link_dep(dep_stream, stream);
|
||||
} else {
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
validate_tree(dep_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
|
||||
nghttp2_stream *next, *dep_prev;
|
||||
|
||||
DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream,
|
||||
stream->stream_id);
|
||||
|
||||
assert(stream->dep_prev);
|
||||
|
||||
dep_prev = stream->dep_prev;
|
||||
|
||||
if (stream->sib_prev) {
|
||||
link_sib(stream->sib_prev, stream->sib_next);
|
||||
} else {
|
||||
next = stream->sib_next;
|
||||
|
||||
link_dep(dep_prev, next);
|
||||
|
||||
if (next) {
|
||||
next->sib_prev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dep_prev->sum_dep_weight -= stream->weight;
|
||||
|
||||
if (stream->queued) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
validate_tree(dep_prev);
|
||||
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
stream->dep_prev = NULL;
|
||||
}
|
||||
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
|
||||
return stream->dep_prev || stream->dep_next || stream->sib_prev ||
|
||||
stream->sib_next;
|
||||
}
|
||||
|
||||
nghttp2_outbound_item *
|
||||
nghttp2_stream_next_outbound_item(nghttp2_stream *stream) {
|
||||
nghttp2_pq_entry *ent;
|
||||
nghttp2_stream *si;
|
||||
|
||||
for (;;) {
|
||||
if (stream_active(stream)) {
|
||||
/* Update ascendant's descendant_last_cycle here, so that we can
|
||||
assure that new stream is scheduled based on it. */
|
||||
for (si = stream; si->dep_prev; si = si->dep_prev) {
|
||||
si->dep_prev->descendant_last_cycle = si->cycle;
|
||||
}
|
||||
return stream->item;
|
||||
}
|
||||
ent = nghttp2_pq_top(&stream->obq);
|
||||
if (!ent) {
|
||||
return NULL;
|
||||
}
|
||||
stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
||||
if (stream == &root) {
|
||||
return NGHTTP2_STREAM_STATE_IDLE;
|
||||
}
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) {
|
||||
return NGHTTP2_STREAM_STATE_CLOSED;
|
||||
}
|
||||
|
@ -988,27 +185,39 @@ nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
|||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) {
|
||||
return stream->dep_prev;
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
|
||||
return stream->sib_next;
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
|
||||
return stream->sib_prev;
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
|
||||
return stream->dep_next;
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
|
||||
return stream->weight;
|
||||
(void)stream;
|
||||
|
||||
return NGHTTP2_DEFAULT_WEIGHT;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
|
||||
return stream->sum_dep_weight;
|
||||
(void)stream;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) {
|
||||
|
|
157
deps/nghttp2/lib/nghttp2_stream.h
vendored
157
deps/nghttp2/lib/nghttp2_stream.h
vendored
|
@ -91,9 +91,6 @@ typedef enum {
|
|||
/* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
|
||||
NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
|
||||
NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c,
|
||||
/* Indicates that this stream is not subject to RFC7540
|
||||
priorities scheme. */
|
||||
NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10,
|
||||
/* Ignore client RFC 9218 priority signal. */
|
||||
NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
|
||||
/* Indicates that RFC 9113 leading and trailing white spaces
|
||||
|
@ -146,39 +143,18 @@ typedef enum {
|
|||
} nghttp2_http_flag;
|
||||
|
||||
struct nghttp2_stream {
|
||||
/* Entry for dep_prev->obq */
|
||||
nghttp2_stream_state state;
|
||||
nghttp2_pq_entry pq_entry;
|
||||
/* Priority Queue storing direct descendant (nghttp2_stream). Only
|
||||
streams which itself has some data to send, or has a descendant
|
||||
which has some data to sent. */
|
||||
nghttp2_pq obq;
|
||||
/* Content-Length of request/response body. -1 if unknown. */
|
||||
int64_t content_length;
|
||||
/* Received body so far */
|
||||
int64_t recv_content_length;
|
||||
/* Base last_cycle for direct descendent streams. */
|
||||
uint64_t descendant_last_cycle;
|
||||
/* Next scheduled time to sent item */
|
||||
uint64_t cycle;
|
||||
/* Next seq used for direct descendant streams */
|
||||
uint64_t descendant_next_seq;
|
||||
/* Secondary key for prioritization to break a tie for cycle. This
|
||||
value is monotonically increased for single parent stream. */
|
||||
uint64_t seq;
|
||||
/* pointers to form dependency tree. If multiple streams depend on
|
||||
a stream, only one stream (left most) has non-NULL dep_prev which
|
||||
points to the stream it depends on. The remaining streams are
|
||||
linked using sib_prev and sib_next. The stream which has
|
||||
non-NULL dep_prev always NULL sib_prev. The right most stream
|
||||
has NULL sib_next. If this stream is a root of dependency tree,
|
||||
dep_prev and sib_prev are NULL. */
|
||||
nghttp2_stream *dep_prev, *dep_next;
|
||||
nghttp2_stream *sib_prev, *sib_next;
|
||||
/* When stream is kept after closure, it may be kept in doubly
|
||||
linked list pointed by nghttp2_session closed_stream_head.
|
||||
closed_next points to the next stream object if it is the element
|
||||
of the list. */
|
||||
nghttp2_stream *closed_prev, *closed_next;
|
||||
nghttp2_stream *closed_next;
|
||||
/* The arbitrary data provided by user for this stream. */
|
||||
void *stream_user_data;
|
||||
/* Item to send */
|
||||
|
@ -205,13 +181,8 @@ struct nghttp2_stream {
|
|||
NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
|
||||
submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
|
||||
int32_t local_window_size;
|
||||
/* weight of this stream */
|
||||
int32_t weight;
|
||||
/* This is unpaid penalty (offset) when calculating cycle. */
|
||||
uint32_t pending_penalty;
|
||||
/* sum of weight of direct descendants */
|
||||
int32_t sum_dep_weight;
|
||||
nghttp2_stream_state state;
|
||||
/* status code from remote server */
|
||||
int16_t status_code;
|
||||
/* Bitwise OR of zero or more nghttp2_http_flag values */
|
||||
|
@ -239,9 +210,9 @@ struct nghttp2_stream {
|
|||
|
||||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags, nghttp2_stream_state initial_state,
|
||||
int32_t weight, int32_t remote_initial_window_size,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data, nghttp2_mem *mem);
|
||||
void *stream_user_data);
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream);
|
||||
|
||||
|
@ -267,14 +238,8 @@ void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
|
|||
* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
|
||||
* cleared if they are set. So even if this function is called, if
|
||||
* one of flag is still set, data does not become active.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
|
||||
void nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
|
||||
|
||||
/*
|
||||
* Returns nonzero if item is deferred by whatever reason.
|
||||
|
@ -317,57 +282,11 @@ int nghttp2_stream_update_local_initial_window_size(
|
|||
*/
|
||||
void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Returns nonzero if |target| is an ancestor of |stream|.
|
||||
*/
|
||||
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||
nghttp2_stream *target);
|
||||
|
||||
/*
|
||||
* Computes distributed weight of a stream of the |weight| under the
|
||||
* |stream| if |stream| is removed from a dependency tree.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* exclusive. All existing direct descendants of |dep_stream| become
|
||||
* the descendants of the |stream|. This function assumes
|
||||
* |stream->item| is NULL.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* not exclusive. This function assumes |stream->item| is NULL.
|
||||
*/
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Removes the |stream| from the current dependency tree. This
|
||||
* function assumes |stream->item| is NULL.
|
||||
*/
|
||||
int nghttp2_stream_dep_remove(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Attaches |item| to |stream|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item);
|
||||
void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* Detaches |stream->item|. This function does not free
|
||||
|
@ -375,66 +294,4 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
|||
*/
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* exclusive.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* not exclusive.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Removes subtree whose root stream is |stream|. The
|
||||
* effective_weight of streams in removed subtree is not updated.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| is in any dependency tree.
|
||||
*/
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Schedules transmission of |stream|'s item, assuming stream->item is
|
||||
* attached, and stream->last_writelen was updated.
|
||||
*/
|
||||
void nghttp2_stream_reschedule(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Changes |stream|'s weight to |weight|. If |stream| is queued, it
|
||||
* will be rescheduled based on new weight.
|
||||
*/
|
||||
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight);
|
||||
|
||||
/*
|
||||
* Returns a stream which has highest priority, updating
|
||||
* descendant_last_cycle of selected stream's ancestors.
|
||||
*/
|
||||
nghttp2_outbound_item *
|
||||
nghttp2_stream_next_outbound_item(nghttp2_stream *stream);
|
||||
|
||||
#endif /* NGHTTP2_STREAM */
|
||||
|
|
155
deps/nghttp2/lib/nghttp2_submit.c
vendored
155
deps/nghttp2/lib/nghttp2_submit.c
vendored
|
@ -32,42 +32,12 @@
|
|||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_priority_spec.h"
|
||||
|
||||
/*
|
||||
* Detects the dependency error, that is stream attempted to depend on
|
||||
* itself. If |stream_id| is -1, we use session->next_stream_id as
|
||||
* stream ID.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* Stream attempted to depend on itself.
|
||||
*/
|
||||
static int detect_self_dependency(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec) {
|
||||
assert(pri_spec);
|
||||
|
||||
if (stream_id == -1) {
|
||||
if ((int32_t)session->next_stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function takes ownership of |nva_copy|. Regardless of the
|
||||
return value, the caller must not free |nva_copy| after this
|
||||
function returns. */
|
||||
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_nv *nva_copy, size_t nvlen,
|
||||
int32_t stream_id, nghttp2_nv *nva_copy,
|
||||
size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
|
@ -114,8 +84,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
|||
|
||||
frame = &item->frame;
|
||||
|
||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
|
||||
pri_spec, nva_copy, nvlen);
|
||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat, NULL,
|
||||
nva_copy, nvlen);
|
||||
|
||||
rv = nghttp2_session_add_item(session, item);
|
||||
|
||||
|
@ -141,31 +111,22 @@ fail2:
|
|||
|
||||
static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
||||
uint8_t flags, int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
nghttp2_nv *nva_copy;
|
||||
nghttp2_priority_spec copy_pri_spec;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = &session->mem;
|
||||
|
||||
if (pri_spec) {
|
||||
copy_pri_spec = *pri_spec;
|
||||
nghttp2_priority_spec_normalize_weight(©_pri_spec);
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(©_pri_spec);
|
||||
}
|
||||
|
||||
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
||||
nva_copy, nvlen, dpw, stream_user_data);
|
||||
return submit_headers_shared(session, flags, stream_id, nva_copy, nvlen, dpw,
|
||||
stream_user_data);
|
||||
}
|
||||
|
||||
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
||||
|
@ -174,8 +135,8 @@ int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
|||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return (int)submit_headers_shared_nva(
|
||||
session, NGHTTP2_FLAG_END_STREAM, stream_id, NULL, nva, nvlen, NULL, NULL);
|
||||
return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM,
|
||||
stream_id, nva, nvlen, NULL, NULL);
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
||||
|
@ -183,7 +144,7 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
|||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
(void)pri_spec;
|
||||
|
||||
if (stream_id == -1) {
|
||||
if (session->server) {
|
||||
|
@ -195,20 +156,8 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
|||
|
||||
flags &= NGHTTP2_FLAG_END_STREAM;
|
||||
|
||||
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
|
||||
session->remote_settings.no_rfc7540_priorities != 1) {
|
||||
rv = detect_self_dependency(session, stream_id, pri_spec);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
} else {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva,
|
||||
nvlen, NULL, stream_user_data);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, NULL,
|
||||
stream_user_data);
|
||||
}
|
||||
|
||||
int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
||||
|
@ -220,51 +169,10 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
|||
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec) {
|
||||
int rv;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame *frame;
|
||||
nghttp2_priority_spec copy_pri_spec;
|
||||
nghttp2_mem *mem;
|
||||
(void)session;
|
||||
(void)flags;
|
||||
|
||||
mem = &session->mem;
|
||||
|
||||
if (session->remote_settings.no_rfc7540_priorities == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_id == 0 || pri_spec == NULL) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
copy_pri_spec = *pri_spec;
|
||||
|
||||
nghttp2_priority_spec_normalize_weight(©_pri_spec);
|
||||
|
||||
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
|
||||
|
||||
if (item == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
frame = &item->frame;
|
||||
|
||||
nghttp2_frame_priority_init(&frame->priority, stream_id, ©_pri_spec);
|
||||
|
||||
rv = nghttp2_session_add_item(session, item);
|
||||
|
||||
if (rv != 0) {
|
||||
nghttp2_frame_priority_free(&frame->priority);
|
||||
nghttp2_mem_free(mem, item);
|
||||
|
||||
return rv;
|
||||
}
|
||||
(void)stream_id;
|
||||
(void)pri_spec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -738,46 +646,29 @@ fail_item_malloc:
|
|||
return rv;
|
||||
}
|
||||
|
||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
static uint8_t set_request_flags(const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
|
||||
if (pri_spec) {
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int32_t submit_request_shared(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
uint8_t flags;
|
||||
int rv;
|
||||
|
||||
if (session->server) {
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
|
||||
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
|
||||
session->remote_settings.no_rfc7540_priorities != 1) {
|
||||
rv = detect_self_dependency(session, -1, pri_spec);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
flags = set_request_flags(dpw);
|
||||
|
||||
flags = set_request_flags(pri_spec, dpw);
|
||||
|
||||
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
||||
dpw, stream_user_data);
|
||||
return submit_headers_shared_nva(session, flags, -1, nva, nvlen, dpw,
|
||||
stream_user_data);
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
|
@ -786,8 +677,9 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
|
|||
const nghttp2_data_provider *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
(void)pri_spec;
|
||||
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
return submit_request_shared(session, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v1(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
|
@ -798,8 +690,9 @@ int32_t nghttp2_submit_request2(nghttp2_session *session,
|
|||
const nghttp2_data_provider2 *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
(void)pri_spec;
|
||||
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
return submit_request_shared(session, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v2(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
|
@ -826,8 +719,8 @@ static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
|||
}
|
||||
|
||||
flags = set_response_flags(dpw);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
||||
dpw, NULL);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, dpw,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
|
|
1148
deps/nghttp2/lib/sfparse.c
vendored
1148
deps/nghttp2/lib/sfparse.c
vendored
File diff suppressed because it is too large
Load diff
315
deps/nghttp2/lib/sfparse.h
vendored
315
deps/nghttp2/lib/sfparse.h
vendored
|
@ -31,86 +31,90 @@
|
|||
libcurl) */
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#endif
|
||||
#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
||||
#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) */
|
||||
#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||
# include <inttypes.h>
|
||||
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||
#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* :type:`sf_type` defines value type.
|
||||
* :type:`sfparse_type` defines value type.
|
||||
*/
|
||||
typedef enum sf_type {
|
||||
typedef enum sfparse_type {
|
||||
/**
|
||||
* :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
|
||||
* :enum:`SFPARSE_TYPE_BOOLEAN` indicates boolean type.
|
||||
*/
|
||||
SF_TYPE_BOOLEAN,
|
||||
SFPARSE_TYPE_BOOLEAN,
|
||||
/**
|
||||
* :enum:`SF_TYPE_INTEGER` indicates integer type.
|
||||
* :enum:`SFPARSE_TYPE_INTEGER` indicates integer type.
|
||||
*/
|
||||
SF_TYPE_INTEGER,
|
||||
SFPARSE_TYPE_INTEGER,
|
||||
/**
|
||||
* :enum:`SF_TYPE_DECIMAL` indicates decimal type.
|
||||
* :enum:`SFPARSE_TYPE_DECIMAL` indicates decimal type.
|
||||
*/
|
||||
SF_TYPE_DECIMAL,
|
||||
SFPARSE_TYPE_DECIMAL,
|
||||
/**
|
||||
* :enum:`SF_TYPE_STRING` indicates string type.
|
||||
* :enum:`SFPARSE_TYPE_STRING` indicates string type.
|
||||
*/
|
||||
SF_TYPE_STRING,
|
||||
SFPARSE_TYPE_STRING,
|
||||
/**
|
||||
* :enum:`SF_TYPE_TOKEN` indicates token type.
|
||||
* :enum:`SFPARSE_TYPE_TOKEN` indicates token type.
|
||||
*/
|
||||
SF_TYPE_TOKEN,
|
||||
SFPARSE_TYPE_TOKEN,
|
||||
/**
|
||||
* :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
|
||||
* :enum:`SFPARSE_TYPE_BYTESEQ` indicates byte sequence type.
|
||||
*/
|
||||
SF_TYPE_BYTESEQ,
|
||||
SFPARSE_TYPE_BYTESEQ,
|
||||
/**
|
||||
* :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
|
||||
* :enum:`SFPARSE_TYPE_INNER_LIST` indicates inner list type.
|
||||
*/
|
||||
SF_TYPE_INNER_LIST,
|
||||
SFPARSE_TYPE_INNER_LIST,
|
||||
/**
|
||||
* :enum:`SF_TYPE_DATE` indicates date type.
|
||||
* :enum:`SFPARSE_TYPE_DATE` indicates date type.
|
||||
*/
|
||||
SF_TYPE_DATE
|
||||
} sf_type;
|
||||
SFPARSE_TYPE_DATE,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
|
||||
*/
|
||||
SFPARSE_TYPE_DISPSTRING
|
||||
} sfparse_type;
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
|
||||
* :macro:`SFPARSE_ERR_PARSE` indicates fatal parse error has
|
||||
* occurred, and it is not possible to continue the processing.
|
||||
*/
|
||||
#define SF_ERR_PARSE_ERROR -1
|
||||
#define SFPARSE_ERR_PARSE -1
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
|
||||
* The context of this error varies depending on the function that
|
||||
* returns this error code.
|
||||
* :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
|
||||
* read. The context of this error varies depending on the function
|
||||
* that returns this error code.
|
||||
*/
|
||||
#define SF_ERR_EOF -2
|
||||
#define SFPARSE_ERR_EOF -2
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sf_vec` stores sequence of bytes.
|
||||
* :type:`sfparse_vec` stores sequence of bytes.
|
||||
*/
|
||||
typedef struct sf_vec {
|
||||
typedef struct sfparse_vec {
|
||||
/**
|
||||
* :member:`base` points to the beginning of the sequence of bytes.
|
||||
*/
|
||||
|
@ -119,29 +123,29 @@ typedef struct sf_vec {
|
|||
* :member:`len` is the number of bytes contained in this sequence.
|
||||
*/
|
||||
size_t len;
|
||||
} sf_vec;
|
||||
} sfparse_vec;
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
|
||||
* :macro:`SFPARSE_VALUE_FLAG_NONE` indicates no flag set.
|
||||
*/
|
||||
#define SF_VALUE_FLAG_NONE 0x0u
|
||||
#define SFPARSE_VALUE_FLAG_NONE 0x0u
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||
* contains escaped character(s).
|
||||
*/
|
||||
#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||
#define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sf_decimal` contains decimal value.
|
||||
* :type:`sfparse_decimal` contains decimal value.
|
||||
*/
|
||||
typedef struct sf_decimal {
|
||||
typedef struct sfparse_decimal {
|
||||
/**
|
||||
* :member:`numer` contains numerator of the decimal value.
|
||||
*/
|
||||
|
@ -150,260 +154,289 @@ typedef struct sf_decimal {
|
|||
* :member:`denom` contains denominator of the decimal value.
|
||||
*/
|
||||
int64_t denom;
|
||||
} sf_decimal;
|
||||
} sfparse_decimal;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sf_value` stores a Structured Field item. For Inner List,
|
||||
* only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order
|
||||
* to read the items contained in an inner list, call
|
||||
* `sf_parser_inner_list`.
|
||||
* :type:`sfparse_value` stores a Structured Field item. For Inner
|
||||
* List, only type is set to
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
|
||||
* items contained in an inner list, call `sfparse_parser_inner_list`.
|
||||
*/
|
||||
typedef struct sf_value {
|
||||
typedef struct sfparse_value {
|
||||
/**
|
||||
* :member:`type` is the type of the value contained in this
|
||||
* particular object.
|
||||
*/
|
||||
sf_type type;
|
||||
sfparse_type type;
|
||||
/**
|
||||
* :member:`flags` is bitwise OR of one or more of
|
||||
* :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
|
||||
* :macro:`SFPARSE_VALUE_FLAG_* <SFPARSE_VALUE_FLAG_NONE>`.
|
||||
*/
|
||||
uint32_t flags;
|
||||
/**
|
||||
* @anonunion_start
|
||||
*
|
||||
* @sf_value_value
|
||||
* @sfparse_value_value
|
||||
*/
|
||||
union {
|
||||
/**
|
||||
* :member:`boolean` contains boolean value if :member:`type` ==
|
||||
* :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0
|
||||
* indicates false.
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
|
||||
* and 0 indicates false.
|
||||
*/
|
||||
int boolean;
|
||||
/**
|
||||
* :member:`integer` contains integer value if :member:`type` is
|
||||
* either :enum:`sf_type.SF_TYPE_INTEGER` or
|
||||
* :enum:`sf_type.SF_TYPE_DATE`.
|
||||
* either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
|
||||
*/
|
||||
int64_t integer;
|
||||
/**
|
||||
* :member:`decimal` contains decimal value if :member:`type` ==
|
||||
* :enum:`sf_type.SF_TYPE_DECIMAL`.
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DECIMAL`.
|
||||
*/
|
||||
sf_decimal decimal;
|
||||
sfparse_decimal decimal;
|
||||
/**
|
||||
* :member:`vec` contains sequence of bytes if :member:`type` is
|
||||
* either :enum:`sf_type.SF_TYPE_STRING`,
|
||||
* :enum:`sf_type.SF_TYPE_TOKEN`, or
|
||||
* :enum:`sf_type.SF_TYPE_BYTESEQ`.
|
||||
* either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
|
||||
*
|
||||
* For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
|
||||
* more escaped characters if :member:`flags` has
|
||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the
|
||||
* string, use `sf_unescape`.
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
|
||||
* contains one or more escaped characters if :member:`flags` has
|
||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
|
||||
* the string, use `sfparse_unescape`.
|
||||
*
|
||||
* For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
|
||||
* encoded string. To decode this byte string, use
|
||||
* `sf_base64decode`.
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
|
||||
* contains base64 encoded string. To decode this byte string,
|
||||
* use `sfparse_base64decode`.
|
||||
*
|
||||
* If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
|
||||
* <sf_vec.base>` is guaranteed to be NULL.
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
|
||||
* may contain percent-encoded UTF-8 byte sequences. To decode
|
||||
* it, use `sfparse_pctdecode`.
|
||||
*
|
||||
* If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
|
||||
* <sfparse_vec.base>` is guaranteed to be NULL.
|
||||
*/
|
||||
sf_vec vec;
|
||||
sfparse_vec vec;
|
||||
/**
|
||||
* @anonunion_end
|
||||
*/
|
||||
};
|
||||
} sf_value;
|
||||
} sfparse_value;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sf_parser` is the Structured Field Values parser. Use
|
||||
* `sf_parser_init` to initialize it.
|
||||
* :type:`sfparse_parser` is the Structured Field Values parser. Use
|
||||
* `sfparse_parser_init` to initialize it.
|
||||
*/
|
||||
typedef struct sf_parser {
|
||||
typedef struct sfparse_parser {
|
||||
/* all fields are private */
|
||||
const uint8_t *pos;
|
||||
const uint8_t *end;
|
||||
uint32_t state;
|
||||
} sf_parser;
|
||||
} sfparse_parser;
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_init` initializes |sfp| with the given buffer pointed by
|
||||
* |data| of length |datalen|.
|
||||
* `sfparse_parser_init` initializes |sfp| with the given data encoded
|
||||
* in Structured Field Values pointed by |data| of length |datalen|.
|
||||
*/
|
||||
void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
|
||||
void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
|
||||
size_t datalen);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_param` reads a parameter. If this function returns 0,
|
||||
* it stores parameter key and value in |dest_key| and |dest_value|
|
||||
* `sfparse_parser_param` reads a parameter. If this function returns
|
||||
* 0, it stores parameter key and value in |dest_key| and |dest_value|
|
||||
* respectively, if they are not NULL.
|
||||
*
|
||||
* This function does no effort to find duplicated keys. Same key may
|
||||
* be reported more than once.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all parameters have
|
||||
* read, and caller can continue to read rest of the values. If it
|
||||
* returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
|
||||
* have read, and caller can continue to read rest of the values. If
|
||||
* it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
|
||||
* while parsing field value.
|
||||
*/
|
||||
int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||
int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||
sfparse_value *dest_value);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_dict` reads the next dictionary key and value pair. If
|
||||
* this function returns 0, it stores the key and value in |dest_key|
|
||||
* and |dest_value| respectively, if they are not NULL.
|
||||
* `sfparse_parser_dict` reads the next dictionary key and value pair.
|
||||
* If this function returns 0, it stores the key and value in
|
||||
* |dest_key| and |dest_value| respectively, if they are not NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the pair by
|
||||
* calling `sf_parser_param`.
|
||||
* calling `sfparse_parser_param`.
|
||||
*
|
||||
* This function does no effort to find duplicated keys. Same key may
|
||||
* be reported more than once.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all key and value
|
||||
* pairs have been read, and there is nothing left to read.
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
|
||||
* value pairs have been read, and there is nothing left to read.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* All values in the dictionary have read.
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||
int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||
sfparse_value *dest_value);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_list` reads the next list item. If this function
|
||||
* `sfparse_parser_list` reads the next list item. If this function
|
||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sf_parser_param`.
|
||||
* calling `sfparse_parser_param`.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in the
|
||||
* list have been read, and there is nothing left to read.
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||
* the list have been read, and there is nothing left to read.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* All values in the list have read.
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sf_parser_list(sf_parser *sfp, sf_value *dest);
|
||||
int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_item` reads a single item. If this function returns 0,
|
||||
* it stores the item in |dest| if it is not NULL.
|
||||
* `sfparse_parser_item` reads a single item. If this function
|
||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||
*
|
||||
* This function is only used for the field value that consists of a
|
||||
* single item.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sf_parser_param`.
|
||||
* calling `sfparse_parser_param`.
|
||||
*
|
||||
* Caller should call this function again to make sure that there is
|
||||
* nothing left to read. If this 2nd function call returns
|
||||
* :macro:`SF_ERR_EOF`, all data have been processed successfully.
|
||||
* :macro:`SFPARSE_ERR_EOF`, all data have been processed
|
||||
* successfully.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* There is nothing left to read.
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sf_parser_item(sf_parser *sfp, sf_value *dest);
|
||||
int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_parser_inner_list` reads the next inner list item. If this
|
||||
* function returns 0, it stores the item in |dest| if it is not NULL.
|
||||
* `sfparse_parser_inner_list` reads the next inner list item. If
|
||||
* this function returns 0, it stores the item in |dest| if it is not
|
||||
* NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sf_parser_param`.
|
||||
* calling `sfparse_parser_param`.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in this
|
||||
* inner list have been read, and caller can optionally read
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||
* this inner list have been read, and caller can optionally read
|
||||
* parameters attached to this inner list by calling
|
||||
* `sf_parser_param`. Then caller can continue to read rest of the
|
||||
* values.
|
||||
* `sfparse_parser_param`. Then caller can continue to read rest of
|
||||
* the values.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* All values in the inner list have read.
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
|
||||
int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
|
||||
* |src| should be the pointer to :member:`sf_value.vec` of type
|
||||
* :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
|
||||
* `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
|
||||
* `sf_parser_param`, otherwise the behavior is undefined.
|
||||
* `sfparse_unescape` copies |src| to |dest| by removing escapes
|
||||
* (``\``). |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||
* has sufficient space to store the unescaped string.
|
||||
*
|
||||
* If there is no escape character in |src|, |*src| is assigned to
|
||||
* |*dest|. This includes the case that :member:`src->len
|
||||
* <sf_vec.len>` == 0.
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the unescaped string. The
|
||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||
*
|
||||
* This function sets the length of unescaped string to
|
||||
* :member:`dest->len <sf_vec.len>`.
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
*/
|
||||
void sf_unescape(sf_vec *dest, const sf_vec *src);
|
||||
void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sf_base64decode` decodes Base64 encoded string |src| and writes
|
||||
* the result into |dest|. |src| should be the pointer to
|
||||
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
|
||||
* produced by either `sf_parser_dict`, `sf_parser_list`,
|
||||
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
|
||||
* otherwise the behavior is undefined.
|
||||
* `sfparse_base64decode` decodes Base64 encoded string |src| and
|
||||
* writes the result into |dest|. |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||
* has sufficient space to store the decoded byte string.
|
||||
*
|
||||
* If :member:`src->len <sf_vec.len>` == 0, |*src| is assigned to
|
||||
* |*dest|.
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the decoded byte string.
|
||||
*
|
||||
* This function sets the length of decoded byte string to
|
||||
* :member:`dest->len <sf_vec.len>`.
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
*/
|
||||
void sf_base64decode(sf_vec *dest, const sf_vec *src);
|
||||
void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_pctdecode` decodes percent-encoded string |src| and writes
|
||||
* the result into |dest|. |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the decoded byte string. The
|
||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||
*
|
||||
* This function sets the length of decoded byte string to
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
*/
|
||||
void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
||||
#endif /* SFPARSE_H */
|
||||
#endif /* !defined(SFPARSE_H) */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue