From 83336b28a54315ef72efef2cca65fd81b276959e Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sat, 7 Jun 2025 05:30:45 -0400 Subject: [PATCH 01/10] deps: update nghttp2 to 1.65.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/57269 Reviewed-By: Michaël Zasso Reviewed-By: Rafael Gonzaga Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel (cherry picked from commit d74daeab96035bdb4d78067845370737f6869f65) --- deps/nghttp2/lib/includes/nghttp2/nghttp2.h | 241 +--- .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- deps/nghttp2/lib/nghttp2_hd.c | 11 + deps/nghttp2/lib/nghttp2_http.c | 17 +- deps/nghttp2/lib/nghttp2_session.c | 707 +--------- deps/nghttp2/lib/nghttp2_session.h | 120 +- deps/nghttp2/lib/nghttp2_stream.c | 847 +----------- deps/nghttp2/lib/nghttp2_stream.h | 157 +-- deps/nghttp2/lib/nghttp2_submit.c | 155 +-- deps/nghttp2/lib/sfparse.c | 1140 +++++++++++++---- deps/nghttp2/lib/sfparse.h | 313 +++-- 11 files changed, 1220 insertions(+), 2492 deletions(-) diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h index 2ef49b8d68f4ed..3d91af55109cc8 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -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. - * - * 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: + * prioritization scheme. * - * :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. - * - * 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: + * prioritization scheme. * - * :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. - * - * 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: + * prioritization scheme. * - * :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); diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index 827c99896846e3..1302eb57bc58d8 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.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 */ diff --git a/deps/nghttp2/lib/nghttp2_hd.c b/deps/nghttp2/lib/nghttp2_hd.c index 55fc2cc6bfea3d..ad85eed1e13e7b 100644 --- a/deps/nghttp2/lib/nghttp2_hd.c +++ b/deps/nghttp2/lib/nghttp2_hd.c @@ -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; diff --git a/deps/nghttp2/lib/nghttp2_http.c b/deps/nghttp2/lib/nghttp2_http.c index f222fe5e3fbe3c..60a0b01e66c1c8 100644 --- a/deps/nghttp2/lib/nghttp2_http.c +++ b/deps/nghttp2/lib/nghttp2_http.c @@ -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; diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index df33a89efdc1d3..f5bda333f83d15 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -41,6 +41,8 @@ #include "nghttp2_debug.h" #include "nghttp2_submit.h" +nghttp2_stream root; + /* * Returns non-zero if the number of outgoing opened streams is larger * than or equal to @@ -146,11 +148,6 @@ static int session_detect_idle_stream(nghttp2_session *session, return 0; } -static int session_no_rfc7540_pri_no_fallback(nghttp2_session *session) { - return session->pending_no_rfc7540_priorities == 1 && - !session->fallback_rfc7540_priorities; -} - static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) { return (ext_types[type / 8] & (1 << (type & 0x7))) > 0; } @@ -458,10 +455,6 @@ static int session_new(nghttp2_session **session_ptr, /* next_stream_id is initialized in either nghttp2_session_client_new2 or nghttp2_session_server_new2 */ - nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE, - NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL, - mem); - (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; (*session_ptr)->recv_window_size = 0; (*session_ptr)->consumed_size = 0; @@ -548,11 +541,6 @@ static int session_new(nghttp2_session **session_ptr, max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size; } - if ((option->opt_set_mask & NGHTTP2_OPT_NO_CLOSED_STREAMS) && - option->no_closed_streams) { - (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS; - } - if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) { (*session_ptr)->max_outbound_ack = option->max_outbound_ack; } @@ -562,13 +550,6 @@ static int session_new(nghttp2_session **session_ptr, (*session_ptr)->max_settings = option->max_settings; } - if ((option->opt_set_mask & - NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES) && - option->server_fallback_rfc7540_priorities) { - (*session_ptr)->opt_flags |= - NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES; - } - if ((option->opt_set_mask & NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) && option->no_rfc9113_leading_and_trailing_ws_validation) { @@ -810,7 +791,6 @@ void nghttp2_session_del(nghttp2_session *session) { for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) { nghttp2_pq_free(&session->sched[i].ob_data); } - nghttp2_stream_free(&session->root); /* Have to free streams first, so that we can check stream->item->queued */ @@ -829,82 +809,6 @@ void nghttp2_session_del(nghttp2_session *session) { nghttp2_mem_free(mem, session); } -int nghttp2_session_reprioritize_stream( - nghttp2_session *session, nghttp2_stream *stream, - const nghttp2_priority_spec *pri_spec_in) { - int rv; - nghttp2_stream *dep_stream = NULL; - nghttp2_priority_spec pri_spec_default; - const nghttp2_priority_spec *pri_spec = pri_spec_in; - - assert((!session->server && session->pending_no_rfc7540_priorities != 1) || - (session->server && !session_no_rfc7540_pri_no_fallback(session))); - assert(pri_spec->stream_id != stream->stream_id); - - if (!nghttp2_stream_in_dep_tree(stream)) { - return 0; - } - - if (pri_spec->stream_id != 0) { - dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - - if (!dep_stream && - session_detect_idle_stream(session, pri_spec->stream_id)) { - nghttp2_priority_spec_default_init(&pri_spec_default); - - dep_stream = nghttp2_session_open_stream( - session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_IDLE, NULL); - - if (dep_stream == NULL) { - return NGHTTP2_ERR_NOMEM; - } - } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { - nghttp2_priority_spec_default_init(&pri_spec_default); - pri_spec = &pri_spec_default; - } - } - - if (pri_spec->stream_id == 0) { - dep_stream = &session->root; - } else if (nghttp2_stream_dep_find_ancestor(dep_stream, stream)) { - DEBUGF("stream: cycle detected, dep_stream(%p)=%d stream(%p)=%d\n", - dep_stream, dep_stream->stream_id, stream, stream->stream_id); - - nghttp2_stream_dep_remove_subtree(dep_stream); - rv = nghttp2_stream_dep_add_subtree(stream->dep_prev, dep_stream); - if (rv != 0) { - return rv; - } - } - - assert(dep_stream); - - if (dep_stream == stream->dep_prev && !pri_spec->exclusive) { - /* This is minor optimization when just weight is changed. */ - nghttp2_stream_change_weight(stream, pri_spec->weight); - - return 0; - } - - nghttp2_stream_dep_remove_subtree(stream); - - /* We have to update weight after removing stream from tree */ - stream->weight = pri_spec->weight; - - if (pri_spec->exclusive) { - rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream); - } else { - rv = nghttp2_stream_dep_add_subtree(dep_stream, stream); - } - - if (rv != 0) { - return rv; - } - - return 0; -} - static uint64_t pq_get_first_cycle(nghttp2_pq *pq) { nghttp2_stream *stream; @@ -923,7 +827,6 @@ static int session_ob_data_push(nghttp2_session *session, int inc; nghttp2_pq *pq; - assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES); assert(stream->queued == 0); urgency = nghttp2_extpri_uint8_urgency(stream->extpri); @@ -952,7 +855,6 @@ static void session_ob_data_remove(nghttp2_session *session, nghttp2_stream *stream) { uint32_t urgency; - assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES); assert(stream->queued == 1); urgency = nghttp2_extpri_uint8_urgency(stream->extpri); @@ -969,14 +871,7 @@ static int session_attach_stream_item(nghttp2_session *session, nghttp2_outbound_item *item) { int rv; - rv = nghttp2_stream_attach_item(stream, item); - if (rv != 0) { - return rv; - } - - if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) { - return 0; - } + nghttp2_stream_attach_item(stream, item); rv = session_ob_data_push(session, stream); if (rv != 0) { @@ -992,8 +887,7 @@ static void session_detach_stream_item(nghttp2_session *session, nghttp2_stream *stream) { nghttp2_stream_detach_item(stream); - if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || - !stream->queued) { + if (!stream->queued) { return; } @@ -1004,8 +898,7 @@ static void session_defer_stream_item(nghttp2_session *session, nghttp2_stream *stream, uint8_t flags) { nghttp2_stream_defer_item(stream, flags); - if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || - !stream->queued) { + if (!stream->queued) { return; } @@ -1015,15 +908,9 @@ static void session_defer_stream_item(nghttp2_session *session, static int session_resume_deferred_stream_item(nghttp2_session *session, nghttp2_stream *stream, uint8_t flags) { - int rv; - - rv = nghttp2_stream_resume_deferred_item(stream, flags); - if (rv != 0) { - return rv; - } + nghttp2_stream_resume_deferred_item(stream, flags); - if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || - (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL)) { + if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) { return 0; } @@ -1168,7 +1055,6 @@ int nghttp2_session_add_item(nghttp2_session *session, return 0; case NGHTTP2_PUSH_PROMISE: { nghttp2_headers_aux_data *aux_data; - nghttp2_priority_spec pri_spec; aux_data = &item->aux_data.headers; @@ -1176,20 +1062,13 @@ int nghttp2_session_add_item(nghttp2_session *session, return NGHTTP2_ERR_STREAM_CLOSED; } - nghttp2_priority_spec_init(&pri_spec, stream->stream_id, - NGHTTP2_DEFAULT_WEIGHT, 0); - if (!nghttp2_session_open_stream( session, frame->push_promise.promised_stream_id, - NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_RESERVED, + NGHTTP2_STREAM_FLAG_NONE, NGHTTP2_STREAM_RESERVED, aux_data->stream_user_data)) { return NGHTTP2_ERR_NOMEM; } - /* We don't have to call nghttp2_session_adjust_closed_stream() - here, since stream->stream_id is local stream_id, and it does - not affect closed stream count. */ - nghttp2_outbound_queue_push(&session->ob_reg, item); item->queued = 1; @@ -1290,15 +1169,11 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, int32_t stream_id, uint8_t flags, - nghttp2_priority_spec *pri_spec_in, nghttp2_stream_state initial_state, void *stream_user_data) { int rv; nghttp2_stream *stream; - nghttp2_stream *dep_stream = NULL; int stream_alloc = 0; - nghttp2_priority_spec pri_spec_default; - nghttp2_priority_spec *pri_spec = pri_spec_in; nghttp2_mem *mem; mem = &session->mem; @@ -1311,23 +1186,9 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, if (stream) { assert(stream->state == NGHTTP2_STREAM_IDLE); - assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || - nghttp2_stream_in_dep_tree(stream)); - - nghttp2_session_detach_idle_stream(session, stream); - - if (nghttp2_stream_in_dep_tree(stream)) { - assert(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)); - - rv = nghttp2_stream_dep_remove(stream); - if (rv != 0) { - return NULL; - } + assert(initial_state != NGHTTP2_STREAM_IDLE); - if (session_no_rfc7540_pri_no_fallback(session)) { - stream->flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES; - } - } + --session->num_idle_streams; } else { stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream)); if (stream == NULL) { @@ -1337,69 +1198,16 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, stream_alloc = 1; } - if (session_no_rfc7540_pri_no_fallback(session) || - session->remote_settings.no_rfc7540_priorities == 1) { - /* For client which has not received server - SETTINGS_NO_RFC7540_PRIORITIES = 1, send a priority signal - opportunistically. */ - if (session->server || - session->remote_settings.no_rfc7540_priorities == 1) { - nghttp2_priority_spec_default_init(&pri_spec_default); - pri_spec = &pri_spec_default; - } - - if (session->pending_no_rfc7540_priorities == 1) { - flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES; - } - } else if (pri_spec->stream_id != 0) { - dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - - if (!dep_stream && - session_detect_idle_stream(session, pri_spec->stream_id)) { - /* Depends on idle stream, which does not exist in memory. - Assign default priority for it. */ - nghttp2_priority_spec_default_init(&pri_spec_default); - - dep_stream = nghttp2_session_open_stream( - session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_IDLE, NULL); - - if (dep_stream == NULL) { - if (stream_alloc) { - nghttp2_mem_free(mem, stream); - } - - return NULL; - } - } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { - /* If dep_stream is not part of dependency tree, stream will get - default priority. This handles the case when - pri_spec->stream_id == stream_id. This happens because we - don't check pri_spec->stream_id against new stream ID in - nghttp2_submit_request. This also handles the case when idle - stream created by PRIORITY frame was opened. Somehow we - first remove the idle stream from dependency tree. This is - done to simplify code base, but ideally we should retain old - dependency. But I'm not sure this adds values. */ - nghttp2_priority_spec_default_init(&pri_spec_default); - pri_spec = &pri_spec_default; - } - } - if (initial_state == NGHTTP2_STREAM_RESERVED) { flags |= NGHTTP2_STREAM_FLAG_PUSH; } if (stream_alloc) { nghttp2_stream_init(stream, stream_id, flags, initial_state, - pri_spec->weight, (int32_t)session->remote_settings.initial_window_size, (int32_t)session->local_settings.initial_window_size, - stream_user_data, mem); - - if (session_no_rfc7540_pri_no_fallback(session)) { - stream->seq = session->stream_seq++; - } + stream_user_data); + stream->seq = session->stream_seq++; rv = nghttp2_map_insert(&session->streams, stream_id, stream); if (rv != 0) { @@ -1410,7 +1218,6 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, } else { stream->flags = flags; stream->state = initial_state; - stream->weight = pri_spec->weight; stream->stream_user_data = stream_user_data; } @@ -1428,9 +1235,7 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, limit. That is one of the DOS vector. */ break; case NGHTTP2_STREAM_IDLE: - /* Idle stream does not count toward the concurrent streams limit. - This is used as anchor node in dependency tree. */ - nghttp2_session_keep_idle_stream(session, stream); + ++session->num_idle_streams; break; default: if (nghttp2_session_is_my_stream_id(session, stream_id)) { @@ -1440,31 +1245,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, } } - if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) { - return stream; - } - - if (pri_spec->stream_id == 0) { - dep_stream = &session->root; - } - - assert(dep_stream); - - if (pri_spec->exclusive) { - rv = nghttp2_stream_dep_insert(dep_stream, stream); - if (rv != 0) { - return NULL; - } - } else { - nghttp2_stream_dep_add(dep_stream, stream); - } - return stream; } int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, uint32_t error_code) { - int rv; nghttp2_stream *stream; nghttp2_mem *mem; int is_my_stream_id; @@ -1528,207 +1313,26 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, /* Closes both directions just in case they are not closed yet */ stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED; - if (session->pending_no_rfc7540_priorities == 1) { - return nghttp2_session_destroy_stream(session, stream); - } - - if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 && - session->server && !is_my_stream_id && - nghttp2_stream_in_dep_tree(stream)) { - /* On server side, retain stream at most MAX_CONCURRENT_STREAMS - combined with the current active incoming streams to make - dependency tree work better. */ - nghttp2_session_keep_closed_stream(session, stream); - } else { - rv = nghttp2_session_destroy_stream(session, stream); - if (rv != 0) { - return rv; - } - } + nghttp2_session_destroy_stream(session, stream); return 0; } -int nghttp2_session_destroy_stream(nghttp2_session *session, - nghttp2_stream *stream) { +void nghttp2_session_destroy_stream(nghttp2_session *session, + nghttp2_stream *stream) { nghttp2_mem *mem; - int rv; DEBUGF("stream: destroy closed stream(%p)=%d\n", stream, stream->stream_id); mem = &session->mem; - if (nghttp2_stream_in_dep_tree(stream)) { - rv = nghttp2_stream_dep_remove(stream); - if (rv != 0) { - return rv; - } - } - - if (stream->queued && - (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) { + if (stream->queued) { session_ob_data_remove(session, stream); } nghttp2_map_remove(&session->streams, stream->stream_id); nghttp2_stream_free(stream); nghttp2_mem_free(mem, stream); - - return 0; -} - -void nghttp2_session_keep_closed_stream(nghttp2_session *session, - nghttp2_stream *stream) { - DEBUGF("stream: keep closed stream(%p)=%d, state=%d\n", stream, - stream->stream_id, stream->state); - - if (session->closed_stream_tail) { - session->closed_stream_tail->closed_next = stream; - stream->closed_prev = session->closed_stream_tail; - } else { - session->closed_stream_head = stream; - } - session->closed_stream_tail = stream; - - ++session->num_closed_streams; -} - -void nghttp2_session_keep_idle_stream(nghttp2_session *session, - nghttp2_stream *stream) { - DEBUGF("stream: keep idle stream(%p)=%d, state=%d\n", stream, - stream->stream_id, stream->state); - - if (session->idle_stream_tail) { - session->idle_stream_tail->closed_next = stream; - stream->closed_prev = session->idle_stream_tail; - } else { - session->idle_stream_head = stream; - } - session->idle_stream_tail = stream; - - ++session->num_idle_streams; -} - -void nghttp2_session_detach_idle_stream(nghttp2_session *session, - nghttp2_stream *stream) { - nghttp2_stream *prev_stream, *next_stream; - - DEBUGF("stream: detach idle stream(%p)=%d, state=%d\n", stream, - stream->stream_id, stream->state); - - prev_stream = stream->closed_prev; - next_stream = stream->closed_next; - - if (prev_stream) { - prev_stream->closed_next = next_stream; - } else { - session->idle_stream_head = next_stream; - } - - if (next_stream) { - next_stream->closed_prev = prev_stream; - } else { - session->idle_stream_tail = prev_stream; - } - - stream->closed_prev = NULL; - stream->closed_next = NULL; - - --session->num_idle_streams; -} - -int nghttp2_session_adjust_closed_stream(nghttp2_session *session) { - size_t num_stream_max; - int rv; - - if (session->local_settings.max_concurrent_streams == - NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS) { - num_stream_max = session->pending_local_max_concurrent_stream; - } else { - num_stream_max = session->local_settings.max_concurrent_streams; - } - - DEBUGF("stream: adjusting kept closed streams num_closed_streams=%zu, " - "num_incoming_streams=%zu, max_concurrent_streams=%zu\n", - session->num_closed_streams, session->num_incoming_streams, - num_stream_max); - - while (session->num_closed_streams > 0 && - session->num_closed_streams + session->num_incoming_streams > - num_stream_max) { - nghttp2_stream *head_stream; - nghttp2_stream *next; - - head_stream = session->closed_stream_head; - - assert(head_stream); - - next = head_stream->closed_next; - - rv = nghttp2_session_destroy_stream(session, head_stream); - if (rv != 0) { - return rv; - } - - /* head_stream is now freed */ - - session->closed_stream_head = next; - - if (session->closed_stream_head) { - session->closed_stream_head->closed_prev = NULL; - } else { - session->closed_stream_tail = NULL; - } - - --session->num_closed_streams; - } - - return 0; -} - -int nghttp2_session_adjust_idle_stream(nghttp2_session *session) { - size_t max; - int rv; - - /* Make minimum number of idle streams 16, and maximum 100, which - are arbitrary chosen numbers. */ - max = nghttp2_min_uint32( - 100, - nghttp2_max_uint32( - 16, nghttp2_min_uint32(session->local_settings.max_concurrent_streams, - session->pending_local_max_concurrent_stream))); - - DEBUGF("stream: adjusting kept idle streams num_idle_streams=%zu, max=%zu\n", - session->num_idle_streams, max); - - while (session->num_idle_streams > max) { - nghttp2_stream *head; - nghttp2_stream *next; - - head = session->idle_stream_head; - assert(head); - - next = head->closed_next; - - rv = nghttp2_session_destroy_stream(session, head); - if (rv != 0) { - return rv; - } - - /* head is now destroyed */ - - session->idle_stream_head = next; - - if (session->idle_stream_head) { - session->idle_stream_head->closed_prev = NULL; - } else { - session->idle_stream_tail = NULL; - } - - --session->num_idle_streams; - } - - return 0; } /* @@ -2411,16 +2015,12 @@ static int session_prep_frame(nghttp2_session *session, stream = nghttp2_session_open_stream( session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, - &frame->headers.pri_spec, NGHTTP2_STREAM_INITIAL, - aux_data->stream_user_data); + NGHTTP2_STREAM_INITIAL, aux_data->stream_user_data); if (stream == NULL) { return NGHTTP2_ERR_NOMEM; } - /* We don't call nghttp2_session_adjust_closed_stream() here, - since we don't keep closed stream in client side */ - rv = session_predicate_request_headers_send(session, item); if (rv != 0) { return rv; @@ -2662,8 +2262,6 @@ static int session_prep_frame(nghttp2_session *session, nghttp2_outbound_item * nghttp2_session_get_next_ob_item(nghttp2_session *session) { - nghttp2_outbound_item *item; - if (nghttp2_outbound_queue_top(&session->ob_urgent)) { return nghttp2_outbound_queue_top(&session->ob_urgent); } @@ -2679,11 +2277,6 @@ nghttp2_session_get_next_ob_item(nghttp2_session *session) { } if (session->remote_window_size > 0) { - item = nghttp2_stream_next_outbound_item(&session->root); - if (item) { - return item; - } - return session_sched_get_next_outbound_item(session); } @@ -2718,11 +2311,6 @@ nghttp2_session_pop_next_ob_item(nghttp2_session *session) { } if (session->remote_window_size > 0) { - item = nghttp2_stream_next_outbound_item(&session->root); - if (item) { - return item; - } - return session_sched_get_next_outbound_item(session); } @@ -2781,7 +2369,6 @@ static int find_stream_on_goaway_func(void *entry, void *ptr) { nghttp2_session_close_stream() inside nghttp2_map_each(). Reuse closed_next member.. bad choice? */ assert(stream->closed_next == NULL); - assert(stream->closed_prev == NULL); if (arg->head) { stream->closed_next = arg->head; @@ -2837,11 +2424,6 @@ static void session_reschedule_stream(nghttp2_session *session, nghttp2_stream *stream) { stream->last_writelen = stream->item->frame.hd.length; - if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) { - nghttp2_stream_reschedule(stream); - return; - } - if (!session->server) { return; } @@ -3020,37 +2602,6 @@ static int session_after_frame_sent1(nghttp2_session *session) { } } case NGHTTP2_PRIORITY: - if (session->server || session->pending_no_rfc7540_priorities == 1) { - return 0; - } - - stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); - - if (!stream) { - if (!session_detect_idle_stream(session, frame->hd.stream_id)) { - return 0; - } - - stream = nghttp2_session_open_stream( - session, frame->hd.stream_id, NGHTTP2_FLAG_NONE, - &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL); - if (!stream) { - return NGHTTP2_ERR_NOMEM; - } - } else { - rv = nghttp2_session_reprioritize_stream(session, stream, - &frame->priority.pri_spec); - if (nghttp2_is_fatal(rv)) { - return rv; - } - } - - rv = nghttp2_session_adjust_idle_stream(session); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - return 0; case NGHTTP2_RST_STREAM: rv = nghttp2_session_close_stream(session, frame->hd.stream_id, @@ -3239,14 +2790,6 @@ static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session, aob = &session->aob; framebufs = &aob->framebufs; - /* We may have idle streams more than we expect (e.g., - nghttp2_session_change_stream_priority() or - nghttp2_session_create_idle_stream()). Adjust them here. */ - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - for (;;) { switch (aob->state) { case NGHTTP2_OB_POP_ITEM: { @@ -4064,7 +3607,6 @@ static int session_end_stream_headers_received(nghttp2_session *session, if (session->server && session_enforce_http_messaging(session) && frame->headers.cat == NGHTTP2_HCAT_REQUEST && - (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) && !(stream->flags & NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES) && (stream->http_flags & NGHTTP2_HTTP_FLAG_PRIORITY)) { rv = session_update_stream_priority(session, stream, stream->http_extpri); @@ -4253,18 +3795,13 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session, NGHTTP2_ERR_REFUSED_STREAM); } - stream = nghttp2_session_open_stream( - session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, - &frame->headers.pri_spec, NGHTTP2_STREAM_OPENING, NULL); + stream = nghttp2_session_open_stream(session, frame->hd.stream_id, + NGHTTP2_STREAM_FLAG_NONE, + NGHTTP2_STREAM_OPENING, NULL); if (!stream) { return NGHTTP2_ERR_NOMEM; } - rv = nghttp2_session_adjust_closed_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - session->last_proc_stream_id = session->last_recv_stream_id; rv = session_call_on_begin_headers(session, frame); @@ -4425,77 +3962,6 @@ static int session_process_headers_frame(nghttp2_session *session) { return nghttp2_session_on_headers_received(session, frame, stream); } -int nghttp2_session_on_priority_received(nghttp2_session *session, - nghttp2_frame *frame) { - int rv; - nghttp2_stream *stream; - - assert(!session_no_rfc7540_pri_no_fallback(session)); - - if (frame->hd.stream_id == 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "PRIORITY: stream_id == 0"); - } - - if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) { - return nghttp2_session_terminate_session_with_reason( - session, NGHTTP2_PROTOCOL_ERROR, "depend on itself"); - } - - if (!session->server) { - /* Re-prioritization works only in server */ - return session_call_on_frame_received(session, frame); - } - - stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); - - if (!stream) { - /* PRIORITY against idle stream can create anchor node in - dependency tree. */ - if (!session_detect_idle_stream(session, frame->hd.stream_id)) { - return 0; - } - - stream = nghttp2_session_open_stream( - session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, - &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL); - - if (stream == NULL) { - return NGHTTP2_ERR_NOMEM; - } - - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - } else { - rv = nghttp2_session_reprioritize_stream(session, stream, - &frame->priority.pri_spec); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - } - - return session_call_on_frame_received(session, frame); -} - -static int session_process_priority_frame(nghttp2_session *session) { - nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_frame *frame = &iframe->frame; - - assert(!session_no_rfc7540_pri_no_fallback(session)); - - nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos); - - return nghttp2_session_on_priority_received(session, frame); -} - static int session_update_stream_reset_ratelim(nghttp2_session *session) { if (!session->server || (session->goaway_flags & NGHTTP2_GOAWAY_SUBMITTED)) { return 0; @@ -4934,12 +4400,6 @@ int nghttp2_session_on_settings_received(nghttp2_session *session, if (session->remote_settings.no_rfc7540_priorities == UINT32_MAX) { session->remote_settings.no_rfc7540_priorities = 0; - - if (session->server && session->pending_no_rfc7540_priorities && - (session->opt_flags & - NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES)) { - session->fallback_rfc7540_priorities = 1; - } } if (!noack && !session_is_closing(session)) { @@ -5000,7 +4460,6 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, int rv; nghttp2_stream *stream; nghttp2_stream *promised_stream; - nghttp2_priority_spec pri_spec; if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( @@ -5058,20 +4517,14 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session, frame, NGHTTP2_ERR_STREAM_CLOSED, "PUSH_PROMISE: stream closed"); } - nghttp2_priority_spec_init(&pri_spec, stream->stream_id, - NGHTTP2_DEFAULT_WEIGHT, 0); - promised_stream = nghttp2_session_open_stream( session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec, NGHTTP2_STREAM_RESERVED, NULL); + NGHTTP2_STREAM_RESERVED, NULL); if (!promised_stream) { return NGHTTP2_ERR_NOMEM; } - /* We don't call nghttp2_session_adjust_closed_stream(), since we - don't keep closed stream in client side */ - session->last_proc_stream_id = session->last_recv_stream_id; rv = session_call_on_begin_headers(session, frame); if (rv != 0) { @@ -5292,7 +4745,6 @@ int nghttp2_session_on_priority_update_received(nghttp2_session *session, nghttp2_frame *frame) { nghttp2_ext_priority_update *priority_update; nghttp2_stream *stream; - nghttp2_priority_spec pri_spec; nghttp2_extpri extpri; int rv; @@ -5330,10 +4782,9 @@ int nghttp2_session_on_priority_update_received(nghttp2_session *session, "PRIORITY_UPDATE: max concurrent streams exceeded"); } - nghttp2_priority_spec_default_init(&pri_spec); - stream = nghttp2_session_open_stream(session, priority_update->stream_id, - NGHTTP2_FLAG_NONE, &pri_spec, - NGHTTP2_STREAM_IDLE, NULL); + stream = + nghttp2_session_open_stream(session, priority_update->stream_id, + NGHTTP2_FLAG_NONE, NGHTTP2_STREAM_IDLE, NULL); if (!stream) { return NGHTTP2_ERR_NOMEM; } @@ -5869,14 +5320,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, mem = &session->mem; - /* We may have idle streams more than we expect (e.g., - nghttp2_session_change_stream_priority() or - nghttp2_session_create_idle_stream()). Adjust them here. */ - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - if (!nghttp2_session_want_read(session)) { return (nghttp2_ssize)inlen; } @@ -6392,8 +5835,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; } - if (!session_no_rfc7540_pri_no_fallback(session) || - iframe->payloadleft > sizeof(iframe->raw_sbuf)) { + if (iframe->payloadleft > sizeof(iframe->raw_sbuf)) { busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -6510,18 +5952,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; case NGHTTP2_PRIORITY: - if (!session_no_rfc7540_pri_no_fallback(session) && - session->remote_settings.no_rfc7540_priorities != 1) { - rv = session_process_priority_frame(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - } - session_inbound_frame_reset(session); break; @@ -7404,9 +6834,7 @@ int nghttp2_session_want_write(nghttp2_session *session) { */ return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) || nghttp2_outbound_queue_top(&session->ob_reg) || - ((!nghttp2_pq_empty(&session->root.obq) || - !session_sched_empty(session)) && - session->remote_window_size > 0) || + (!session_sched_empty(session) && session->remote_window_size > 0) || (nghttp2_outbound_queue_top(&session->ob_syn) && !session_is_outgoing_concurrent_streams_max(session)); } @@ -8046,7 +7474,6 @@ static int nghttp2_session_upgrade_internal(nghttp2_session *session, nghttp2_settings_entry *iv; size_t niv; int rv; - nghttp2_priority_spec pri_spec; nghttp2_mem *mem; mem = &session->mem; @@ -8083,18 +7510,13 @@ static int nghttp2_session_upgrade_internal(nghttp2_session *session, return rv; } - nghttp2_priority_spec_default_init(&pri_spec); - stream = nghttp2_session_open_stream( - session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENING, + session, 1, NGHTTP2_STREAM_FLAG_NONE, NGHTTP2_STREAM_OPENING, session->server ? NULL : stream_user_data); if (stream == NULL) { return NGHTTP2_ERR_NOMEM; } - /* We don't call nghttp2_session_adjust_closed_stream(), since this - should be the first stream open. */ - if (session->server) { nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); session->last_recv_stream_id = 1; @@ -8293,14 +7715,16 @@ int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id) { if (stream_id == 0) { - return &session->root; + return &root; } return nghttp2_session_get_stream_raw(session, stream_id); } nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) { - return &session->root; + (void)session; + + return &root; } int nghttp2_session_check_server_session(nghttp2_session *session) { @@ -8310,75 +7734,20 @@ int nghttp2_session_check_server_session(nghttp2_session *session) { int nghttp2_session_change_stream_priority( nghttp2_session *session, int32_t stream_id, const nghttp2_priority_spec *pri_spec) { - int rv; - nghttp2_stream *stream; - nghttp2_priority_spec pri_spec_copy; - - if (session->pending_no_rfc7540_priorities == 1) { - return 0; - } - - if (stream_id == 0 || stream_id == pri_spec->stream_id) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - stream = nghttp2_session_get_stream_raw(session, stream_id); - if (!stream) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - pri_spec_copy = *pri_spec; - nghttp2_priority_spec_normalize_weight(&pri_spec_copy); - - rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy); + (void)session; + (void)stream_id; + (void)pri_spec; - if (nghttp2_is_fatal(rv)) { - return rv; - } - - /* We don't intentionally call nghttp2_session_adjust_idle_stream() - so that idle stream created by this function, and existing ones - are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is - called. */ return 0; } int nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, const nghttp2_priority_spec *pri_spec) { - nghttp2_stream *stream; - nghttp2_priority_spec pri_spec_copy; - - if (session->pending_no_rfc7540_priorities == 1) { - return 0; - } - - if (stream_id == 0 || stream_id == pri_spec->stream_id || - !session_detect_idle_stream(session, stream_id)) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - stream = nghttp2_session_get_stream_raw(session, stream_id); - if (stream) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - pri_spec_copy = *pri_spec; - nghttp2_priority_spec_normalize_weight(&pri_spec_copy); - - stream = - nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_copy, NGHTTP2_STREAM_IDLE, NULL); - if (!stream) { - return NGHTTP2_ERR_NOMEM; - } + (void)session; + (void)stream_id; + (void)pri_spec; - /* We don't intentionally call nghttp2_session_adjust_idle_stream() - so that idle stream created by this function, and existing ones - are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is - called. */ return 0; } diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index ef8f7b27d67261..6a54d35fcab7fa 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -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 /* */ 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. diff --git a/deps/nghttp2/lib/nghttp2_stream.c b/deps/nghttp2/lib/nghttp2_stream.c index f2362447903755..afbd7c2d9e0a77 100644 --- a/deps/nghttp2/lib/nghttp2_stream.c +++ b/deps/nghttp2/lib/nghttp2_stream.c @@ -25,45 +25,17 @@ #include "nghttp2_stream.h" #include -#include #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; } -} -nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) { 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) { diff --git a/deps/nghttp2/lib/nghttp2_stream.h b/deps/nghttp2/lib/nghttp2_stream.h index 28add165469d94..e73cd283b1dca4 100644 --- a/deps/nghttp2/lib/nghttp2_stream.h +++ b/deps/nghttp2/lib/nghttp2_stream.h @@ -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 */ diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index 81c1ab7046bc33..d481aebde221fd 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -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 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, 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 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags, 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(pri_spec, dpw); + flags = set_request_flags(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, diff --git a/deps/nghttp2/lib/sfparse.c b/deps/nghttp2/lib/sfparse.c index b5e94cc281533b..cee089d3944d18 100644 --- a/deps/nghttp2/lib/sfparse.c +++ b/deps/nghttp2/lib/sfparse.c @@ -30,38 +30,46 @@ #include #include -#define SF_STATE_DICT 0x08u -#define SF_STATE_LIST 0x10u -#define SF_STATE_ITEM 0x18u +#ifdef __AVX2__ +# include +#endif /* __AVX2__ */ -#define SF_STATE_INNER_LIST 0x04u +#define SFPARSE_STATE_DICT 0x08u +#define SFPARSE_STATE_LIST 0x10u +#define SFPARSE_STATE_ITEM 0x18u -#define SF_STATE_BEFORE 0x00u -#define SF_STATE_BEFORE_PARAMS 0x01u -#define SF_STATE_PARAMS 0x02u -#define SF_STATE_AFTER 0x03u +#define SFPARSE_STATE_INNER_LIST 0x04u -#define SF_STATE_OP_MASK 0x03u +#define SFPARSE_STATE_BEFORE 0x00u +#define SFPARSE_STATE_BEFORE_PARAMS 0x01u +#define SFPARSE_STATE_PARAMS 0x02u +#define SFPARSE_STATE_AFTER 0x03u -#define SF_SET_STATE_AFTER(NAME) (SF_STATE_##NAME | SF_STATE_AFTER) -#define SF_SET_STATE_BEFORE_PARAMS(NAME) \ - (SF_STATE_##NAME | SF_STATE_BEFORE_PARAMS) -#define SF_SET_STATE_INNER_LIST_BEFORE(NAME) \ - (SF_STATE_##NAME | SF_STATE_INNER_LIST | SF_STATE_BEFORE) +#define SFPARSE_STATE_OP_MASK 0x03u -#define SF_STATE_DICT_AFTER SF_SET_STATE_AFTER(DICT) -#define SF_STATE_DICT_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(DICT) -#define SF_STATE_DICT_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(DICT) +#define SFPARSE_SET_STATE_AFTER(NAME) \ + (SFPARSE_STATE_##NAME | SFPARSE_STATE_AFTER) +#define SFPARSE_SET_STATE_BEFORE_PARAMS(NAME) \ + (SFPARSE_STATE_##NAME | SFPARSE_STATE_BEFORE_PARAMS) +#define SFPARSE_SET_STATE_INNER_LIST_BEFORE(NAME) \ + (SFPARSE_STATE_##NAME | SFPARSE_STATE_INNER_LIST | SFPARSE_STATE_BEFORE) -#define SF_STATE_LIST_AFTER SF_SET_STATE_AFTER(LIST) -#define SF_STATE_LIST_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(LIST) -#define SF_STATE_LIST_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(LIST) +#define SFPARSE_STATE_DICT_AFTER SFPARSE_SET_STATE_AFTER(DICT) +#define SFPARSE_STATE_DICT_BEFORE_PARAMS SFPARSE_SET_STATE_BEFORE_PARAMS(DICT) +#define SFPARSE_STATE_DICT_INNER_LIST_BEFORE \ + SFPARSE_SET_STATE_INNER_LIST_BEFORE(DICT) -#define SF_STATE_ITEM_AFTER SF_SET_STATE_AFTER(ITEM) -#define SF_STATE_ITEM_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(ITEM) -#define SF_STATE_ITEM_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(ITEM) +#define SFPARSE_STATE_LIST_AFTER SFPARSE_SET_STATE_AFTER(LIST) +#define SFPARSE_STATE_LIST_BEFORE_PARAMS SFPARSE_SET_STATE_BEFORE_PARAMS(LIST) +#define SFPARSE_STATE_LIST_INNER_LIST_BEFORE \ + SFPARSE_SET_STATE_INNER_LIST_BEFORE(LIST) -#define SF_STATE_INITIAL 0x00u +#define SFPARSE_STATE_ITEM_AFTER SFPARSE_SET_STATE_AFTER(ITEM) +#define SFPARSE_STATE_ITEM_BEFORE_PARAMS SFPARSE_SET_STATE_BEFORE_PARAMS(ITEM) +#define SFPARSE_STATE_ITEM_INNER_LIST_BEFORE \ + SFPARSE_SET_STATE_INNER_LIST_BEFORE(ITEM) + +#define SFPARSE_STATE_INITIAL 0x00u #define DIGIT_CASES \ case '0': \ @@ -135,6 +143,70 @@ UCALPHA_CASES: \ LCALPHA_CASES +#define TOKEN_CASES \ + case '!': \ + case '#': \ + case '$': \ + case '%': \ + case '&': \ + case '\'': \ + case '*': \ + case '+': \ + case '-': \ + case '.': \ + case '/': \ + DIGIT_CASES: \ + case ':': \ + UCALPHA_CASES: \ + case '^': \ + case '_': \ + case '`': \ + LCALPHA_CASES: \ + case '|': \ + case '~' + +#define LCHEXALPHA_CASES \ + case 'a': \ + case 'b': \ + case 'c': \ + case 'd': \ + case 'e': \ + case 'f' + +#define X00_1F_CASES \ + case 0x00: \ + case 0x01: \ + case 0x02: \ + case 0x03: \ + case 0x04: \ + case 0x05: \ + case 0x06: \ + case 0x07: \ + case 0x08: \ + case 0x09: \ + case 0x0a: \ + case 0x0b: \ + case 0x0c: \ + case 0x0d: \ + case 0x0e: \ + case 0x0f: \ + case 0x10: \ + case 0x11: \ + case 0x12: \ + case 0x13: \ + case 0x14: \ + case 0x15: \ + case 0x16: \ + case 0x17: \ + case 0x18: \ + case 0x19: \ + case 0x1a: \ + case 0x1b: \ + case 0x1c: \ + case 0x1d: \ + case 0x1e: \ + case 0x1f + #define X20_21_CASES \ case ' ': \ case '!' @@ -175,6 +247,137 @@ case '}': \ case '~' +#define X7F_FF_CASES \ + case 0x7f: \ + case 0x80: \ + case 0x81: \ + case 0x82: \ + case 0x83: \ + case 0x84: \ + case 0x85: \ + case 0x86: \ + case 0x87: \ + case 0x88: \ + case 0x89: \ + case 0x8a: \ + case 0x8b: \ + case 0x8c: \ + case 0x8d: \ + case 0x8e: \ + case 0x8f: \ + case 0x90: \ + case 0x91: \ + case 0x92: \ + case 0x93: \ + case 0x94: \ + case 0x95: \ + case 0x96: \ + case 0x97: \ + case 0x98: \ + case 0x99: \ + case 0x9a: \ + case 0x9b: \ + case 0x9c: \ + case 0x9d: \ + case 0x9e: \ + case 0x9f: \ + case 0xa0: \ + case 0xa1: \ + case 0xa2: \ + case 0xa3: \ + case 0xa4: \ + case 0xa5: \ + case 0xa6: \ + case 0xa7: \ + case 0xa8: \ + case 0xa9: \ + case 0xaa: \ + case 0xab: \ + case 0xac: \ + case 0xad: \ + case 0xae: \ + case 0xaf: \ + case 0xb0: \ + case 0xb1: \ + case 0xb2: \ + case 0xb3: \ + case 0xb4: \ + case 0xb5: \ + case 0xb6: \ + case 0xb7: \ + case 0xb8: \ + case 0xb9: \ + case 0xba: \ + case 0xbb: \ + case 0xbc: \ + case 0xbd: \ + case 0xbe: \ + case 0xbf: \ + case 0xc0: \ + case 0xc1: \ + case 0xc2: \ + case 0xc3: \ + case 0xc4: \ + case 0xc5: \ + case 0xc6: \ + case 0xc7: \ + case 0xc8: \ + case 0xc9: \ + case 0xca: \ + case 0xcb: \ + case 0xcc: \ + case 0xcd: \ + case 0xce: \ + case 0xcf: \ + case 0xd0: \ + case 0xd1: \ + case 0xd2: \ + case 0xd3: \ + case 0xd4: \ + case 0xd5: \ + case 0xd6: \ + case 0xd7: \ + case 0xd8: \ + case 0xd9: \ + case 0xda: \ + case 0xdb: \ + case 0xdc: \ + case 0xdd: \ + case 0xde: \ + case 0xdf: \ + case 0xe0: \ + case 0xe1: \ + case 0xe2: \ + case 0xe3: \ + case 0xe4: \ + case 0xe5: \ + case 0xe6: \ + case 0xe7: \ + case 0xe8: \ + case 0xe9: \ + case 0xea: \ + case 0xeb: \ + case 0xec: \ + case 0xed: \ + case 0xee: \ + case 0xef: \ + case 0xf0: \ + case 0xf1: \ + case 0xf2: \ + case 0xf3: \ + case 0xf4: \ + case 0xf5: \ + case 0xf6: \ + case 0xf7: \ + case 0xf8: \ + case 0xf9: \ + case 0xfa: \ + case 0xfb: \ + case 0xfc: \ + case 0xfd: \ + case 0xfe: \ + case 0xff + static int is_ws(uint8_t c) { switch (c) { case ' ': @@ -185,40 +388,108 @@ static int is_ws(uint8_t c) { } } -static int parser_eof(sf_parser *sfp) { return sfp->pos == sfp->end; } +#ifdef __AVX2__ +# ifdef _MSC_VER +# include + +static int ctz(unsigned int v) { + unsigned long n; + + /* Assume that v is not 0. */ + _BitScanForward(&n, v); + + return (int)n; +} +# else /* !_MSC_VER */ +# define ctz __builtin_ctz +# endif /* !_MSC_VER */ +#endif /* __AVX2__ */ + +static int parser_eof(sfparse_parser *sfp) { return sfp->pos == sfp->end; } -static void parser_discard_ows(sf_parser *sfp) { +static void parser_discard_ows(sfparse_parser *sfp) { for (; !parser_eof(sfp) && is_ws(*sfp->pos); ++sfp->pos) ; } -static void parser_discard_sp(sf_parser *sfp) { +static void parser_discard_sp(sfparse_parser *sfp) { for (; !parser_eof(sfp) && *sfp->pos == ' '; ++sfp->pos) ; } -static void parser_set_op_state(sf_parser *sfp, uint32_t op) { - sfp->state &= ~SF_STATE_OP_MASK; +static void parser_set_op_state(sfparse_parser *sfp, uint32_t op) { + sfp->state &= ~SFPARSE_STATE_OP_MASK; sfp->state |= op; } -static void parser_unset_inner_list_state(sf_parser *sfp) { - sfp->state &= ~SF_STATE_INNER_LIST; +static void parser_unset_inner_list_state(sfparse_parser *sfp) { + sfp->state &= ~SFPARSE_STATE_INNER_LIST; } -static int parser_key(sf_parser *sfp, sf_vec *dest) { +#ifdef __AVX2__ +static const uint8_t *find_char_key(const uint8_t *first, const uint8_t *last) { + const __m256i us = _mm256_set1_epi8('_'); + const __m256i ds = _mm256_set1_epi8('-'); + const __m256i dot = _mm256_set1_epi8('.'); + const __m256i ast = _mm256_set1_epi8('*'); + const __m256i r0l = _mm256_set1_epi8('0' - 1); + const __m256i r0r = _mm256_set1_epi8('9' + 1); + const __m256i r1l = _mm256_set1_epi8('a' - 1); + const __m256i r1r = _mm256_set1_epi8('z' + 1); + __m256i s, x; + uint32_t m; + + for (; first != last; first += 32) { + s = _mm256_loadu_si256((void *)first); + + x = _mm256_cmpeq_epi8(s, us); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, ds), x); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, dot), x); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, ast), x); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r0l), _mm256_cmpgt_epi8(r0r, s)), + x); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r1l), _mm256_cmpgt_epi8(r1r, s)), + x); + + m = ~(uint32_t)_mm256_movemask_epi8(x); + if (m) { + return first + ctz(m); + } + } + + return last; +} +#endif /* __AVX2__ */ + +static int parser_key(sfparse_parser *sfp, sfparse_vec *dest) { const uint8_t *base; +#ifdef __AVX2__ + const uint8_t *last; +#endif /* __AVX2__ */ switch (*sfp->pos) { case '*': LCALPHA_CASES: break; default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } base = sfp->pos++; +#ifdef __AVX2__ + if (sfp->end - sfp->pos >= 32) { + last = sfp->pos + ((sfp->end - sfp->pos) & ~0x1fu); + + sfp->pos = find_char_key(sfp->pos, last); + if (sfp->pos != last) { + goto fin; + } + } +#endif /* __AVX2__ */ + for (; !parser_eof(sfp); ++sfp->pos) { switch (*sfp->pos) { case '_': @@ -233,6 +504,9 @@ static int parser_key(sf_parser *sfp, sf_vec *dest) { break; } +#ifdef __AVX2__ +fin: +#endif /* __AVX2__ */ if (dest) { dest->base = (uint8_t *)base; dest->len = (size_t)(sfp->pos - dest->base); @@ -241,7 +515,7 @@ static int parser_key(sf_parser *sfp, sf_vec *dest) { return 0; } -static int parser_number(sf_parser *sfp, sf_value *dest) { +static int parser_number(sfparse_parser *sfp, sfparse_value *dest) { int sign = 1; int64_t value = 0; size_t len = 0; @@ -250,7 +524,7 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { if (*sfp->pos == '-') { ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } sign = -1; @@ -262,7 +536,7 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { switch (*sfp->pos) { DIGIT_CASES: if (++len > 15) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } value *= 10; @@ -275,13 +549,13 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { } if (len == 0) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } if (parser_eof(sfp) || *sfp->pos != '.') { if (dest) { - dest->type = SF_TYPE_INTEGER; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_INTEGER; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->integer = value * sign; } @@ -291,7 +565,7 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { /* decimal */ if (len > 12) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } fpos = len; @@ -302,7 +576,7 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { switch (*sfp->pos) { DIGIT_CASES: if (++len > 15) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } value *= 10; @@ -315,12 +589,12 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { } if (fpos == len || len - fpos > 3) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } if (dest) { - dest->type = SF_TYPE_DECIMAL; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_DECIMAL; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->decimal.numer = value * sign; switch (len - fpos) { @@ -342,9 +616,9 @@ static int parser_number(sf_parser *sfp, sf_value *dest) { return 0; } -static int parser_date(sf_parser *sfp, sf_value *dest) { +static int parser_date(sfparse_parser *sfp, sfparse_value *dest) { int rv; - sf_value val; + sfparse_value val; /* The first byte has already been validated by the caller. */ assert('@' == *sfp->pos); @@ -352,7 +626,7 @@ static int parser_date(sf_parser *sfp, sf_value *dest) { ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } rv = parser_number(sfp, &val); @@ -360,27 +634,93 @@ static int parser_date(sf_parser *sfp, sf_value *dest) { return rv; } - if (val.type != SF_TYPE_INTEGER) { - return SF_ERR_PARSE_ERROR; + if (val.type != SFPARSE_TYPE_INTEGER) { + return SFPARSE_ERR_PARSE; } if (dest) { *dest = val; - dest->type = SF_TYPE_DATE; + dest->type = SFPARSE_TYPE_DATE; } return 0; } -static int parser_string(sf_parser *sfp, sf_value *dest) { +#ifdef __AVX2__ +static const uint8_t *find_char_string(const uint8_t *first, + const uint8_t *last) { + const __m256i bs = _mm256_set1_epi8('\\'); + const __m256i dq = _mm256_set1_epi8('"'); + const __m256i del = _mm256_set1_epi8(0x7f); + const __m256i sp = _mm256_set1_epi8(' '); + __m256i s, x; + uint32_t m; + + for (; first != last; first += 32) { + s = _mm256_loadu_si256((void *)first); + + x = _mm256_cmpgt_epi8(sp, s); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, bs), x); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, dq), x); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, del), x); + + m = (uint32_t)_mm256_movemask_epi8(x); + if (m) { + return first + ctz(m); + } + } + + return last; +} +#endif /* __AVX2__ */ + +static int parser_string(sfparse_parser *sfp, sfparse_value *dest) { const uint8_t *base; - uint32_t flags = SF_VALUE_FLAG_NONE; +#ifdef __AVX2__ + const uint8_t *last; +#endif /* __AVX2__ */ + uint32_t flags = SFPARSE_VALUE_FLAG_NONE; /* The first byte has already been validated by the caller. */ assert('"' == *sfp->pos); base = ++sfp->pos; +#ifdef __AVX2__ + for (; sfp->end - sfp->pos >= 32; ++sfp->pos) { + last = sfp->pos + ((sfp->end - sfp->pos) & ~0x1fu); + + sfp->pos = find_char_string(sfp->pos, last); + if (sfp->pos == last) { + break; + } + + switch (*sfp->pos) { + case '\\': + ++sfp->pos; + if (parser_eof(sfp)) { + return SFPARSE_ERR_PARSE; + } + + switch (*sfp->pos) { + case '"': + case '\\': + flags = SFPARSE_VALUE_FLAG_ESCAPED_STRING; + + break; + default: + return SFPARSE_ERR_PARSE; + } + + break; + case '"': + goto fin; + default: + return SFPARSE_ERR_PARSE; + } + } +#endif /* __AVX2__ */ + for (; !parser_eof(sfp); ++sfp->pos) { switch (*sfp->pos) { X20_21_CASES: @@ -390,75 +730,131 @@ static int parser_string(sf_parser *sfp, sf_value *dest) { case '\\': ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } switch (*sfp->pos) { case '"': case '\\': - flags = SF_VALUE_FLAG_ESCAPED_STRING; + flags = SFPARSE_VALUE_FLAG_ESCAPED_STRING; break; default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } break; case '"': - if (dest) { - dest->type = SF_TYPE_STRING; - dest->flags = flags; - dest->vec.len = (size_t)(sfp->pos - base); - dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; - } + goto fin; + default: + return SFPARSE_ERR_PARSE; + } + } - ++sfp->pos; + return SFPARSE_ERR_PARSE; - return 0; - default: - return SF_ERR_PARSE_ERROR; +fin: + if (dest) { + dest->type = SFPARSE_TYPE_STRING; + dest->flags = flags; + dest->vec.len = (size_t)(sfp->pos - base); + dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; + } + + ++sfp->pos; + + return 0; +} + +#ifdef __AVX2__ +static const uint8_t *find_char_token(const uint8_t *first, + const uint8_t *last) { + /* r0: !..:, excluding "(), + r1: A..Z + r2: ^..~, excluding {} */ + const __m256i r0l = _mm256_set1_epi8('!' - 1); + const __m256i r0r = _mm256_set1_epi8(':' + 1); + const __m256i dq = _mm256_set1_epi8('"'); + const __m256i prl = _mm256_set1_epi8('('); + const __m256i prr = _mm256_set1_epi8(')'); + const __m256i comma = _mm256_set1_epi8(','); + const __m256i r1l = _mm256_set1_epi8('A' - 1); + const __m256i r1r = _mm256_set1_epi8('Z' + 1); + const __m256i r2l = _mm256_set1_epi8('^' - 1); + const __m256i r2r = _mm256_set1_epi8('~' + 1); + const __m256i cbl = _mm256_set1_epi8('{'); + const __m256i cbr = _mm256_set1_epi8('}'); + __m256i s, x; + uint32_t m; + + for (; first != last; first += 32) { + s = _mm256_loadu_si256((void *)first); + + x = _mm256_andnot_si256( + _mm256_cmpeq_epi8(s, comma), + _mm256_andnot_si256( + _mm256_cmpeq_epi8(s, prr), + _mm256_andnot_si256( + _mm256_cmpeq_epi8(s, prl), + _mm256_andnot_si256(_mm256_cmpeq_epi8(s, dq), + _mm256_and_si256(_mm256_cmpgt_epi8(s, r0l), + _mm256_cmpgt_epi8(r0r, s)))))); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r1l), _mm256_cmpgt_epi8(r1r, s)), + x); + x = _mm256_or_si256( + _mm256_andnot_si256( + _mm256_cmpeq_epi8(s, cbr), + _mm256_andnot_si256(_mm256_cmpeq_epi8(s, cbl), + _mm256_and_si256(_mm256_cmpgt_epi8(s, r2l), + _mm256_cmpgt_epi8(r2r, s)))), + x); + + m = ~(uint32_t)_mm256_movemask_epi8(x); + if (m) { + return first + ctz(m); } } - return SF_ERR_PARSE_ERROR; + return last; } +#endif /* __AVX2__ */ -static int parser_token(sf_parser *sfp, sf_value *dest) { +static int parser_token(sfparse_parser *sfp, sfparse_value *dest) { const uint8_t *base; +#ifdef __AVX2__ + const uint8_t *last; +#endif /* __AVX2__ */ /* The first byte has already been validated by the caller. */ base = sfp->pos++; +#ifdef __AVX2__ + if (sfp->end - sfp->pos >= 32) { + last = sfp->pos + ((sfp->end - sfp->pos) & ~0x1fu); + + sfp->pos = find_char_token(sfp->pos, last); + if (sfp->pos != last) { + goto fin; + } + } +#endif /* __AVX2__ */ + for (; !parser_eof(sfp); ++sfp->pos) { switch (*sfp->pos) { - case '!': - case '#': - case '$': - case '%': - case '&': - case '\'': - case '*': - case '+': - case '-': - case '.': - case '^': - case '_': - case '`': - case '|': - case '~': - case ':': - case '/': - DIGIT_CASES: - ALPHA_CASES: + TOKEN_CASES: continue; } break; } +#ifdef __AVX2__ +fin: +#endif /* __AVX2__ */ if (dest) { - dest->type = SF_TYPE_TOKEN; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_TOKEN; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->vec.base = (uint8_t *)base; dest->vec.len = (size_t)(sfp->pos - base); } @@ -466,14 +862,63 @@ static int parser_token(sf_parser *sfp, sf_value *dest) { return 0; } -static int parser_byteseq(sf_parser *sfp, sf_value *dest) { +#ifdef __AVX2__ +static const uint8_t *find_char_byteseq(const uint8_t *first, + const uint8_t *last) { + const __m256i pls = _mm256_set1_epi8('+'); + const __m256i fs = _mm256_set1_epi8('/'); + const __m256i r0l = _mm256_set1_epi8('0' - 1); + const __m256i r0r = _mm256_set1_epi8('9' + 1); + const __m256i r1l = _mm256_set1_epi8('A' - 1); + const __m256i r1r = _mm256_set1_epi8('Z' + 1); + const __m256i r2l = _mm256_set1_epi8('a' - 1); + const __m256i r2r = _mm256_set1_epi8('z' + 1); + __m256i s, x; + uint32_t m; + + for (; first != last; first += 32) { + s = _mm256_loadu_si256((void *)first); + + x = _mm256_cmpeq_epi8(s, pls); + x = _mm256_or_si256(_mm256_cmpeq_epi8(s, fs), x); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r0l), _mm256_cmpgt_epi8(r0r, s)), + x); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r1l), _mm256_cmpgt_epi8(r1r, s)), + x); + x = _mm256_or_si256( + _mm256_and_si256(_mm256_cmpgt_epi8(s, r2l), _mm256_cmpgt_epi8(r2r, s)), + x); + + m = ~(uint32_t)_mm256_movemask_epi8(x); + if (m) { + return first + ctz(m); + } + } + + return last; +} +#endif /* __AVX2__ */ + +static int parser_byteseq(sfparse_parser *sfp, sfparse_value *dest) { const uint8_t *base; +#ifdef __AVX2__ + const uint8_t *last; +#endif /* __AVX2__ */ /* The first byte has already been validated by the caller. */ assert(':' == *sfp->pos); base = ++sfp->pos; +#ifdef __AVX2__ + if (sfp->end - sfp->pos >= 32) { + last = sfp->pos + ((sfp->end - sfp->pos) & ~0x1fu); + sfp->pos = find_char_byteseq(sfp->pos, last); + } +#endif /* __AVX2__ */ + for (; !parser_eof(sfp); ++sfp->pos) { switch (*sfp->pos) { case '+': @@ -485,75 +930,47 @@ static int parser_byteseq(sf_parser *sfp, sf_value *dest) { switch ((sfp->pos - base) & 0x3) { case 0: case 1: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; case 2: - switch (*(sfp->pos - 1)) { - case 'A': - case 'Q': - case 'g': - case 'w': - break; - default: - return SF_ERR_PARSE_ERROR; - } - ++sfp->pos; - if (parser_eof(sfp) || *sfp->pos != '=') { - return SF_ERR_PARSE_ERROR; + if (parser_eof(sfp)) { + return SFPARSE_ERR_PARSE; + } + + if (*sfp->pos == '=') { + ++sfp->pos; } break; case 3: - switch (*(sfp->pos - 1)) { - case 'A': - case 'E': - case 'I': - case 'M': - case 'Q': - case 'U': - case 'Y': - case 'c': - case 'g': - case 'k': - case 'o': - case 's': - case 'w': - case '0': - case '4': - case '8': - break; - default: - return SF_ERR_PARSE_ERROR; - } + ++sfp->pos; break; } - ++sfp->pos; - if (parser_eof(sfp) || *sfp->pos != ':') { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } goto fin; case ':': - if ((sfp->pos - base) & 0x3) { - return SF_ERR_PARSE_ERROR; + if (((sfp->pos - base) & 0x3) == 1) { + return SFPARSE_ERR_PARSE; } goto fin; default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } } - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; fin: if (dest) { - dest->type = SF_TYPE_BYTESEQ; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_BYTESEQ; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->vec.len = (size_t)(sfp->pos - base); dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; } @@ -563,7 +980,7 @@ static int parser_byteseq(sf_parser *sfp, sf_value *dest) { return 0; } -static int parser_boolean(sf_parser *sfp, sf_value *dest) { +static int parser_boolean(sfparse_parser *sfp, sfparse_value *dest) { int b; /* The first byte has already been validated by the caller. */ @@ -572,7 +989,7 @@ static int parser_boolean(sf_parser *sfp, sf_value *dest) { ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } switch (*sfp->pos) { @@ -585,21 +1002,184 @@ static int parser_boolean(sf_parser *sfp, sf_value *dest) { break; default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } ++sfp->pos; if (dest) { - dest->type = SF_TYPE_BOOLEAN; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_BOOLEAN; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->boolean = b; } return 0; } -static int parser_bare_item(sf_parser *sfp, sf_value *dest) { +static int pctdecode(uint8_t *pc, const uint8_t **ppos) { + uint8_t c, b = **ppos; + + switch (b) { + DIGIT_CASES: + c = (uint8_t)((b - '0') << 4); + + break; + LCHEXALPHA_CASES: + c = (uint8_t)((b - 'a' + 10) << 4); + + break; + default: + return -1; + } + + b = *++*ppos; + + switch (b) { + DIGIT_CASES: + c |= (uint8_t)(b - '0'); + + break; + LCHEXALPHA_CASES: + c |= (uint8_t)(b - 'a' + 10); + + break; + default: + return -1; + } + + *pc = c; + ++*ppos; + + return 0; +} + +/* Start of utf8 dfa */ +/* Copyright (c) 2008-2010 Bjoern Hoehrmann + * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + * + * Copyright (c) 2008-2009 Bjoern Hoehrmann + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 + +/* clang-format off */ +static const uint8_t utf8d[] = { + /* + * The first part of the table maps bytes to character classes that + * to reduce the size of the transition table and create bitmasks. + */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + /* + * The second part is a transition table that maps a combination + * of a state of the automaton and a character class to a state. + */ + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; +/* clang-format on */ + +static void utf8_decode(uint32_t *state, uint8_t byte) { + *state = utf8d[256 + *state + utf8d[byte]]; +} + +/* End of utf8 dfa */ + +static int parser_dispstring(sfparse_parser *sfp, sfparse_value *dest) { + const uint8_t *base; + uint8_t c; + uint32_t utf8state = UTF8_ACCEPT; + + assert('%' == *sfp->pos); + + ++sfp->pos; + + if (parser_eof(sfp) || *sfp->pos != '"') { + return SFPARSE_ERR_PARSE; + } + + base = ++sfp->pos; + + for (; !parser_eof(sfp);) { + switch (*sfp->pos) { + X00_1F_CASES: + X7F_FF_CASES: + return SFPARSE_ERR_PARSE; + case '%': + ++sfp->pos; + + if (sfp->pos + 2 > sfp->end) { + return SFPARSE_ERR_PARSE; + } + + if (pctdecode(&c, &sfp->pos) != 0) { + return SFPARSE_ERR_PARSE; + } + + utf8_decode(&utf8state, c); + if (utf8state == UTF8_REJECT) { + return SFPARSE_ERR_PARSE; + } + + break; + case '"': + if (utf8state != UTF8_ACCEPT) { + return SFPARSE_ERR_PARSE; + } + + if (dest) { + dest->type = SFPARSE_TYPE_DISPSTRING; + dest->flags = SFPARSE_VALUE_FLAG_NONE; + dest->vec.len = (size_t)(sfp->pos - base); + dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base; + } + + ++sfp->pos; + + return 0; + default: + if (utf8state != UTF8_ACCEPT) { + return SFPARSE_ERR_PARSE; + } + + ++sfp->pos; + } + } + + return SFPARSE_ERR_PARSE; +} + +static int parser_bare_item(sfparse_parser *sfp, sfparse_value *dest) { switch (*sfp->pos) { case '"': return parser_string(sfp, dest); @@ -615,29 +1195,32 @@ static int parser_bare_item(sf_parser *sfp, sf_value *dest) { case '*': ALPHA_CASES: return parser_token(sfp, dest); + case '%': + return parser_dispstring(sfp, dest); default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } } -static int parser_skip_inner_list(sf_parser *sfp); +static int parser_skip_inner_list(sfparse_parser *sfp); -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) { int rv; - switch (sfp->state & SF_STATE_OP_MASK) { - case SF_STATE_BEFORE: + switch (sfp->state & SFPARSE_STATE_OP_MASK) { + case SFPARSE_STATE_BEFORE: rv = parser_skip_inner_list(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_BEFORE_PARAMS: - parser_set_op_state(sfp, SF_STATE_PARAMS); + case SFPARSE_STATE_BEFORE_PARAMS: + parser_set_op_state(sfp, SFPARSE_STATE_PARAMS); break; - case SF_STATE_PARAMS: + case SFPARSE_STATE_PARAMS: break; default: assert(0); @@ -645,16 +1228,16 @@ int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { } if (parser_eof(sfp) || *sfp->pos != ';') { - parser_set_op_state(sfp, SF_STATE_AFTER); + parser_set_op_state(sfp, SFPARSE_STATE_AFTER); - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; } ++sfp->pos; parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } rv = parser_key(sfp, dest_key); @@ -664,8 +1247,8 @@ int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { if (parser_eof(sfp) || *sfp->pos != '=') { if (dest_value) { - dest_value->type = SF_TYPE_BOOLEAN; - dest_value->flags = SF_VALUE_FLAG_NONE; + dest_value->type = SFPARSE_TYPE_BOOLEAN; + dest_value->flags = SFPARSE_VALUE_FLAG_NONE; dest_value->boolean = 1; } @@ -675,23 +1258,23 @@ int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } return parser_bare_item(sfp, dest_value); } -static int parser_skip_params(sf_parser *sfp) { +static int parser_skip_params(sfparse_parser *sfp) { int rv; for (;;) { - rv = sf_parser_param(sfp, NULL, NULL); + rv = sfparse_parser_param(sfp, NULL, NULL); switch (rv) { case 0: break; - case SF_ERR_EOF: + case SFPARSE_ERR_EOF: return 0; - case SF_ERR_PARSE_ERROR: + case SFPARSE_ERR_PARSE: return rv; default: assert(0); @@ -700,45 +1283,45 @@ static int parser_skip_params(sf_parser *sfp) { } } -int sf_parser_inner_list(sf_parser *sfp, sf_value *dest) { +int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest) { int rv; - switch (sfp->state & SF_STATE_OP_MASK) { - case SF_STATE_BEFORE: + switch (sfp->state & SFPARSE_STATE_OP_MASK) { + case SFPARSE_STATE_BEFORE: parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } break; - case SF_STATE_BEFORE_PARAMS: + case SFPARSE_STATE_BEFORE_PARAMS: rv = parser_skip_params(sfp); if (rv != 0) { return rv; } - /* Technically, we are entering SF_STATE_AFTER, but we will set + /* Technically, we are entering SFPARSE_STATE_AFTER, but we will set another state without reading the state. */ - /* parser_set_op_state(sfp, SF_STATE_AFTER); */ + /* parser_set_op_state(sfp, SFPARSE_STATE_AFTER); */ /* fall through */ - case SF_STATE_AFTER: + case SFPARSE_STATE_AFTER: if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } switch (*sfp->pos) { case ' ': parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } break; case ')': break; default: - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } break; @@ -751,9 +1334,9 @@ int sf_parser_inner_list(sf_parser *sfp, sf_value *dest) { ++sfp->pos; parser_unset_inner_list_state(sfp); - parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS); + parser_set_op_state(sfp, SFPARSE_STATE_BEFORE_PARAMS); - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; } rv = parser_bare_item(sfp, dest); @@ -761,22 +1344,22 @@ int sf_parser_inner_list(sf_parser *sfp, sf_value *dest) { return rv; } - parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS); + parser_set_op_state(sfp, SFPARSE_STATE_BEFORE_PARAMS); return 0; } -static int parser_skip_inner_list(sf_parser *sfp) { +static int parser_skip_inner_list(sfparse_parser *sfp) { int rv; for (;;) { - rv = sf_parser_inner_list(sfp, NULL); + rv = sfparse_parser_inner_list(sfp, NULL); switch (rv) { case 0: break; - case SF_ERR_EOF: + case SFPARSE_ERR_EOF: return 0; - case SF_ERR_PARSE_ERROR: + case SFPARSE_ERR_PARSE: return rv; default: assert(0); @@ -785,39 +1368,39 @@ static int parser_skip_inner_list(sf_parser *sfp) { } } -static int parser_next_key_or_item(sf_parser *sfp) { +static int parser_next_key_or_item(sfparse_parser *sfp) { parser_discard_ows(sfp); if (parser_eof(sfp)) { - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; } if (*sfp->pos != ',') { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } ++sfp->pos; parser_discard_ows(sfp); if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } return 0; } -static int parser_dict_value(sf_parser *sfp, sf_value *dest) { +static int parser_dict_value(sfparse_parser *sfp, sfparse_value *dest) { int rv; if (parser_eof(sfp) || *(sfp->pos) != '=') { /* Boolean true */ if (dest) { - dest->type = SF_TYPE_BOOLEAN; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_BOOLEAN; + dest->flags = SFPARSE_VALUE_FLAG_NONE; dest->boolean = 1; } - sfp->state = SF_STATE_DICT_BEFORE_PARAMS; + sfp->state = SFPARSE_STATE_DICT_BEFORE_PARAMS; return 0; } @@ -825,18 +1408,18 @@ static int parser_dict_value(sf_parser *sfp, sf_value *dest) { ++sfp->pos; if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } if (*sfp->pos == '(') { if (dest) { - dest->type = SF_TYPE_INNER_LIST; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_INNER_LIST; + dest->flags = SFPARSE_VALUE_FLAG_NONE; } ++sfp->pos; - sfp->state = SF_STATE_DICT_INNER_LIST_BEFORE; + sfp->state = SFPARSE_STATE_DICT_INNER_LIST_BEFORE; return 0; } @@ -846,41 +1429,42 @@ static int parser_dict_value(sf_parser *sfp, sf_value *dest) { return rv; } - sfp->state = SF_STATE_DICT_BEFORE_PARAMS; + sfp->state = SFPARSE_STATE_DICT_BEFORE_PARAMS; return 0; } -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) { int rv; switch (sfp->state) { - case SF_STATE_DICT_INNER_LIST_BEFORE: + case SFPARSE_STATE_DICT_INNER_LIST_BEFORE: rv = parser_skip_inner_list(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_DICT_BEFORE_PARAMS: + case SFPARSE_STATE_DICT_BEFORE_PARAMS: rv = parser_skip_params(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_DICT_AFTER: + case SFPARSE_STATE_DICT_AFTER: rv = parser_next_key_or_item(sfp); if (rv != 0) { return rv; } break; - case SF_STATE_INITIAL: + case SFPARSE_STATE_INITIAL: parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; } break; @@ -897,36 +1481,36 @@ int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) { return parser_dict_value(sfp, dest_value); } -int sf_parser_list(sf_parser *sfp, sf_value *dest) { +int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest) { int rv; switch (sfp->state) { - case SF_STATE_LIST_INNER_LIST_BEFORE: + case SFPARSE_STATE_LIST_INNER_LIST_BEFORE: rv = parser_skip_inner_list(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_LIST_BEFORE_PARAMS: + case SFPARSE_STATE_LIST_BEFORE_PARAMS: rv = parser_skip_params(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_LIST_AFTER: + case SFPARSE_STATE_LIST_AFTER: rv = parser_next_key_or_item(sfp); if (rv != 0) { return rv; } break; - case SF_STATE_INITIAL: + case SFPARSE_STATE_INITIAL: parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; } break; @@ -937,13 +1521,13 @@ int sf_parser_list(sf_parser *sfp, sf_value *dest) { if (*sfp->pos == '(') { if (dest) { - dest->type = SF_TYPE_INNER_LIST; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_INNER_LIST; + dest->flags = SFPARSE_VALUE_FLAG_NONE; } ++sfp->pos; - sfp->state = SF_STATE_LIST_INNER_LIST_BEFORE; + sfp->state = SFPARSE_STATE_LIST_INNER_LIST_BEFORE; return 0; } @@ -953,45 +1537,45 @@ int sf_parser_list(sf_parser *sfp, sf_value *dest) { return rv; } - sfp->state = SF_STATE_LIST_BEFORE_PARAMS; + sfp->state = SFPARSE_STATE_LIST_BEFORE_PARAMS; return 0; } -int sf_parser_item(sf_parser *sfp, sf_value *dest) { +int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest) { int rv; switch (sfp->state) { - case SF_STATE_INITIAL: + case SFPARSE_STATE_INITIAL: parser_discard_sp(sfp); if (parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } break; - case SF_STATE_ITEM_INNER_LIST_BEFORE: + case SFPARSE_STATE_ITEM_INNER_LIST_BEFORE: rv = parser_skip_inner_list(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_ITEM_BEFORE_PARAMS: + case SFPARSE_STATE_ITEM_BEFORE_PARAMS: rv = parser_skip_params(sfp); if (rv != 0) { return rv; } /* fall through */ - case SF_STATE_ITEM_AFTER: + case SFPARSE_STATE_ITEM_AFTER: parser_discard_sp(sfp); if (!parser_eof(sfp)) { - return SF_ERR_PARSE_ERROR; + return SFPARSE_ERR_PARSE; } - return SF_ERR_EOF; + return SFPARSE_ERR_EOF; default: assert(0); abort(); @@ -999,13 +1583,13 @@ int sf_parser_item(sf_parser *sfp, sf_value *dest) { if (*sfp->pos == '(') { if (dest) { - dest->type = SF_TYPE_INNER_LIST; - dest->flags = SF_VALUE_FLAG_NONE; + dest->type = SFPARSE_TYPE_INNER_LIST; + dest->flags = SFPARSE_VALUE_FLAG_NONE; } ++sfp->pos; - sfp->state = SF_STATE_ITEM_INNER_LIST_BEFORE; + sfp->state = SFPARSE_STATE_ITEM_INNER_LIST_BEFORE; return 0; } @@ -1015,12 +1599,13 @@ int sf_parser_item(sf_parser *sfp, sf_value *dest) { return rv; } - sfp->state = SF_STATE_ITEM_BEFORE_PARAMS; + sfp->state = SFPARSE_STATE_ITEM_BEFORE_PARAMS; return 0; } -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) { if (datalen == 0) { sfp->pos = sfp->end = NULL; } else { @@ -1028,16 +1613,16 @@ void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen) { sfp->end = data + datalen; } - sfp->state = SF_STATE_INITIAL; + sfp->state = SFPARSE_STATE_INITIAL; } -void sf_unescape(sf_vec *dest, const sf_vec *src) { +void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src) { const uint8_t *p, *q; uint8_t *o; size_t len, slen; if (src->len == 0) { - *dest = *src; + dest->len = 0; return; } @@ -1049,16 +1634,12 @@ void sf_unescape(sf_vec *dest, const sf_vec *src) { for (;;) { q = memchr(p, '\\', len); if (q == NULL) { - if (len == src->len) { - *dest = *src; - - return; - } - memcpy(o, p, len); o += len; - break; + dest->len = (size_t)(o - dest->base); + + return; } slen = (size_t)(q - p); @@ -1069,11 +1650,9 @@ void sf_unescape(sf_vec *dest, const sf_vec *src) { *o++ = *p++; len -= slen + 2; } - - dest->len = (size_t)(o - dest->base); } -void sf_base64decode(sf_vec *dest, const sf_vec *src) { +void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src) { static const int index_tbl[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1092,20 +1671,22 @@ void sf_base64decode(sf_vec *dest, const sf_vec *src) { uint8_t *o; const uint8_t *p, *end; uint32_t n; - size_t i; + size_t i, left; int idx; - assert((src->len & 0x3) == 0); - if (src->len == 0) { - *dest = *src; + dest->len = 0; return; } o = dest->base; p = src->base; - end = src->base + src->len; + left = src->len & 0x3; + if (left == 0 && src->base[src->len - 1] == '=') { + left = 4; + } + end = src->base + src->len - left; for (; p != end;) { n = 0; @@ -1113,33 +1694,94 @@ void sf_base64decode(sf_vec *dest, const sf_vec *src) { for (i = 1; i <= 4; ++i, ++p) { idx = index_tbl[*p]; - if (idx == -1) { - assert(i > 2); + assert(idx != -1); - if (i == 3) { - assert(*p == '=' && *(p + 1) == '=' && p + 2 == end); + n += (uint32_t)(idx << (24 - i * 6)); + } - *o++ = (uint8_t)(n >> 16); + *o++ = (uint8_t)(n >> 16); + *o++ = (n >> 8) & 0xffu; + *o++ = n & 0xffu; + } - goto fin; - } + switch (left) { + case 0: + goto fin; + case 1: + assert(0); + abort(); + case 3: + if (src->base[src->len - 1] == '=') { + left = 2; + } - assert(*p == '=' && p + 1 == end); + break; + case 4: + assert('=' == src->base[src->len - 1]); - *o++ = (uint8_t)(n >> 16); - *o++ = (n >> 8) & 0xffu; + if (src->base[src->len - 2] == '=') { + left = 2; + } else { + left = 3; + } - goto fin; - } + break; + } - n += (uint32_t)(idx << (24 - i * 6)); - } + switch (left) { + case 2: + *o = (uint8_t)(index_tbl[*p++] << 2); + *o++ |= (uint8_t)(index_tbl[*p++] >> 4); - *o++ = (uint8_t)(n >> 16); + break; + case 3: + n = (uint32_t)(index_tbl[*p++] << 10); + n += (uint32_t)(index_tbl[*p++] << 4); + n += (uint32_t)(index_tbl[*p++] >> 2); *o++ = (n >> 8) & 0xffu; *o++ = n & 0xffu; + + break; } fin: dest->len = (size_t)(o - dest->base); } + +void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src) { + const uint8_t *p, *q; + uint8_t *o; + size_t len, slen; + + if (src->len == 0) { + dest->len = 0; + + return; + } + + o = dest->base; + p = src->base; + len = src->len; + + for (;;) { + q = memchr(p, '%', len); + if (q == NULL) { + memcpy(o, p, len); + o += len; + + dest->len = (size_t)(o - dest->base); + + return; + } + + slen = (size_t)(q - p); + memcpy(o, p, slen); + o += slen; + + p = q + 1; + + pctdecode(o++, &p); + + len -= slen + 3; + } +} diff --git a/deps/nghttp2/lib/sfparse.h b/deps/nghttp2/lib/sfparse.h index 1474db1429acea..9341221a099438 100644 --- a/deps/nghttp2/lib/sfparse.h +++ b/deps/nghttp2/lib/sfparse.h @@ -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 -#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */ # include -#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ +#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */ #include #include /** * @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_* `. + * :macro:`SFPARSE_VALUE_FLAG_* `. */ 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 ` == 0, :member:`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 ` == 0, :member:`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 ` must point to the buffer that - * has sufficient space to store the unescaped string. - * - * If there is no escape character in |src|, |*src| is assigned to - * |*dest|. This includes the case that :member:`src->len - * ` == 0. + * :member:`dest->base ` must point to the buffer + * that has sufficient space to store the unescaped string. The + * memory areas pointed by :member:`dest->base ` and + * :member:`src->base ` must not overlap. * * This function sets the length of unescaped string to - * :member:`dest->len `. + * :member:`dest->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 ` must point to the buffer + * that has sufficient space to store the decoded byte string. * - * :member:`dest->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 `. + */ +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. * - * If :member:`src->len ` == 0, |*src| is assigned to - * |*dest|. + * :member:`dest->base ` must point to the buffer + * that has sufficient space to store the decoded byte string. The + * memory areas pointed by :member:`dest->base ` and + * :member:`src->base ` must not overlap. * * This function sets the length of decoded byte string to - * :member:`dest->len `. + * :member:`dest->len `. */ -void sf_base64decode(sf_vec *dest, const sf_vec *src); +void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src); #ifdef __cplusplus } -#endif +#endif /* defined(__cplusplus) */ -#endif /* SFPARSE_H */ +#endif /* !defined(SFPARSE_H) */ From 8edbdd289b09512a174b1fa297ec4a4a3e5e259b Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 23 Jun 2025 21:04:25 -0400 Subject: [PATCH 02/10] deps: update nghttp2 to 1.66.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/58786 Reviewed-By: Luigi Pinca Reviewed-By: Ulises Gascón Reviewed-By: Michaël Zasso Reviewed-By: Rafael Gonzaga (cherry picked from commit 745f48d9f36b6f5765297e7d6058dc7f51a18ccc) --- deps/nghttp2/lib/Makefile.in | 2 ++ deps/nghttp2/lib/includes/Makefile.in | 2 ++ .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 ++-- deps/nghttp2/lib/nghttp2_session.c | 21 ++++++++++++++++--- deps/nghttp2/lib/nghttp2_session.h | 19 +++++++++++++---- deps/nghttp2/lib/nghttp2_stream.c | 2 +- deps/nghttp2/lib/nghttp2_submit.c | 3 ++- 7 files changed, 42 insertions(+), 11 deletions(-) diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in index 14686ef14b1a4f..7a4cb5e97404b6 100644 --- a/deps/nghttp2/lib/Makefile.in +++ b/deps/nghttp2/lib/Makefile.in @@ -360,6 +360,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@ LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ +LIBNGTCP2_CRYPTO_OSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ +LIBNGTCP2_CRYPTO_OSSL_LIBS = @LIBNGTCP2_CRYPTO_OSSL_LIBS@ LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS = @LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in index 778dcb874c926b..7504f8e7c75b52 100644 --- a/deps/nghttp2/lib/includes/Makefile.in +++ b/deps/nghttp2/lib/includes/Makefile.in @@ -265,6 +265,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@ LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ +LIBNGTCP2_CRYPTO_OSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ +LIBNGTCP2_CRYPTO_OSSL_LIBS = @LIBNGTCP2_CRYPTO_OSSL_LIBS@ LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS = @LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index 1302eb57bc58d8..776c4924276b85 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.65.0" +#define NGHTTP2_VERSION "1.66.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 0x014100 +#define NGHTTP2_VERSION_NUM 0x014200 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index f5bda333f83d15..dc1a00cf576917 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -41,7 +41,7 @@ #include "nghttp2_debug.h" #include "nghttp2_submit.h" -nghttp2_stream root; +nghttp2_stream nghttp2_stream_root; /* * Returns non-zero if the number of outgoing opened streams is larger @@ -1092,6 +1092,15 @@ int nghttp2_session_add_item(nghttp2_session *session, int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, uint32_t error_code) { + return nghttp2_session_add_rst_stream_continue( + session, stream_id, error_code, + /* continue_without_stream = */ 1); +} + +int nghttp2_session_add_rst_stream_continue(nghttp2_session *session, + int32_t stream_id, + uint32_t error_code, + int continue_without_stream) { int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; @@ -1148,6 +1157,12 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, } } + /* To keep the old behaviour, do not fail if stream was not + found. */ + if (!continue_without_stream && !stream) { + return 0; + } + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; @@ -7715,7 +7730,7 @@ int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id) { if (stream_id == 0) { - return &root; + return &nghttp2_stream_root; } return nghttp2_session_get_stream_raw(session, stream_id); @@ -7724,7 +7739,7 @@ nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session, nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) { (void)session; - return &root; + return &nghttp2_stream_root; } int nghttp2_session_check_server_session(nghttp2_session *session) { diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index 6a54d35fcab7fa..419d23b5a9617e 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -45,7 +45,7 @@ preface handling. */ extern int nghttp2_enable_strict_preface; -extern nghttp2_stream root; +extern nghttp2_stream nghttp2_stream_root; /* * Option flags. @@ -402,6 +402,13 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session, int nghttp2_session_add_item(nghttp2_session *session, nghttp2_outbound_item *item); +/* + * This function wraps around nghttp2_session_add_rst_stream_continue + * with continue_without_stream = 1. + */ +int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, + uint32_t error_code); + /* * Adds RST_STREAM frame for the stream |stream_id| with the error * code |error_code|. This is a convenient function built on top of @@ -409,7 +416,9 @@ int nghttp2_session_add_item(nghttp2_session *session, * * This function simply returns 0 without adding RST_STREAM frame if * given stream is in NGHTTP2_STREAM_CLOSING state, because multiple - * RST_STREAM for a stream is redundant. + * RST_STREAM for a stream is redundant. It also returns 0 without + * adding the frame if |continue_without_stream| is nonzero, and + * stream was already gone. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -417,8 +426,10 @@ int nghttp2_session_add_item(nghttp2_session *session, * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, - uint32_t error_code); +int nghttp2_session_add_rst_stream_continue(nghttp2_session *session, + int32_t stream_id, + uint32_t error_code, + int continue_without_stream); /* * Adds PING frame. This is a convenient function built on top of diff --git a/deps/nghttp2/lib/nghttp2_stream.c b/deps/nghttp2/lib/nghttp2_stream.c index afbd7c2d9e0a77..0f2d3658775d72 100644 --- a/deps/nghttp2/lib/nghttp2_stream.c +++ b/deps/nghttp2/lib/nghttp2_stream.c @@ -151,7 +151,7 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) { } nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) { - if (stream == &root) { + if (stream == &nghttp2_stream_root) { return NGHTTP2_STREAM_STATE_IDLE; } diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index d481aebde221fd..5c6390fa759fd8 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -185,7 +185,8 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, return NGHTTP2_ERR_INVALID_ARGUMENT; } - return nghttp2_session_add_rst_stream(session, stream_id, error_code); + return nghttp2_session_add_rst_stream_continue( + session, stream_id, error_code, /* continue_without_stream = */ 0); } int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags, From 89226870c55753628b2a082c290ed8e8c108e28c Mon Sep 17 00:00:00 2001 From: nodejs-github-bot <18269663+nodejs-github-bot@users.noreply.github.com> Date: Sun, 5 Oct 2025 00:37:01 +0000 Subject: [PATCH 03/10] deps: update nghttp2 to 1.67.1 PR-URL: https://github.com/nodejs/node/pull/59790 Reviewed-By: Antoine du Hamel Reviewed-By: Trivikram Kamat (cherry picked from commit 43eb6cb5819f08e35231c33fb2fc423f08543eb0) --- deps/nghttp2/lib/CMakeLists.txt | 40 ++- deps/nghttp2/lib/Makefile.am | 2 +- deps/nghttp2/lib/Makefile.in | 4 +- deps/nghttp2/lib/config.cmake.in | 3 + deps/nghttp2/lib/includes/Makefile.in | 2 + deps/nghttp2/lib/includes/nghttp2/nghttp2.h | 74 ++++- .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- deps/nghttp2/lib/nghttp2_callbacks.c | 5 + deps/nghttp2/lib/nghttp2_callbacks.h | 1 + deps/nghttp2/lib/nghttp2_int.h | 6 +- deps/nghttp2/lib/nghttp2_map.c | 70 +++-- deps/nghttp2/lib/nghttp2_map.h | 9 +- deps/nghttp2/lib/nghttp2_option.c | 7 + deps/nghttp2/lib/nghttp2_option.h | 6 + deps/nghttp2/lib/nghttp2_session.c | 291 +++++++++++++----- deps/nghttp2/lib/nghttp2_session.h | 6 + deps/nghttp2/lib/nghttp2_submit.c | 6 +- 17 files changed, 388 insertions(+), 148 deletions(-) create mode 100644 deps/nghttp2/lib/config.cmake.in diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt index fda8dcb7fc7f2a..98e3dbe7682fb0 100644 --- a/deps/nghttp2/lib/CMakeLists.txt +++ b/deps/nghttp2/lib/CMakeLists.txt @@ -47,7 +47,29 @@ if(WIN32) set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif() -set(EXPORT_SET "${PROJECT_NAME}-targets") +set(NGHTTP2_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") +set(NGHTTP2_VERSION_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") +set(NGHTTP2_PROJECT_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") +set(NGHTTP2_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +set(NGHTTP2_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") +set(NGHTTP2_NAMESPACE "${PROJECT_NAME}::") +set(NGHTTP2_VERSION ${PROJECT_VERSION}) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${NGHTTP2_VERSION_CONFIG}" VERSION ${NGHTTP2_VERSION} COMPATIBILITY SameMajorVersion +) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.in" "${NGHTTP2_PROJECT_CONFIG}" @ONLY) + +# Install cmake config files +install( + FILES "${NGHTTP2_PROJECT_CONFIG}" "${NGHTTP2_VERSION_CONFIG}" + DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}") + +install( + EXPORT "${NGHTTP2_TARGETS_EXPORT_NAME}" + NAMESPACE "${NGHTTP2_NAMESPACE}" + DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}") # Public shared library if(BUILD_SHARED_LIBS) @@ -65,7 +87,11 @@ if(BUILD_SHARED_LIBS) $ ) - install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET}) + install(TARGETS ${SHARED_LIB} + EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME} + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") list(APPEND nghttp2_exports ${SHARED_LIB}) endif() @@ -87,7 +113,9 @@ if(BUILD_STATIC_LIBS) target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB") - install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET}) + install(TARGETS ${STATIC_LIB} + EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME} + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") list(APPEND nghttp2_exports ${STATIC_LIB}) endif() @@ -97,11 +125,7 @@ else() set(LIB_SELECTED ${STATIC_LIB}) endif() -add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED}) +add_library(nghttp2 ALIAS ${LIB_SELECTED}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - -install(EXPORT ${EXPORT_SET} - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} - NAMESPACE ${PROJECT_NAME}::) diff --git a/deps/nghttp2/lib/Makefile.am b/deps/nghttp2/lib/Makefile.am index 1168c1e6135661..3a743df6ae72e5 100644 --- a/deps/nghttp2/lib/Makefile.am +++ b/deps/nghttp2/lib/Makefile.am @@ -22,7 +22,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in +EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in config.cmake.in AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG) AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \ diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in index 7a4cb5e97404b6..bb458a182c9f6d 100644 --- a/deps/nghttp2/lib/Makefile.in +++ b/deps/nghttp2/lib/Makefile.in @@ -360,6 +360,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@ LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ +LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS = @LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS@ +LIBNGTCP2_CRYPTO_LIBRESSL_LIBS = @LIBNGTCP2_CRYPTO_LIBRESSL_LIBS@ LIBNGTCP2_CRYPTO_OSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ LIBNGTCP2_CRYPTO_OSSL_LIBS = @LIBNGTCP2_CRYPTO_OSSL_LIBS@ LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ @@ -494,7 +496,7 @@ top_srcdir = @top_srcdir@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in +EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in config.cmake.in AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG) AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \ @DEFS@ diff --git a/deps/nghttp2/lib/config.cmake.in b/deps/nghttp2/lib/config.cmake.in new file mode 100644 index 00000000000000..0b677718f462d6 --- /dev/null +++ b/deps/nghttp2/lib/config.cmake.in @@ -0,0 +1,3 @@ +include(CMakeFindDependencyMacro) + +include("${CMAKE_CURRENT_LIST_DIR}/@NGHTTP2_TARGETS_EXPORT_NAME@.cmake") diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in index 7504f8e7c75b52..a4687390385ce6 100644 --- a/deps/nghttp2/lib/includes/Makefile.in +++ b/deps/nghttp2/lib/includes/Makefile.in @@ -265,6 +265,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@ LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ +LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS = @LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS@ +LIBNGTCP2_CRYPTO_LIBRESSL_LIBS = @LIBNGTCP2_CRYPTO_LIBRESSL_LIBS@ LIBNGTCP2_CRYPTO_OSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ LIBNGTCP2_CRYPTO_OSSL_LIBS = @LIBNGTCP2_CRYPTO_OSSL_LIBS@ LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h index 3d91af55109cc8..19c1874f23a3ca 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -2039,18 +2039,19 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session, /** * @functypedef * - * Callback function invoked when a invalid header name/value pair is + * Callback function invoked when an invalid header name/value pair is * received for the |frame|. * * The parameter and behaviour are similar to * :type:`nghttp2_on_header_callback`. The difference is that this - * callback is only invoked when a invalid header name/value pair is - * received which is treated as stream error if this callback is not - * set. Only invalid regular header field are passed to this - * callback. In other words, invalid pseudo header field is not - * passed to this callback. Also header fields which includes upper - * cased latter are also treated as error without passing them to this - * callback. + * callback is only invoked when an invalid header name/value pair is + * received which is treated as stream error if this callback returns + * :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` and + * :type:`nghttp2_on_invalid_header_callback2` is not set. Only + * invalid regular header field are passed to this callback. In other + * words, invalid pseudo header field is not passed to this callback. + * Also header fields which includes upper cased latter are also + * treated as error without passing them to this callback. * * This callback is only considered if HTTP messaging validation is * turned on (which is on by default, see @@ -2076,17 +2077,18 @@ typedef int (*nghttp2_on_invalid_header_callback)( /** * @functypedef * - * Callback function invoked when a invalid header name/value pair is + * Callback function invoked when an invalid header name/value pair is * received for the |frame|. * * The parameter and behaviour are similar to * :type:`nghttp2_on_header_callback2`. The difference is that this - * callback is only invoked when a invalid header name/value pair is - * received which is silently ignored if this callback is not set. - * Only invalid regular header field are passed to this callback. In - * other words, invalid pseudo header field is not passed to this - * callback. Also header fields which includes upper cased latter are - * also treated as error without passing them to this callback. + * callback is only invoked when an invalid header name/value pair is + * received which is silently ignored if neither this callback nor + * :type:`nghttp2_on_invalid_header_callback` is set. Only invalid + * regular header field are passed to this callback. In other words, + * invalid pseudo header field is not passed to this callback. Also + * header fields which includes upper cased latter are also treated as + * error without passing them to this callback. * * This callback is only considered if HTTP messaging validation is * turned on (which is on by default, see @@ -2445,6 +2447,15 @@ typedef int (*nghttp2_error_callback2)(nghttp2_session *session, int lib_error_code, const char *msg, size_t len, void *user_data); +/** + * @functypedef + * + * Callback function invoked when unpredictable data of |destlen| + * bytes are needed. The implementation must write unpredictable data + * of |destlen| bytes into the buffer pointed by |dest|. + */ +typedef void (*nghttp2_rand_callback)(uint8_t *dest, size_t destlen); + struct nghttp2_session_callbacks; /** @@ -2649,7 +2660,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2( /** * @function * - * Sets callback function invoked when a invalid header name/value + * Sets callback function invoked when an invalid header name/value * pair is received. If both * `nghttp2_session_callbacks_set_on_invalid_header_callback()` and * `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are @@ -2662,7 +2673,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback( /** * @function * - * Sets callback function invoked when a invalid header name/value + * Sets callback function invoked when an invalid header name/value * pair is received. */ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2( @@ -2833,6 +2844,18 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback( NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2( nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2); +/** + * @function + * + * Sets callback function invoked when unpredictable data is needed. + * Although this callback is optional due to the backward + * compatibility, it is recommended to specify it to harden the + * runtime behavior against suspicious activities of a remote + * endpoint. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_rand_callback( + nghttp2_session_callbacks *cbs, nghttp2_rand_callback rand_callback); + /** * @functypedef * @@ -3218,6 +3241,23 @@ nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val); +/** + * @function + * + * This function sets the rate limit for the "glitches", the + * suspicious activities from a remote endpoint. It is a token-bucket + * based rate limiter. |burst| specifies the number of tokens that is + * initially available. The maximum number of tokens is capped to + * this value. |rate| specifies the number of tokens that are + * regenerated per second. When a suspicious activity is detected, + * some amount of tokens are consumed. If there is no token + * available, GOAWAY is sent to tear down the connection. |burst| and + * |rate| default to 1000 and 33 respectively. + */ +NGHTTP2_EXTERN void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option, + uint64_t burst, + uint64_t rate); + /** * @function * diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index 776c4924276b85..bd5e6c28723232 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.66.0" +#define NGHTTP2_VERSION "1.67.1" /** * @macro @@ -37,6 +37,6 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x014200 +#define NGHTTP2_VERSION_NUM 0x014301 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_callbacks.c b/deps/nghttp2/lib/nghttp2_callbacks.c index 32fedd52d85a3f..162ca6bd4b5332 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.c +++ b/deps/nghttp2/lib/nghttp2_callbacks.c @@ -201,3 +201,8 @@ void nghttp2_session_callbacks_set_error_callback2( nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) { cbs->error_callback2 = error_callback2; } + +void nghttp2_session_callbacks_set_rand_callback( + nghttp2_session_callbacks *cbs, nghttp2_rand_callback rand_callback) { + cbs->rand_callback = rand_callback; +} diff --git a/deps/nghttp2/lib/nghttp2_callbacks.h b/deps/nghttp2/lib/nghttp2_callbacks.h index a611f485481e7c..ad515970c48a36 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.h +++ b/deps/nghttp2/lib/nghttp2_callbacks.h @@ -151,6 +151,7 @@ struct nghttp2_session_callbacks { nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback; nghttp2_error_callback error_callback; nghttp2_error_callback2 error_callback2; + nghttp2_rand_callback rand_callback; }; #endif /* NGHTTP2_CALLBACKS_H */ diff --git a/deps/nghttp2/lib/nghttp2_int.h b/deps/nghttp2/lib/nghttp2_int.h index b23585ccb27da2..5ee6b313a01631 100644 --- a/deps/nghttp2/lib/nghttp2_int.h +++ b/deps/nghttp2/lib/nghttp2_int.h @@ -52,7 +52,11 @@ typedef enum { * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke * nghttp2_on_invalid_header_callback. */ - NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106 + NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106, + /* + * Cancel pushed stream. + */ + NGHTTP2_ERR_PUSH_CANCEL = -107, } nghttp2_internal_error; #endif /* NGHTTP2_INT_H */ diff --git a/deps/nghttp2/lib/nghttp2_map.c b/deps/nghttp2/lib/nghttp2_map.c index ee6bb1967ec6da..f89f310319a1a3 100644 --- a/deps/nghttp2/lib/nghttp2_map.c +++ b/deps/nghttp2/lib/nghttp2_map.c @@ -31,12 +31,13 @@ #include "nghttp2_helper.h" -#define NGHTTP2_INITIAL_TABLE_LENBITS 4 +#define NGHTTP2_INITIAL_HASHBITS 4 -void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) { +void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem) { map->mem = mem; map->hashbits = 0; map->table = NULL; + map->seed = seed; map->size = 0; } @@ -77,8 +78,13 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr), return 0; } -static size_t hash(nghttp2_map_key_type key, size_t bits) { - return (size_t)(((uint32_t)key * 2654435769u) >> (32 - bits)); +static size_t map_hash(const nghttp2_map *map, nghttp2_map_key_type key) { + /* hasher from + https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs + We do not perform finalization here because we use top bits + anyway. */ + uint32_t h = ((uint32_t)key + map->seed) * 0x93d765dd; + return (size_t)((h * 2654435769u) >> (32 - map->hashbits)); } static void map_bucket_swap(nghttp2_map_bucket *a, nghttp2_map_bucket *b) { @@ -109,24 +115,28 @@ void nghttp2_map_print_distance(const nghttp2_map *map) { continue; } - idx = hash(bkt->key, map->hashbits); + idx = map_hash(map, bkt->key); fprintf(stderr, "@%zu hash=%zu key=%d base=%zu distance=%u\n", i, - hash(bkt->key, map->hashbits), bkt->key, idx, bkt->psl); + map_hash(map, bkt->key), bkt->key, idx, bkt->psl); } } -#endif /* !WIN32 */ - -static int insert(nghttp2_map_bucket *table, size_t hashbits, - nghttp2_map_key_type key, void *data) { - size_t idx = hash(key, hashbits); - nghttp2_map_bucket b = {0, key, data}, *bkt; - size_t mask = (1u << hashbits) - 1; +#endif /* !defined(WIN32) */ + +static int map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) { + size_t idx = map_hash(map, key); + nghttp2_map_bucket b = { + .key = key, + .data = data, + }; + nghttp2_map_bucket *bkt; + size_t mask = (1u << map->hashbits) - 1; for (;;) { - bkt = &table[idx]; + bkt = &map->table[idx]; if (bkt->data == NULL) { *bkt = b; + ++map->size; return 0; } @@ -147,15 +157,19 @@ static int insert(nghttp2_map_bucket *table, size_t hashbits, static int map_resize(nghttp2_map *map, size_t new_hashbits) { size_t i; - nghttp2_map_bucket *new_table; nghttp2_map_bucket *bkt; size_t tablelen; int rv; + nghttp2_map new_map = { + .table = nghttp2_mem_calloc(map->mem, 1u << new_hashbits, + sizeof(nghttp2_map_bucket)), + .mem = map->mem, + .seed = map->seed, + .hashbits = new_hashbits, + }; (void)rv; - new_table = nghttp2_mem_calloc(map->mem, 1u << new_hashbits, - sizeof(nghttp2_map_bucket)); - if (new_table == NULL) { + if (new_map.table == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -168,15 +182,15 @@ static int map_resize(nghttp2_map *map, size_t new_hashbits) { continue; } - rv = insert(new_table, new_hashbits, bkt->key, bkt->data); + rv = map_insert(&new_map, bkt->key, bkt->data); assert(0 == rv); } } nghttp2_mem_free(map->mem, map->table); + map->table = new_map.table; map->hashbits = new_hashbits; - map->table = new_table; return 0; } @@ -186,30 +200,28 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) { assert(data); - /* Load factor is 0.75 */ + /* Load factor is 7/8 */ /* Under the very initial condition, that is map->size == 0 and - map->hashbits == 0, 4 > 3 still holds nicely. */ - if ((map->size + 1) * 4 > (1u << map->hashbits) * 3) { + map->hashbits == 0, 8 > 7 still holds nicely. */ + if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) { if (map->hashbits) { rv = map_resize(map, map->hashbits + 1); if (rv != 0) { return rv; } } else { - rv = map_resize(map, NGHTTP2_INITIAL_TABLE_LENBITS); + rv = map_resize(map, NGHTTP2_INITIAL_HASHBITS); if (rv != 0) { return rv; } } } - rv = insert(map->table, map->hashbits, key, data); + rv = map_insert(map, key, data); if (rv != 0) { return rv; } - ++map->size; - return 0; } @@ -223,7 +235,7 @@ void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) { return NULL; } - idx = hash(key, map->hashbits); + idx = map_hash(map, key); mask = (1u << map->hashbits) - 1; for (;;) { @@ -252,7 +264,7 @@ int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - idx = hash(key, map->hashbits); + idx = map_hash(map, key); mask = (1u << map->hashbits) - 1; for (;;) { diff --git a/deps/nghttp2/lib/nghttp2_map.h b/deps/nghttp2/lib/nghttp2_map.h index 5adfb78d027679..e45685bce71768 100644 --- a/deps/nghttp2/lib/nghttp2_map.h +++ b/deps/nghttp2/lib/nghttp2_map.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -47,6 +47,7 @@ typedef struct nghttp2_map_bucket { typedef struct nghttp2_map { nghttp2_map_bucket *table; nghttp2_mem *mem; + uint32_t seed; size_t size; size_t hashbits; } nghttp2_map; @@ -54,7 +55,7 @@ typedef struct nghttp2_map { /* * nghttp2_map_init initializes the map |map|. */ -void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem); +void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem); /* * nghttp2_map_free deallocates any resources allocated for |map|. @@ -123,6 +124,6 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr), #ifndef WIN32 void nghttp2_map_print_distance(const nghttp2_map *map); -#endif /* !WIN32 */ +#endif /* !defined(WIN32) */ -#endif /* NGHTTP2_MAP_H */ +#endif /* !defined(NGHTTP2_MAP_H) */ diff --git a/deps/nghttp2/lib/nghttp2_option.c b/deps/nghttp2/lib/nghttp2_option.c index 02a24eee6b2605..7e44a241ba1eec 100644 --- a/deps/nghttp2/lib/nghttp2_option.c +++ b/deps/nghttp2/lib/nghttp2_option.c @@ -155,3 +155,10 @@ void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) { option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS; option->max_continuations = val; } + +void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option, + uint64_t burst, uint64_t rate) { + option->opt_set_mask |= NGHTTP2_OPT_GLITCH_RATE_LIMIT; + option->glitch_burst = burst; + option->glitch_rate = rate; +} diff --git a/deps/nghttp2/lib/nghttp2_option.h b/deps/nghttp2/lib/nghttp2_option.h index c89cb97f8bb685..78fa21e4a77ac8 100644 --- a/deps/nghttp2/lib/nghttp2_option.h +++ b/deps/nghttp2/lib/nghttp2_option.h @@ -72,6 +72,7 @@ typedef enum { NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14, NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15, NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16, + NGHTTP2_OPT_GLITCH_RATE_LIMIT = 1 << 17, } nghttp2_option_flag; /** @@ -83,6 +84,11 @@ struct nghttp2_option { */ uint64_t stream_reset_burst; uint64_t stream_reset_rate; + /** + * NGHTTP2_OPT_GLITCH_RATE_LIMIT + */ + uint64_t glitch_burst; + uint64_t glitch_rate; /** * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH */ diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index dc1a00cf576917..a7ab61d29a55d2 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -438,6 +438,7 @@ static int session_new(nghttp2_session **session_ptr, size_t max_deflate_dynamic_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; size_t i; + uint32_t map_seed; if (mem == NULL) { mem = nghttp2_mem_default(); @@ -474,6 +475,10 @@ static int session_new(nghttp2_session **session_ptr, NGHTTP2_DEFAULT_STREAM_RESET_BURST, NGHTTP2_DEFAULT_STREAM_RESET_RATE); + nghttp2_ratelim_init(&(*session_ptr)->glitch_ratelim, + NGHTTP2_DEFAULT_GLITCH_BURST, + NGHTTP2_DEFAULT_GLITCH_RATE); + if (server) { (*session_ptr)->server = 1; } @@ -566,6 +571,11 @@ static int session_new(nghttp2_session **session_ptr, if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) { (*session_ptr)->max_continuations = option->max_continuations; } + + if (option->opt_set_mask & NGHTTP2_OPT_GLITCH_RATE_LIMIT) { + nghttp2_ratelim_init(&(*session_ptr)->glitch_ratelim, + option->glitch_burst, option->glitch_rate); + } } rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, @@ -594,7 +604,13 @@ static int session_new(nghttp2_session **session_ptr, goto fail_aob_framebuf; } - nghttp2_map_init(&(*session_ptr)->streams, mem); + if (callbacks->rand_callback) { + callbacks->rand_callback((uint8_t *)&map_seed, sizeof(map_seed)); + } else { + map_seed = 0; + } + + nghttp2_map_init(&(*session_ptr)->streams, map_seed, mem); active_outbound_item_reset(&(*session_ptr)->aob, mem); @@ -3256,7 +3272,9 @@ static int session_call_on_invalid_header(nghttp2_session *session, session, frame, nv->name->base, nv->name->len, nv->value->base, nv->value->len, nv->flags, session->user_data); } else { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + /* If both callbacks are not set, the invalid field nv is + ignored. */ + return 0; } if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -3341,6 +3359,10 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_MESSAGING: return NGHTTP2_PROTOCOL_ERROR; + case NGHTTP2_ERR_INTERNAL: + return NGHTTP2_INTERNAL_ERROR; + case NGHTTP2_ERR_PUSH_CANCEL: + return NGHTTP2_CANCEL; default: return NGHTTP2_INTERNAL_ERROR; } @@ -3367,17 +3389,32 @@ static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session, return 0; } +static int session_update_glitch_ratelim(nghttp2_session *session) { + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) { + return 0; + } + + nghttp2_ratelim_update(&session->glitch_ratelim, nghttp2_time_now_sec()); + + if (nghttp2_ratelim_drain(&session->glitch_ratelim, 1) == 0) { + return 0; + } + + return nghttp2_session_terminate_session(session, NGHTTP2_ENHANCE_YOUR_CALM); +} + static int session_handle_invalid_stream2(nghttp2_session *session, int32_t stream_id, nghttp2_frame *frame, int lib_error_code) { int rv; + rv = nghttp2_session_add_rst_stream( session, stream_id, get_error_code_from_lib_error_code(lib_error_code)); if (rv != 0) { return rv; } - if (session->callbacks.on_invalid_frame_recv_callback) { + if (frame && session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( session, frame, lib_error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3532,7 +3569,29 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, rv2 = session_call_on_invalid_header(session, frame, &nv); if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = NGHTTP2_ERR_HTTP_HEADER; + DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + rv = session_call_error_callback( + session, NGHTTP2_ERR_HTTP_HEADER, + "Invalid HTTP header field was received: frame type: " + "%u, stream: %d, name: [%.*s], value: [%.*s]", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = session_handle_invalid_stream2( + session, subject_stream->stream_id, frame, + NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } else { if (rv2 != 0) { return rv2; @@ -3572,13 +3631,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, return rv; } - rv = - session_handle_invalid_stream2(session, subject_stream->stream_id, - frame, NGHTTP2_ERR_HTTP_HEADER); - if (nghttp2_is_fatal(rv)) { - return rv; - } - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + return nghttp2_session_terminate_session(session, + NGHTTP2_PROTOCOL_ERROR); } } if (rv == 0) { @@ -3691,27 +3745,7 @@ static int session_after_header_block_received(nghttp2_session *session) { } } if (rv != 0) { - int32_t stream_id; - - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - stream_id = frame->push_promise.promised_stream_id; - } else { - stream_id = frame->hd.stream_id; - } - - rv = session_handle_invalid_stream2(session, stream_id, frame, - NGHTTP2_ERR_HTTP_MESSAGING); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (frame->hd.type == NGHTTP2_HEADERS && - (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - /* Don't call nghttp2_session_close_stream_if_shut_rdwr - because RST_STREAM has been submitted. */ - } - return 0; + return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); } } @@ -4047,8 +4081,7 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } /* If window size gets positive, push deferred DATA frame to @@ -4074,6 +4107,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_remote_initial_window_size(nghttp2_session *session, @@ -4097,8 +4132,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } if (stream->window_update_queued) { @@ -4132,6 +4166,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_local_initial_window_size(nghttp2_session *session, @@ -4518,9 +4554,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session->max_incoming_reserved_streams) { /* Currently, client does not retain closed stream, so we don't check NGHTTP2_SHUT_RD condition here. */ - - rv = nghttp2_session_add_rst_stream( - session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); + rv = session_handle_invalid_stream2(session, + frame->push_promise.promised_stream_id, + NULL, NGHTTP2_ERR_PUSH_CANCEL); if (rv != 0) { return rv; } @@ -4677,8 +4713,9 @@ static int session_on_stream_window_update_received(nghttp2_session *session, } if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < stream->remote_window_size) { - return session_handle_invalid_stream(session, frame, - NGHTTP2_ERR_FLOW_CONTROL); + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FLOW_CONTROL, + "WINDOW_UPDATE: window size overflow"); } stream->remote_window_size += frame->window_update.window_size_increment; @@ -4908,16 +4945,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session, if (session_enforce_http_messaging(session) && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if (nghttp2_http_on_remote_end_stream(stream) != 0) { - rv = nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_PROTOCOL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - /* Don't call nghttp2_session_close_stream_if_shut_rdwr because - RST_STREAM has been submitted. */ - return 0; + return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); } } @@ -4975,8 +5003,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, stream->local_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_terminate_session(session, + NGHTTP2_FLOW_CONTROL_ERROR); } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ @@ -5444,6 +5472,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (rv == NGHTTP2_ERR_IGN_PAYLOAD) { DEBUGF("recv: DATA not allowed stream_id=%d\n", iframe->frame.hd.stream_id); + + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + iframe->state = NGHTTP2_IB_IGN_DATA; break; } @@ -5469,6 +5507,20 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; } + /* Empty DATA frame without END_STREAM flag set is + suspicious. */ + if (iframe->payloadleft == 0 && + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + } + iframe->state = NGHTTP2_IB_READ_DATA; break; } @@ -5535,8 +5587,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -5545,6 +5597,15 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; break; } @@ -5565,6 +5626,18 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; } + /* This is deprecated RFC 7540 priorities mechanism which is + very unpopular. We do not expect it is received so + frequently. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + iframe->state = NGHTTP2_IB_READ_NBYTE; inbound_frame_set_mark(iframe, NGHTTP2_PRIORITY_SPECLEN); @@ -5737,8 +5810,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (check_ext_type_set(session->user_recv_ext_types, iframe->frame.hd.type)) { if (!session->callbacks.unpack_extension_callback) { - /* Silently ignore unknown frame type. */ + /* Receiving too frequent unknown frames is suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + + /* Silently ignore unknown frame type. */ busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; @@ -5850,6 +5932,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; } + /* Receiving too frequent PRIORITY_UPDATE is + suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + if (iframe->payloadleft > sizeof(iframe->raw_sbuf)) { busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; @@ -5863,6 +5956,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; default: + /* Receiving too frequent unknown frames is suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; @@ -5949,8 +6052,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -5959,6 +6062,15 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; break; } @@ -6024,9 +6136,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.push_promise.promised_stream_id, - NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.push_promise.promised_stream_id, NULL, + NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6204,12 +6316,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->payloadleft -= hd_proclen; /* Use promised stream ID for PUSH_PROMISE */ - rv = nghttp2_session_add_rst_stream( + rv = session_handle_invalid_stream2( session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE ? iframe->frame.push_promise.promised_stream_id : iframe->frame.hd.stream_id, - NGHTTP2_INTERNAL_ERROR); + NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6256,6 +6368,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } session_inbound_frame_reset(session); @@ -6481,6 +6597,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } busy = 1; @@ -6497,6 +6617,20 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->frame.data.padlen = (size_t)padlen; + /* Empty DATA frame without END_STREAM flag set is + suspicious. */ + if (iframe->payloadleft == 0 && + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + } + iframe->state = NGHTTP2_IB_READ_DATA; break; @@ -6539,6 +6673,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + data_readlen = inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen); @@ -6568,28 +6706,13 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - /* Consume all data for connection immediately here */ - rv = session_update_connection_consumed_size( - session, (size_t)data_readlen); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (iframe->state == NGHTTP2_IB_IGN_DATA) { - return (nghttp2_ssize)inlen; - } - } - - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + rv = nghttp2_session_terminate_session(session, + NGHTTP2_PROTOCOL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } - busy = 1; - iframe->state = NGHTTP2_IB_IGN_DATA; - break; + + return (nghttp2_ssize)inlen; } } if (session->callbacks.on_data_chunk_recv_callback) { @@ -6616,6 +6739,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index 419d23b5a9617e..25f300d23f131c 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -106,6 +106,10 @@ typedef struct { #define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000 #define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33 +/* The default values for glitch rate limiter. */ +#define NGHTTP2_DEFAULT_GLITCH_BURST 1000 +#define NGHTTP2_DEFAULT_GLITCH_RATE 33 + /* The default max number of CONTINUATION frames following an incoming HEADER frame. */ #define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8 @@ -229,6 +233,8 @@ struct nghttp2_session { /* Stream reset rate limiter. If receiving excessive amount of stream resets, GOAWAY will be sent. */ nghttp2_ratelim stream_reset_ratelim; + /* Rate limiter for all kinds of glitches. */ + nghttp2_ratelim glitch_ratelim; /* Sequential number across all streams to process streams in FIFO. */ uint64_t stream_seq; diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index 5c6390fa759fd8..8a90f714e4a4b5 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -487,7 +487,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags, return 0; fail_item_malloc: - free(buf); + nghttp2_mem_free(mem, buf); return rv; } @@ -570,7 +570,7 @@ int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags, return 0; fail_item_malloc: - free(ov_copy); + nghttp2_mem_free(mem, ov_copy); return rv; } @@ -642,7 +642,7 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags, return 0; fail_item_malloc: - free(buf); + nghttp2_mem_free(mem, buf); return rv; } From ee9e73de3e0de39ca13fd0856e2327b415efb8ec Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 26 Oct 2025 21:32:37 +0100 Subject: [PATCH 04/10] deps: nghttp2: revert 7784fa979d0b This commit reverts "Make error handling robust". Without this revert, we are getting timeouts, crashes, and different error codes in `parallel/test-http2-*`. Refs: https://github.com/nghttp2/nghttp2/commit/7784fa979d0bcf801a35f1afbb25fb048d815cd7 PR-URL: https://github.com/nodejs/node/pull/59790 Reviewed-By: Antoine du Hamel Reviewed-By: Trivikram Kamat (cherry picked from commit 408aba6190367d15c34d0437c60c480fe022852d) --- deps/nghttp2/lib/nghttp2_int.h | 6 +- deps/nghttp2/lib/nghttp2_session.c | 158 +++++++++++++++-------------- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/deps/nghttp2/lib/nghttp2_int.h b/deps/nghttp2/lib/nghttp2_int.h index 5ee6b313a01631..b23585ccb27da2 100644 --- a/deps/nghttp2/lib/nghttp2_int.h +++ b/deps/nghttp2/lib/nghttp2_int.h @@ -52,11 +52,7 @@ typedef enum { * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke * nghttp2_on_invalid_header_callback. */ - NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106, - /* - * Cancel pushed stream. - */ - NGHTTP2_ERR_PUSH_CANCEL = -107, + NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106 } nghttp2_internal_error; #endif /* NGHTTP2_INT_H */ diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index a7ab61d29a55d2..a53c7420b36952 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -3272,9 +3272,7 @@ static int session_call_on_invalid_header(nghttp2_session *session, session, frame, nv->name->base, nv->name->len, nv->value->base, nv->value->len, nv->flags, session->user_data); } else { - /* If both callbacks are not set, the invalid field nv is - ignored. */ - return 0; + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -3359,10 +3357,6 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_MESSAGING: return NGHTTP2_PROTOCOL_ERROR; - case NGHTTP2_ERR_INTERNAL: - return NGHTTP2_INTERNAL_ERROR; - case NGHTTP2_ERR_PUSH_CANCEL: - return NGHTTP2_CANCEL; default: return NGHTTP2_INTERNAL_ERROR; } @@ -3414,7 +3408,7 @@ static int session_handle_invalid_stream2(nghttp2_session *session, if (rv != 0) { return rv; } - if (frame && session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( session, frame, lib_error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3569,29 +3563,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, rv2 = session_call_on_invalid_header(session, frame, &nv); if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", - frame->hd.type, frame->hd.stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base); - - rv = session_call_error_callback( - session, NGHTTP2_ERR_HTTP_HEADER, - "Invalid HTTP header field was received: frame type: " - "%u, stream: %d, name: [%.*s], value: [%.*s]", - frame->hd.type, frame->hd.stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - rv = session_handle_invalid_stream2( - session, subject_stream->stream_id, frame, - NGHTTP2_ERR_HTTP_HEADER); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + rv = NGHTTP2_ERR_HTTP_HEADER; } else { if (rv2 != 0) { return rv2; @@ -3631,8 +3603,13 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, return rv; } - return nghttp2_session_terminate_session(session, - NGHTTP2_PROTOCOL_ERROR); + rv = + session_handle_invalid_stream2(session, subject_stream->stream_id, + frame, NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } } if (rv == 0) { @@ -3745,7 +3722,27 @@ static int session_after_header_block_received(nghttp2_session *session) { } } if (rv != 0) { - return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); + int32_t stream_id; + + if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { + stream_id = frame->push_promise.promised_stream_id; + } else { + stream_id = frame->hd.stream_id; + } + + rv = session_handle_invalid_stream2(session, stream_id, frame, + NGHTTP2_ERR_HTTP_MESSAGING); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (frame->hd.type == NGHTTP2_HEADERS && + (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + /* Don't call nghttp2_session_close_stream_if_shut_rdwr + because RST_STREAM has been submitted. */ + } + return 0; } } @@ -4081,7 +4078,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return NGHTTP2_ERR_FLOW_CONTROL; + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } /* If window size gets positive, push deferred DATA frame to @@ -4107,8 +4105,6 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOW_CONTROL - * Window size gets out of range. */ static int session_update_remote_initial_window_size(nghttp2_session *session, @@ -4132,7 +4128,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return NGHTTP2_ERR_FLOW_CONTROL; + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } if (stream->window_update_queued) { @@ -4166,8 +4163,6 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOW_CONTROL - * Window size gets out of range. */ static int session_update_local_initial_window_size(nghttp2_session *session, @@ -4554,9 +4549,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session->max_incoming_reserved_streams) { /* Currently, client does not retain closed stream, so we don't check NGHTTP2_SHUT_RD condition here. */ - rv = session_handle_invalid_stream2(session, - frame->push_promise.promised_stream_id, - NULL, NGHTTP2_ERR_PUSH_CANCEL); + + rv = nghttp2_session_add_rst_stream( + session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); if (rv != 0) { return rv; } @@ -4713,9 +4708,8 @@ static int session_on_stream_window_update_received(nghttp2_session *session, } if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < stream->remote_window_size) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_FLOW_CONTROL, - "WINDOW_UPDATE: window size overflow"); + return session_handle_invalid_stream(session, frame, + NGHTTP2_ERR_FLOW_CONTROL); } stream->remote_window_size += frame->window_update.window_size_increment; @@ -4945,7 +4939,16 @@ int nghttp2_session_on_data_received(nghttp2_session *session, if (session_enforce_http_messaging(session) && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if (nghttp2_http_on_remote_end_stream(stream) != 0) { - return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); + rv = nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_PROTOCOL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + /* Don't call nghttp2_session_close_stream_if_shut_rdwr because + RST_STREAM has been submitted. */ + return 0; } } @@ -5003,8 +5006,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, stream->local_window_size); if (rv != 0) { - return nghttp2_session_terminate_session(session, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ @@ -5587,8 +5590,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6052,8 +6055,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6136,9 +6139,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.push_promise.promised_stream_id, NULL, - NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.push_promise.promised_stream_id, + NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6316,12 +6319,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->payloadleft -= hd_proclen; /* Use promised stream ID for PUSH_PROMISE */ - rv = session_handle_invalid_stream2( + rv = nghttp2_session_add_rst_stream( session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE ? iframe->frame.push_promise.promised_stream_id : iframe->frame.hd.stream_id, - NULL, NGHTTP2_ERR_INTERNAL); + NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6368,10 +6371,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } } session_inbound_frame_reset(session); @@ -6597,10 +6596,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } } busy = 1; @@ -6673,10 +6668,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - data_readlen = inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen); @@ -6706,13 +6697,28 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { - rv = nghttp2_session_terminate_session(session, - NGHTTP2_PROTOCOL_ERROR); + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + /* Consume all data for connection immediately here */ + rv = session_update_connection_consumed_size( + session, (size_t)data_readlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_DATA) { + return (nghttp2_ssize)inlen; + } + } + + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } - - return (nghttp2_ssize)inlen; + busy = 1; + iframe->state = NGHTTP2_IB_IGN_DATA; + break; } } if (session->callbacks.on_data_chunk_recv_callback) { @@ -6739,10 +6745,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - session_inbound_frame_reset(session); break; From e82413da5f49278e0a6f5bf4e796cdc95f1de8b7 Mon Sep 17 00:00:00 2001 From: nodejs-github-bot <18269663+nodejs-github-bot@users.noreply.github.com> Date: Sun, 21 Dec 2025 00:41:46 +0000 Subject: [PATCH 05/10] deps: update nghttp2 to 1.68.0 PR-URL: https://github.com/nodejs/node/pull/61136 Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: Tim Perry (cherry picked from commit 1d54921552101445928a13a9343d61c1a1aa7f59) --- .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- deps/nghttp2/lib/nghttp2_alpn.h | 4 +- deps/nghttp2/lib/nghttp2_buf.h | 4 +- deps/nghttp2/lib/nghttp2_callbacks.h | 4 +- deps/nghttp2/lib/nghttp2_debug.c | 4 +- deps/nghttp2/lib/nghttp2_debug.h | 8 +- deps/nghttp2/lib/nghttp2_extpri.h | 4 +- deps/nghttp2/lib/nghttp2_frame.h | 4 +- deps/nghttp2/lib/nghttp2_hd.h | 4 +- deps/nghttp2/lib/nghttp2_hd_huffman.h | 4 +- deps/nghttp2/lib/nghttp2_helper.h | 4 +- deps/nghttp2/lib/nghttp2_http.h | 4 +- deps/nghttp2/lib/nghttp2_int.h | 10 +- deps/nghttp2/lib/nghttp2_mem.h | 4 +- deps/nghttp2/lib/nghttp2_net.h | 16 +- deps/nghttp2/lib/nghttp2_option.h | 4 +- deps/nghttp2/lib/nghttp2_outbound_item.h | 4 +- deps/nghttp2/lib/nghttp2_pq.h | 4 +- deps/nghttp2/lib/nghttp2_priority_spec.h | 4 +- deps/nghttp2/lib/nghttp2_queue.h | 4 +- deps/nghttp2/lib/nghttp2_ratelim.h | 4 +- deps/nghttp2/lib/nghttp2_rcbuf.h | 4 +- deps/nghttp2/lib/nghttp2_session.c | 216 +++++++++++------- deps/nghttp2/lib/nghttp2_session.h | 4 +- deps/nghttp2/lib/nghttp2_stream.h | 4 +- deps/nghttp2/lib/nghttp2_submit.h | 4 +- deps/nghttp2/lib/nghttp2_time.c | 15 +- deps/nghttp2/lib/nghttp2_time.h | 4 +- deps/nghttp2/lib/nghttp2_version.c | 2 +- 29 files changed, 206 insertions(+), 153 deletions(-) diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index bd5e6c28723232..8dfe536dec9ade 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.67.1" +#define NGHTTP2_VERSION "1.68.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 0x014301 +#define NGHTTP2_VERSION_NUM 0x014400 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_alpn.h b/deps/nghttp2/lib/nghttp2_alpn.h index 09810fd821490a..ecc9ed204e9d0a 100644 --- a/deps/nghttp2/lib/nghttp2_alpn.h +++ b/deps/nghttp2/lib/nghttp2_alpn.h @@ -27,8 +27,8 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include -#endif /* NGHTTP2_ALPN_H */ +#endif /* !defined(NGHTTP2_ALPN_H) */ diff --git a/deps/nghttp2/lib/nghttp2_buf.h b/deps/nghttp2/lib/nghttp2_buf.h index 95ff3706a232a3..636aa619cb69c2 100644 --- a/deps/nghttp2/lib/nghttp2_buf.h +++ b/deps/nghttp2/lib/nghttp2_buf.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -409,4 +409,4 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs); */ size_t nghttp2_bufs_len(nghttp2_bufs *bufs); -#endif /* NGHTTP2_BUF_H */ +#endif /* !defined(NGHTTP2_BUF_H) */ diff --git a/deps/nghttp2/lib/nghttp2_callbacks.h b/deps/nghttp2/lib/nghttp2_callbacks.h index ad515970c48a36..4b45e57849b646 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.h +++ b/deps/nghttp2/lib/nghttp2_callbacks.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -154,4 +154,4 @@ struct nghttp2_session_callbacks { nghttp2_rand_callback rand_callback; }; -#endif /* NGHTTP2_CALLBACKS_H */ +#endif /* !defined(NGHTTP2_CALLBACKS_H) */ diff --git a/deps/nghttp2/lib/nghttp2_debug.c b/deps/nghttp2/lib/nghttp2_debug.c index 09dd2b28587af5..b5f33ef3a6d1a9 100644 --- a/deps/nghttp2/lib/nghttp2_debug.c +++ b/deps/nghttp2/lib/nghttp2_debug.c @@ -50,11 +50,11 @@ void nghttp2_set_debug_vprintf_callback( static_debug_vprintf_callback = debug_vprintf_callback; } -#else /* !DEBUGBUILD */ +#else /* !defined(DEBUGBUILD) */ void nghttp2_set_debug_vprintf_callback( nghttp2_debug_vprintf_callback debug_vprintf_callback) { (void)debug_vprintf_callback; } -#endif /* !DEBUGBUILD */ +#endif /* !defined(DEBUGBUILD) */ diff --git a/deps/nghttp2/lib/nghttp2_debug.h b/deps/nghttp2/lib/nghttp2_debug.h index cbb4dd57547234..26566a622dba85 100644 --- a/deps/nghttp2/lib/nghttp2_debug.h +++ b/deps/nghttp2/lib/nghttp2_debug.h @@ -27,17 +27,17 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #ifdef DEBUGBUILD # define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__) void nghttp2_debug_vprintf(const char *format, ...); -#else +#else /* !defined(DEBUGBUILD) */ # define DEBUGF(...) \ do { \ } while (0) -#endif +#endif /* !defined(DEBUGBUILD) */ -#endif /* NGHTTP2_DEBUG_H */ +#endif /* !defined(NGHTTP2_DEBUG_H) */ diff --git a/deps/nghttp2/lib/nghttp2_extpri.h b/deps/nghttp2/lib/nghttp2_extpri.h index db911972084c72..2e0391653b2c3e 100644 --- a/deps/nghttp2/lib/nghttp2_extpri.h +++ b/deps/nghttp2/lib/nghttp2_extpri.h @@ -28,7 +28,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -62,4 +62,4 @@ void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri); */ #define nghttp2_extpri_uint8_inc(PRI) (((PRI) & NGHTTP2_EXTPRI_INC_MASK) != 0) -#endif /* NGHTTP2_EXTPRI_H */ +#endif /* !defined(NGHTTP2_EXTPRI_H) */ diff --git a/deps/nghttp2/lib/nghttp2_frame.h b/deps/nghttp2/lib/nghttp2_frame.h index d58668806c432a..ed4ab2c6842e71 100644 --- a/deps/nghttp2/lib/nghttp2_frame.h +++ b/deps/nghttp2/lib/nghttp2_frame.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_hd.h" @@ -634,4 +634,4 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv); void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, size_t padlen, int framehd_only); -#endif /* NGHTTP2_FRAME_H */ +#endif /* !defined(NGHTTP2_FRAME_H) */ diff --git a/deps/nghttp2/lib/nghttp2_hd.h b/deps/nghttp2/lib/nghttp2_hd.h index 38a31a83c3891d..bdc7fad5c2b50e 100644 --- a/deps/nghttp2/lib/nghttp2_hd.h +++ b/deps/nghttp2/lib/nghttp2_hd.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -439,4 +439,4 @@ nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, */ int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx); -#endif /* NGHTTP2_HD_H */ +#endif /* !defined(NGHTTP2_HD_H) */ diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman.h b/deps/nghttp2/lib/nghttp2_hd_huffman.h index 2bfd5318165f28..df037a8b20efc3 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman.h +++ b/deps/nghttp2/lib/nghttp2_hd_huffman.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -69,4 +69,4 @@ typedef struct { extern const nghttp2_huff_sym huff_sym_table[]; extern const nghttp2_huff_decode huff_decode_table[][16]; -#endif /* NGHTTP2_HD_HUFFMAN_H */ +#endif /* !defined(NGHTTP2_HD_HUFFMAN_H) */ diff --git a/deps/nghttp2/lib/nghttp2_helper.h b/deps/nghttp2/lib/nghttp2_helper.h index f5de6290dab0e1..7d64076140ce88 100644 --- a/deps/nghttp2/lib/nghttp2_helper.h +++ b/deps/nghttp2/lib/nghttp2_helper.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include @@ -142,4 +142,4 @@ int nghttp2_should_send_window_update(int32_t local_window_size, */ uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len); -#endif /* NGHTTP2_HELPER_H */ +#endif /* !defined(NGHTTP2_HELPER_H) */ diff --git a/deps/nghttp2/lib/nghttp2_http.h b/deps/nghttp2/lib/nghttp2_http.h index d9992fe690830b..2925334c0b64e8 100644 --- a/deps/nghttp2/lib/nghttp2_http.h +++ b/deps/nghttp2/lib/nghttp2_http.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_session.h" @@ -97,4 +97,4 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream, int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value, size_t valuelen); -#endif /* NGHTTP2_HTTP_H */ +#endif /* !defined(NGHTTP2_HTTP_H) */ diff --git a/deps/nghttp2/lib/nghttp2_int.h b/deps/nghttp2/lib/nghttp2_int.h index b23585ccb27da2..d89cf154543f53 100644 --- a/deps/nghttp2/lib/nghttp2_int.h +++ b/deps/nghttp2/lib/nghttp2_int.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -52,7 +52,11 @@ typedef enum { * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke * nghttp2_on_invalid_header_callback. */ - NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106 + NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106, + /* + * Cancel pushed stream. + */ + NGHTTP2_ERR_PUSH_CANCEL = -107, } nghttp2_internal_error; -#endif /* NGHTTP2_INT_H */ +#endif /* !defined(NGHTTP2_INT_H) */ diff --git a/deps/nghttp2/lib/nghttp2_mem.h b/deps/nghttp2/lib/nghttp2_mem.h index f83dbcb8f9a588..10af7c695ef81f 100644 --- a/deps/nghttp2/lib/nghttp2_mem.h +++ b/deps/nghttp2/lib/nghttp2_mem.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -42,4 +42,4 @@ void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data); void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size); void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size); -#endif /* NGHTTP2_MEM_H */ +#endif /* !defined(NGHTTP2_MEM_H) */ diff --git a/deps/nghttp2/lib/nghttp2_net.h b/deps/nghttp2/lib/nghttp2_net.h index 521f98143e4765..0c57d947964460 100644 --- a/deps/nghttp2/lib/nghttp2_net.h +++ b/deps/nghttp2/lib/nghttp2_net.h @@ -27,28 +27,28 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #ifdef HAVE_ARPA_INET_H # include -#endif /* HAVE_ARPA_INET_H */ +#endif /* defined(HAVE_ARPA_INET_H) */ #ifdef HAVE_NETINET_IN_H # include -#endif /* HAVE_NETINET_IN_H */ +#endif /* defined(HAVE_NETINET_IN_H) */ #include -#if defined(WIN32) +#ifdef WIN32 /* Windows requires ws2_32 library for ntonl family functions. We define inline functions for those function so that we don't have dependency on that lib. */ # ifdef _MSC_VER # define STIN static __inline -# else +# else /* !defined(_MSC_VER) */ # define STIN static inline -# endif +# endif /* !defined(_MSC_VER) */ STIN uint32_t htonl(uint32_t hostlong) { uint32_t res; @@ -86,6 +86,6 @@ STIN uint16_t ntohs(uint16_t netshort) { return res; } -#endif /* WIN32 */ +#endif /* defined(WIN32) */ -#endif /* NGHTTP2_NET_H */ +#endif /* !defined(NGHTTP2_NET_H) */ diff --git a/deps/nghttp2/lib/nghttp2_option.h b/deps/nghttp2/lib/nghttp2_option.h index 78fa21e4a77ac8..711185ba2f8e82 100644 --- a/deps/nghttp2/lib/nghttp2_option.h +++ b/deps/nghttp2/lib/nghttp2_option.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -160,4 +160,4 @@ struct nghttp2_option { uint8_t user_recv_ext_types[32]; }; -#endif /* NGHTTP2_OPTION_H */ +#endif /* !defined(NGHTTP2_OPTION_H) */ diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.h b/deps/nghttp2/lib/nghttp2_outbound_item.h index 4e91750088f809..6e8e310cc475dd 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.h +++ b/deps/nghttp2/lib/nghttp2_outbound_item.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_frame.h" @@ -186,4 +186,4 @@ void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q); /* Returns the size of the queue */ #define nghttp2_outbound_queue_size(Q) ((Q)->n) -#endif /* NGHTTP2_OUTBOUND_ITEM_H */ +#endif /* !defined(NGHTTP2_OUTBOUND_ITEM_H) */ diff --git a/deps/nghttp2/lib/nghttp2_pq.h b/deps/nghttp2/lib/nghttp2_pq.h index c8d90ef2cc8f33..5dd863f86ae956 100644 --- a/deps/nghttp2/lib/nghttp2_pq.h +++ b/deps/nghttp2/lib/nghttp2_pq.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_int.h" @@ -121,4 +121,4 @@ int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg); */ void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item); -#endif /* NGHTTP2_PQ_H */ +#endif /* !defined(NGHTTP2_PQ_H) */ diff --git a/deps/nghttp2/lib/nghttp2_priority_spec.h b/deps/nghttp2/lib/nghttp2_priority_spec.h index 92ece822a8f257..158e0dcdbe6c0a 100644 --- a/deps/nghttp2/lib/nghttp2_priority_spec.h +++ b/deps/nghttp2/lib/nghttp2_priority_spec.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -39,4 +39,4 @@ */ void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec); -#endif /* NGHTTP2_PRIORITY_SPEC_H */ +#endif /* !defined(NGHTTP2_PRIORITY_SPEC_H) */ diff --git a/deps/nghttp2/lib/nghttp2_queue.h b/deps/nghttp2/lib/nghttp2_queue.h index a06fa6c7a46fc7..c63897c04bef7e 100644 --- a/deps/nghttp2/lib/nghttp2_queue.h +++ b/deps/nghttp2/lib/nghttp2_queue.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include "config.h" -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -48,4 +48,4 @@ void *nghttp2_queue_front(nghttp2_queue *queue); void *nghttp2_queue_back(nghttp2_queue *queue); int nghttp2_queue_empty(nghttp2_queue *queue); -#endif /* NGHTTP2_QUEUE_H */ +#endif /* !defined(NGHTTP2_QUEUE_H) */ diff --git a/deps/nghttp2/lib/nghttp2_ratelim.h b/deps/nghttp2/lib/nghttp2_ratelim.h index 866ed3f00aed4c..d1097f2f81c406 100644 --- a/deps/nghttp2/lib/nghttp2_ratelim.h +++ b/deps/nghttp2/lib/nghttp2_ratelim.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -54,4 +54,4 @@ void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp); succeeds, or -1. */ int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n); -#endif /* NGHTTP2_RATELIM_H */ +#endif /* !defined(NGHTTP2_RATELIM_H) */ diff --git a/deps/nghttp2/lib/nghttp2_rcbuf.h b/deps/nghttp2/lib/nghttp2_rcbuf.h index 6814e709fb4148..ef82e1b3abd744 100644 --- a/deps/nghttp2/lib/nghttp2_rcbuf.h +++ b/deps/nghttp2/lib/nghttp2_rcbuf.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -77,4 +77,4 @@ int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src, */ void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf); -#endif /* NGHTTP2_RCBUF_H */ +#endif /* !defined(NGHTTP2_RCBUF_H) */ diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index a53c7420b36952..1f4ea54c62e23e 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -3272,7 +3272,9 @@ static int session_call_on_invalid_header(nghttp2_session *session, session, frame, nv->name->base, nv->name->len, nv->value->base, nv->value->len, nv->flags, session->user_data); } else { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + /* If both callbacks are not set, the invalid field nv is + ignored. */ + return 0; } if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -3357,6 +3359,10 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_MESSAGING: return NGHTTP2_PROTOCOL_ERROR; + case NGHTTP2_ERR_INTERNAL: + return NGHTTP2_INTERNAL_ERROR; + case NGHTTP2_ERR_PUSH_CANCEL: + return NGHTTP2_CANCEL; default: return NGHTTP2_INTERNAL_ERROR; } @@ -3408,7 +3414,7 @@ static int session_handle_invalid_stream2(nghttp2_session *session, if (rv != 0) { return rv; } - if (session->callbacks.on_invalid_frame_recv_callback) { + if (frame && session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( session, frame, lib_error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3563,7 +3569,29 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, rv2 = session_call_on_invalid_header(session, frame, &nv); if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = NGHTTP2_ERR_HTTP_HEADER; + DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + rv = session_call_error_callback( + session, NGHTTP2_ERR_HTTP_HEADER, + "Invalid HTTP header field was received: frame type: " + "%u, stream: %d, name: [%.*s], value: [%.*s]", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = session_handle_invalid_stream2( + session, subject_stream->stream_id, frame, + NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } else { if (rv2 != 0) { return rv2; @@ -3603,13 +3631,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, return rv; } - rv = - session_handle_invalid_stream2(session, subject_stream->stream_id, - frame, NGHTTP2_ERR_HTTP_HEADER); - if (nghttp2_is_fatal(rv)) { - return rv; - } - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + return nghttp2_session_terminate_session(session, + NGHTTP2_PROTOCOL_ERROR); } } if (rv == 0) { @@ -3722,27 +3745,7 @@ static int session_after_header_block_received(nghttp2_session *session) { } } if (rv != 0) { - int32_t stream_id; - - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - stream_id = frame->push_promise.promised_stream_id; - } else { - stream_id = frame->hd.stream_id; - } - - rv = session_handle_invalid_stream2(session, stream_id, frame, - NGHTTP2_ERR_HTTP_MESSAGING); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (frame->hd.type == NGHTTP2_HEADERS && - (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - /* Don't call nghttp2_session_close_stream_if_shut_rdwr - because RST_STREAM has been submitted. */ - } - return 0; + return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); } } @@ -4078,8 +4081,7 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } /* If window size gets positive, push deferred DATA frame to @@ -4105,6 +4107,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_remote_initial_window_size(nghttp2_session *session, @@ -4128,8 +4132,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } if (stream->window_update_queued) { @@ -4163,6 +4166,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_local_initial_window_size(nghttp2_session *session, @@ -4549,9 +4554,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session->max_incoming_reserved_streams) { /* Currently, client does not retain closed stream, so we don't check NGHTTP2_SHUT_RD condition here. */ - - rv = nghttp2_session_add_rst_stream( - session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); + rv = session_handle_invalid_stream2(session, + frame->push_promise.promised_stream_id, + NULL, NGHTTP2_ERR_PUSH_CANCEL); if (rv != 0) { return rv; } @@ -4708,8 +4713,9 @@ static int session_on_stream_window_update_received(nghttp2_session *session, } if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < stream->remote_window_size) { - return session_handle_invalid_stream(session, frame, - NGHTTP2_ERR_FLOW_CONTROL); + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FLOW_CONTROL, + "WINDOW_UPDATE: window size overflow"); } stream->remote_window_size += frame->window_update.window_size_increment; @@ -4939,16 +4945,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session, if (session_enforce_http_messaging(session) && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if (nghttp2_http_on_remote_end_stream(stream) != 0) { - rv = nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_PROTOCOL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - /* Don't call nghttp2_session_close_stream_if_shut_rdwr because - RST_STREAM has been submitted. */ - return 0; + return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); } } @@ -5006,8 +5003,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, stream->local_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_terminate_session(session, + NGHTTP2_FLOW_CONTROL_ERROR); } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ @@ -5590,8 +5587,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -5657,7 +5654,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, DEBUGF("recv: WINDOW_UPDATE\n"); break; } -#endif /* DEBUGBUILD */ +#endif /* defined(DEBUGBUILD) */ iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; @@ -5841,6 +5838,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, case NGHTTP2_ALTSVC: if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == 0) { + /* Receiving too frequent unknown frames is suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -5852,6 +5859,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc; if (session->server) { + /* Receiving too frequent ALTSVC from client is + suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -5871,6 +5889,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, break; case NGHTTP2_ORIGIN: if (!(session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN)) { + /* Receiving too frequent unknown frames is suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -5882,6 +5910,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (session->server || iframe->frame.hd.stream_id || (iframe->frame.hd.flags & 0xf0)) { + /* Receiving too frequent invalid frames is + suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -5908,6 +5947,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, case NGHTTP2_PRIORITY_UPDATE: if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) { + /* Receiving too frequent unknown frames is suspicious. */ + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; @@ -6055,8 +6104,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6139,9 +6188,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.push_promise.promised_stream_id, - NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.push_promise.promised_stream_id, NULL, + NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6266,7 +6315,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } else { DEBUGF("recv: [IB_IGN_HEADER_BLOCK]\n"); } -#endif /* DEBUGBUILD */ +#endif /* defined(DEBUGBUILD) */ readlen = inbound_frame_payload_readlen(iframe, in, last); @@ -6319,12 +6368,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->payloadleft -= hd_proclen; /* Use promised stream ID for PUSH_PROMISE */ - rv = nghttp2_session_add_rst_stream( + rv = session_handle_invalid_stream2( session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE ? iframe->frame.push_promise.promised_stream_id : iframe->frame.hd.stream_id, - NGHTTP2_INTERNAL_ERROR); + NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6371,6 +6420,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } session_inbound_frame_reset(session); @@ -6494,7 +6547,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } else { fprintf(stderr, "recv: [IB_IGN_CONTINUATION]\n"); } -#endif /* DEBUGBUILD */ +#endif /* defined(DEBUGBUILD) */ if (++session->num_continuations > session->max_continuations) { return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS; @@ -6596,6 +6649,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } busy = 1; @@ -6668,6 +6725,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + data_readlen = inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen); @@ -6697,28 +6758,13 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - /* Consume all data for connection immediately here */ - rv = session_update_connection_consumed_size( - session, (size_t)data_readlen); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (iframe->state == NGHTTP2_IB_IGN_DATA) { - return (nghttp2_ssize)inlen; - } - } - - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + rv = nghttp2_session_terminate_session(session, + NGHTTP2_PROTOCOL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } - busy = 1; - iframe->state = NGHTTP2_IB_IGN_DATA; - break; + + return (nghttp2_ssize)inlen; } } if (session->callbacks.on_data_chunk_recv_callback) { @@ -6745,6 +6791,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index 25f300d23f131c..edbef80d397123 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_map.h" @@ -892,4 +892,4 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, size_t delta_size, int send_window_update); -#endif /* NGHTTP2_SESSION_H */ +#endif /* !defined(NGHTTP2_SESSION_H) */ diff --git a/deps/nghttp2/lib/nghttp2_stream.h b/deps/nghttp2/lib/nghttp2_stream.h index e73cd283b1dca4..603209ec645f30 100644 --- a/deps/nghttp2/lib/nghttp2_stream.h +++ b/deps/nghttp2/lib/nghttp2_stream.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include #include "nghttp2_outbound_item.h" @@ -294,4 +294,4 @@ void nghttp2_stream_attach_item(nghttp2_stream *stream, */ void nghttp2_stream_detach_item(nghttp2_stream *stream); -#endif /* NGHTTP2_STREAM */ +#endif /* !defined(NGHTTP2_STREAM_H) */ diff --git a/deps/nghttp2/lib/nghttp2_submit.h b/deps/nghttp2/lib/nghttp2_submit.h index 350ee02275902a..decf803db27c0d 100644 --- a/deps/nghttp2/lib/nghttp2_submit.h +++ b/deps/nghttp2/lib/nghttp2_submit.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -37,4 +37,4 @@ int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_data_provider_wrap *dpw); -#endif /* NGHTTP2_SUBMIT_H */ +#endif /* !defined(NGHTTP2_SUBMIT_H) */ diff --git a/deps/nghttp2/lib/nghttp2_time.c b/deps/nghttp2/lib/nghttp2_time.c index 148ccfdce81c12..18fd7bcac3771c 100644 --- a/deps/nghttp2/lib/nghttp2_time.c +++ b/deps/nghttp2/lib/nghttp2_time.c @@ -26,7 +26,7 @@ #ifdef HAVE_WINDOWS_H # include -#endif /* HAVE_WINDOWS_H */ +#endif /* defined(HAVE_WINDOWS_H) */ #include @@ -40,12 +40,11 @@ static uint64_t time_now_sec(void) { return (uint64_t)t; } -#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */ +#endif /* !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__) */ #if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__) uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; } -#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \ - HAVE_DECL_CLOCK_MONOTONIC +#elif defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC uint64_t nghttp2_time_now_sec(void) { struct timespec tp; int rv = clock_gettime(CLOCK_MONOTONIC, &tp); @@ -56,8 +55,8 @@ uint64_t nghttp2_time_now_sec(void) { return (uint64_t)tp.tv_sec; } -#else /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \ - (!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */ +#else /* (!defined(HAVE_GETTICKCOUNT64) || !defined(__CYGWIN__)) && \ + (!defined(HAVE_CLOCK_GETTIME) || !HAVE_DECL_CLOCK_MONOTONIC) */ uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); } -#endif /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \ - (!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */ +#endif /* (!defined(HAVE_GETTICKCOUNT64) || !defined(__CYGWIN__)) && \ + (!defined(HAVE_CLOCK_GETTIME) || !HAVE_DECL_CLOCK_MONOTONIC) */ diff --git a/deps/nghttp2/lib/nghttp2_time.h b/deps/nghttp2/lib/nghttp2_time.h index 03c0bbe944ee3b..a91e62ada35e7a 100644 --- a/deps/nghttp2/lib/nghttp2_time.h +++ b/deps/nghttp2/lib/nghttp2_time.h @@ -27,7 +27,7 @@ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include @@ -35,4 +35,4 @@ timepoint. If it is unable to get seconds, it returns 0. */ uint64_t nghttp2_time_now_sec(void); -#endif /* NGHTTP2_TIME_H */ +#endif /* !defined(NGHTTP2_TIME_H) */ diff --git a/deps/nghttp2/lib/nghttp2_version.c b/deps/nghttp2/lib/nghttp2_version.c index 4211f2cf8f624d..39a49ff351b9ed 100644 --- a/deps/nghttp2/lib/nghttp2_version.c +++ b/deps/nghttp2/lib/nghttp2_version.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H # include -#endif /* HAVE_CONFIG_H */ +#endif /* defined(HAVE_CONFIG_H) */ #include From 9bf88cbfdadb0acde244c9facaadcc30fe529969 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 26 Oct 2025 21:32:37 +0100 Subject: [PATCH 06/10] deps: nghttp2: revert 7784fa979d0b This commit reverts "Make error handling robust". Without this revert, we are getting timeouts, crashes, and different error codes in `parallel/test-http2-*`. Refs: https://github.com/nghttp2/nghttp2/commit/7784fa979d0bcf801a35f1afbb25fb048d815cd7 Refs: https://github.com/nodejs/node/issues/60661 PR-URL: https://github.com/nodejs/node/pull/61136 Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: Tim Perry (cherry picked from commit fb2a02f1d13e2d05157640054dd7e825fcc8c7e3) --- deps/nghttp2/lib/nghttp2_int.h | 6 +- deps/nghttp2/lib/nghttp2_session.c | 158 +++++++++++++++-------------- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/deps/nghttp2/lib/nghttp2_int.h b/deps/nghttp2/lib/nghttp2_int.h index d89cf154543f53..4e3b26860daf07 100644 --- a/deps/nghttp2/lib/nghttp2_int.h +++ b/deps/nghttp2/lib/nghttp2_int.h @@ -52,11 +52,7 @@ typedef enum { * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke * nghttp2_on_invalid_header_callback. */ - NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106, - /* - * Cancel pushed stream. - */ - NGHTTP2_ERR_PUSH_CANCEL = -107, + NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106 } nghttp2_internal_error; #endif /* !defined(NGHTTP2_INT_H) */ diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index 1f4ea54c62e23e..97d7fda1d295d5 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -3272,9 +3272,7 @@ static int session_call_on_invalid_header(nghttp2_session *session, session, frame, nv->name->base, nv->name->len, nv->value->base, nv->value->len, nv->flags, session->user_data); } else { - /* If both callbacks are not set, the invalid field nv is - ignored. */ - return 0; + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -3359,10 +3357,6 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_MESSAGING: return NGHTTP2_PROTOCOL_ERROR; - case NGHTTP2_ERR_INTERNAL: - return NGHTTP2_INTERNAL_ERROR; - case NGHTTP2_ERR_PUSH_CANCEL: - return NGHTTP2_CANCEL; default: return NGHTTP2_INTERNAL_ERROR; } @@ -3414,7 +3408,7 @@ static int session_handle_invalid_stream2(nghttp2_session *session, if (rv != 0) { return rv; } - if (frame && session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( session, frame, lib_error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3569,29 +3563,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, rv2 = session_call_on_invalid_header(session, frame, &nv); if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", - frame->hd.type, frame->hd.stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base); - - rv = session_call_error_callback( - session, NGHTTP2_ERR_HTTP_HEADER, - "Invalid HTTP header field was received: frame type: " - "%u, stream: %d, name: [%.*s], value: [%.*s]", - frame->hd.type, frame->hd.stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - rv = session_handle_invalid_stream2( - session, subject_stream->stream_id, frame, - NGHTTP2_ERR_HTTP_HEADER); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + rv = NGHTTP2_ERR_HTTP_HEADER; } else { if (rv2 != 0) { return rv2; @@ -3631,8 +3603,13 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, return rv; } - return nghttp2_session_terminate_session(session, - NGHTTP2_PROTOCOL_ERROR); + rv = + session_handle_invalid_stream2(session, subject_stream->stream_id, + frame, NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } } if (rv == 0) { @@ -3745,7 +3722,27 @@ static int session_after_header_block_received(nghttp2_session *session) { } } if (rv != 0) { - return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); + int32_t stream_id; + + if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { + stream_id = frame->push_promise.promised_stream_id; + } else { + stream_id = frame->hd.stream_id; + } + + rv = session_handle_invalid_stream2(session, stream_id, frame, + NGHTTP2_ERR_HTTP_MESSAGING); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (frame->hd.type == NGHTTP2_HEADERS && + (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + /* Don't call nghttp2_session_close_stream_if_shut_rdwr + because RST_STREAM has been submitted. */ + } + return 0; } } @@ -4081,7 +4078,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return NGHTTP2_ERR_FLOW_CONTROL; + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } /* If window size gets positive, push deferred DATA frame to @@ -4107,8 +4105,6 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOW_CONTROL - * Window size gets out of range. */ static int session_update_remote_initial_window_size(nghttp2_session *session, @@ -4132,7 +4128,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return NGHTTP2_ERR_FLOW_CONTROL; + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } if (stream->window_update_queued) { @@ -4166,8 +4163,6 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOW_CONTROL - * Window size gets out of range. */ static int session_update_local_initial_window_size(nghttp2_session *session, @@ -4554,9 +4549,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session->max_incoming_reserved_streams) { /* Currently, client does not retain closed stream, so we don't check NGHTTP2_SHUT_RD condition here. */ - rv = session_handle_invalid_stream2(session, - frame->push_promise.promised_stream_id, - NULL, NGHTTP2_ERR_PUSH_CANCEL); + + rv = nghttp2_session_add_rst_stream( + session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); if (rv != 0) { return rv; } @@ -4713,9 +4708,8 @@ static int session_on_stream_window_update_received(nghttp2_session *session, } if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < stream->remote_window_size) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_FLOW_CONTROL, - "WINDOW_UPDATE: window size overflow"); + return session_handle_invalid_stream(session, frame, + NGHTTP2_ERR_FLOW_CONTROL); } stream->remote_window_size += frame->window_update.window_size_increment; @@ -4945,7 +4939,16 @@ int nghttp2_session_on_data_received(nghttp2_session *session, if (session_enforce_http_messaging(session) && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if (nghttp2_http_on_remote_end_stream(stream) != 0) { - return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR); + rv = nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_PROTOCOL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + /* Don't call nghttp2_session_close_stream_if_shut_rdwr because + RST_STREAM has been submitted. */ + return 0; } } @@ -5003,8 +5006,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, stream->local_window_size); if (rv != 0) { - return nghttp2_session_terminate_session(session, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ @@ -5587,8 +5590,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6104,8 +6107,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6188,9 +6191,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = session_handle_invalid_stream2( - session, iframe->frame.push_promise.promised_stream_id, NULL, - NGHTTP2_ERR_INTERNAL); + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.push_promise.promised_stream_id, + NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6368,12 +6371,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->payloadleft -= hd_proclen; /* Use promised stream ID for PUSH_PROMISE */ - rv = session_handle_invalid_stream2( + rv = nghttp2_session_add_rst_stream( session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE ? iframe->frame.push_promise.promised_stream_id : iframe->frame.hd.stream_id, - NULL, NGHTTP2_ERR_INTERNAL); + NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6420,10 +6423,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } } session_inbound_frame_reset(session); @@ -6649,10 +6648,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } } busy = 1; @@ -6725,10 +6720,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - data_readlen = inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen); @@ -6758,13 +6749,28 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { - rv = nghttp2_session_terminate_session(session, - NGHTTP2_PROTOCOL_ERROR); + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + /* Consume all data for connection immediately here */ + rv = session_update_connection_consumed_size( + session, (size_t)data_readlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_DATA) { + return (nghttp2_ssize)inlen; + } + } + + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } - - return (nghttp2_ssize)inlen; + busy = 1; + iframe->state = NGHTTP2_IB_IGN_DATA; + break; } } if (session->callbacks.on_data_chunk_recv_callback) { @@ -6791,10 +6797,6 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - session_inbound_frame_reset(session); break; From 618fb83154f9e33f781a6ff4025c1009d539fe99 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 26 Apr 2026 01:03:53 +0000 Subject: [PATCH 07/10] deps: update nghttp2 to 1.69.0 PR-URL: https://github.com/nodejs/node/pull/62891 Reviewed-By: Luigi Pinca Reviewed-By: Stephen Belanger Reviewed-By: Antoine du Hamel (cherry picked from commit 5320a1b96f4820e53c33dccb3019c14cf7260af3) --- deps/nghttp2/lib/CMakeLists.txt | 2 +- deps/nghttp2/lib/includes/nghttp2/nghttp2.h | 2 +- .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- deps/nghttp2/lib/nghttp2_alpn.c | 4 +- deps/nghttp2/lib/nghttp2_frame.c | 10 + deps/nghttp2/lib/nghttp2_frame.h | 3 - deps/nghttp2/lib/nghttp2_hd.c | 17 +- deps/nghttp2/lib/nghttp2_hd_huffman.c | 23 +- deps/nghttp2/lib/nghttp2_hd_huffman.h | 14 +- deps/nghttp2/lib/nghttp2_hd_huffman_data.c | 8224 ++++++++--------- deps/nghttp2/lib/nghttp2_helper.h | 10 +- deps/nghttp2/lib/nghttp2_http.c | 3 +- deps/nghttp2/lib/nghttp2_int.h | 7 +- deps/nghttp2/lib/nghttp2_map.c | 267 +- deps/nghttp2/lib/nghttp2_map.h | 17 +- deps/nghttp2/lib/nghttp2_outbound_item.c | 12 + deps/nghttp2/lib/nghttp2_outbound_item.h | 16 +- deps/nghttp2/lib/nghttp2_session.c | 236 +- deps/nghttp2/lib/nghttp2_session.h | 4 +- deps/nghttp2/lib/nghttp2_submit.c | 6 +- 20 files changed, 4558 insertions(+), 4323 deletions(-) diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt index 98e3dbe7682fb0..3b6a4400305b31 100644 --- a/deps/nghttp2/lib/CMakeLists.txt +++ b/deps/nghttp2/lib/CMakeLists.txt @@ -51,7 +51,7 @@ set(NGHTTP2_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") set(NGHTTP2_VERSION_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") set(NGHTTP2_PROJECT_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}Config.cmake") set(NGHTTP2_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") -set(NGHTTP2_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") +set(NGHTTP2_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") set(NGHTTP2_NAMESPACE "${PROJECT_NAME}::") set(NGHTTP2_VERSION ${PROJECT_VERSION}) diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h index 19c1874f23a3ca..55baba71bdaf26 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -3252,7 +3252,7 @@ NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option, * regenerated per second. When a suspicious activity is detected, * some amount of tokens are consumed. If there is no token * available, GOAWAY is sent to tear down the connection. |burst| and - * |rate| default to 1000 and 33 respectively. + * |rate| default to 10000 and 330 respectively. */ NGHTTP2_EXTERN void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option, uint64_t burst, diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index 8dfe536dec9ade..83fabdeeb95d6e 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.68.0" +#define NGHTTP2_VERSION "1.69.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 0x014400 +#define NGHTTP2_VERSION_NUM 0x014500 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_alpn.c b/deps/nghttp2/lib/nghttp2_alpn.c index 33c5885f8d889f..025bd346594c65 100644 --- a/deps/nghttp2/lib/nghttp2_alpn.c +++ b/deps/nghttp2/lib/nghttp2_alpn.c @@ -26,6 +26,8 @@ #include +#include "nghttp2_helper.h" + static int select_alpn(const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, const char *key, unsigned int keylen) { @@ -41,7 +43,7 @@ static int select_alpn(const unsigned char **out, unsigned char *outlen, } #define NGHTTP2_HTTP_1_1_ALPN "\x8http/1.1" -#define NGHTTP2_HTTP_1_1_ALPN_LEN (sizeof(NGHTTP2_HTTP_1_1_ALPN) - 1) +#define NGHTTP2_HTTP_1_1_ALPN_LEN nghttp2_strlen_lit(NGHTTP2_HTTP_1_1_ALPN) int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen) { diff --git a/deps/nghttp2/lib/nghttp2_frame.c b/deps/nghttp2/lib/nghttp2_frame.c index edc2aaaae9ed75..264ae9d38e0260 100644 --- a/deps/nghttp2/lib/nghttp2_frame.c +++ b/deps/nghttp2/lib/nghttp2_frame.c @@ -750,6 +750,16 @@ void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, uint8_t *p; altsvc = frame->payload; + + if (payloadlen == 0) { + altsvc->origin = NULL; + altsvc->origin_len = 0; + altsvc->field_value = NULL; + altsvc->field_value_len = 0; + + return; + } + p = payload; altsvc->origin = p; diff --git a/deps/nghttp2/lib/nghttp2_frame.h b/deps/nghttp2/lib/nghttp2_frame.h index ed4ab2c6842e71..c0917c0df4cc9f 100644 --- a/deps/nghttp2/lib/nghttp2_frame.h +++ b/deps/nghttp2/lib/nghttp2_frame.h @@ -34,10 +34,7 @@ #include "nghttp2_buf.h" #define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1) -#define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1) -#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1) #define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1) -#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1) /* The number of bytes of frame header. */ #define NGHTTP2_FRAME_HDLEN 9 diff --git a/deps/nghttp2/lib/nghttp2_hd.c b/deps/nghttp2/lib/nghttp2_hd.c index ad85eed1e13e7b..5ac77dbc0ea554 100644 --- a/deps/nghttp2/lib/nghttp2_hd.c +++ b/deps/nghttp2/lib/nghttp2_hd.c @@ -35,9 +35,10 @@ /* Make scalar initialization form of nghttp2_hd_entry */ #define MAKE_STATIC_ENT(N, V, T, H) \ { \ - {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \ - {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \ - {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \ + {NULL, NULL, (uint8_t *)(N), nghttp2_strlen_lit((N)), -1}, \ + {NULL, NULL, (uint8_t *)(V), nghttp2_strlen_lit((V)), -1}, \ + {(uint8_t *)(N), (uint8_t *)(V), nghttp2_strlen_lit((N)), \ + nghttp2_strlen_lit((V)), 0}, \ T, \ H, \ } @@ -2058,8 +2059,9 @@ nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF; - rv = - nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem); + rv = nghttp2_rcbuf_new( + &inflater->namercbuf, + nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem); } else { inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME; rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem); @@ -2143,8 +2145,9 @@ nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF; - rv = - nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem); + rv = nghttp2_rcbuf_new( + &inflater->valuercbuf, + nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem); } else { inflater->state = NGHTTP2_HD_STATE_READ_VALUE; diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman.c b/deps/nghttp2/lib/nghttp2_hd_huffman.c index de2620076a6e0d..45672655f08762 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman.c +++ b/deps/nghttp2/lib/nghttp2_hd_huffman.c @@ -104,15 +104,15 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src, } void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) { - ctx->fstate = NGHTTP2_HUFF_ACCEPTED; + ctx->fstate = 0; + ctx->flags = NGHTTP2_HUFF_ACCEPTED; } nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, nghttp2_buf *buf, const uint8_t *src, size_t srclen, int final) { const uint8_t *end = src + srclen; - nghttp2_huff_decode node = {ctx->fstate, 0}; - const nghttp2_huff_decode *t = &node; + nghttp2_huff_decode t = {ctx->fstate, ctx->flags, 0}; uint8_t c; /* We use the decoding algorithm described in @@ -121,20 +121,21 @@ nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - https://github.com/nghttp2/nghttp2/files/15141264/Prefix.pdf */ for (; src != end;) { c = *src++; - t = &huff_decode_table[t->fstate & 0x1ff][c >> 4]; - if (t->fstate & NGHTTP2_HUFF_SYM) { - *buf->last++ = t->sym; + t = huff_decode_table[t.fstate][c >> 4]; + if (t.flags & NGHTTP2_HUFF_SYM) { + *buf->last++ = t.sym; } - t = &huff_decode_table[t->fstate & 0x1ff][c & 0xf]; - if (t->fstate & NGHTTP2_HUFF_SYM) { - *buf->last++ = t->sym; + t = huff_decode_table[t.fstate][c & 0xf]; + if (t.flags & NGHTTP2_HUFF_SYM) { + *buf->last++ = t.sym; } } - ctx->fstate = t->fstate; + ctx->fstate = t.fstate; + ctx->flags = t.flags; - if (final && !(ctx->fstate & NGHTTP2_HUFF_ACCEPTED)) { + if (final && !(ctx->flags & NGHTTP2_HUFF_ACCEPTED)) { return NGHTTP2_ERR_HEADER_COMP; } diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman.h b/deps/nghttp2/lib/nghttp2_hd_huffman.h index df037a8b20efc3..f898c1779c01c6 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman.h +++ b/deps/nghttp2/lib/nghttp2_hd_huffman.h @@ -34,9 +34,9 @@ typedef enum { /* FSA accepts this state as the end of huffman encoding sequence. */ - NGHTTP2_HUFF_ACCEPTED = 1 << 14, + NGHTTP2_HUFF_ACCEPTED = 1, /* This state emits symbol */ - NGHTTP2_HUFF_SYM = 1 << 15, + NGHTTP2_HUFF_SYM = 1 << 1, } nghttp2_huff_decode_flag; typedef struct { @@ -48,6 +48,7 @@ typedef struct { a special node and it is a terminal state that means decoding failed. */ uint16_t fstate; + uint8_t flags; /* symbol if NGHTTP2_HUFF_SYM flag set */ uint8_t sym; } nghttp2_huff_decode; @@ -57,6 +58,7 @@ typedef nghttp2_huff_decode huff_decode_table_type[16]; typedef struct { /* fstate is the current huffman decoding state. */ uint16_t fstate; + uint8_t flags; } nghttp2_hd_huff_decode_context; typedef struct { @@ -69,4 +71,12 @@ typedef struct { extern const nghttp2_huff_sym huff_sym_table[]; extern const nghttp2_huff_decode huff_decode_table[][16]; +/* + * nghttp2_huff_estimate_decode_length returns the estimated decoded + * length of the huffman encoded string of length |len|. + */ +static inline size_t nghttp2_huff_estimate_decode_length(size_t len) { + return len * 8 / 5; +} + #endif /* !defined(NGHTTP2_HD_HUFFMAN_H) */ diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman_data.c b/deps/nghttp2/lib/nghttp2_hd_huffman_data.c index c8f4a6fa266708..252cae0c18d971 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman_data.c +++ b/deps/nghttp2/lib/nghttp2_hd_huffman_data.c @@ -96,4885 +96,4885 @@ const nghttp2_huff_sym huff_sym_table[] = { const nghttp2_huff_decode huff_decode_table[][16] = { /* 0 */ { - {0x04, 0}, - {0x05, 0}, - {0x07, 0}, - {0x08, 0}, - {0x0b, 0}, - {0x0c, 0}, - {0x10, 0}, - {0x13, 0}, - {0x19, 0}, - {0x1c, 0}, - {0x20, 0}, - {0x23, 0}, - {0x2a, 0}, - {0x31, 0}, - {0x39, 0}, - {0x4040, 0}, + {0x04, 0, 0}, + {0x05, 0, 0}, + {0x07, 0, 0}, + {0x08, 0, 0}, + {0x0b, 0, 0}, + {0x0c, 0, 0}, + {0x10, 0, 0}, + {0x13, 0, 0}, + {0x19, 0, 0}, + {0x1c, 0, 0}, + {0x20, 0, 0}, + {0x23, 0, 0}, + {0x2a, 0, 0}, + {0x31, 0, 0}, + {0x39, 0, 0}, + {0x40, 1, 0}, }, /* 1 */ { - {0xc000, 48}, - {0xc000, 49}, - {0xc000, 50}, - {0xc000, 97}, - {0xc000, 99}, - {0xc000, 101}, - {0xc000, 105}, - {0xc000, 111}, - {0xc000, 115}, - {0xc000, 116}, - {0x0d, 0}, - {0x0e, 0}, - {0x11, 0}, - {0x12, 0}, - {0x14, 0}, - {0x15, 0}, + {0x00, 3, 48}, + {0x00, 3, 49}, + {0x00, 3, 50}, + {0x00, 3, 97}, + {0x00, 3, 99}, + {0x00, 3, 101}, + {0x00, 3, 105}, + {0x00, 3, 111}, + {0x00, 3, 115}, + {0x00, 3, 116}, + {0x0d, 0, 0}, + {0x0e, 0, 0}, + {0x11, 0, 0}, + {0x12, 0, 0}, + {0x14, 0, 0}, + {0x15, 0, 0}, }, /* 2 */ { - {0x8001, 48}, - {0xc016, 48}, - {0x8001, 49}, - {0xc016, 49}, - {0x8001, 50}, - {0xc016, 50}, - {0x8001, 97}, - {0xc016, 97}, - {0x8001, 99}, - {0xc016, 99}, - {0x8001, 101}, - {0xc016, 101}, - {0x8001, 105}, - {0xc016, 105}, - {0x8001, 111}, - {0xc016, 111}, + {0x01, 2, 48}, + {0x16, 3, 48}, + {0x01, 2, 49}, + {0x16, 3, 49}, + {0x01, 2, 50}, + {0x16, 3, 50}, + {0x01, 2, 97}, + {0x16, 3, 97}, + {0x01, 2, 99}, + {0x16, 3, 99}, + {0x01, 2, 101}, + {0x16, 3, 101}, + {0x01, 2, 105}, + {0x16, 3, 105}, + {0x01, 2, 111}, + {0x16, 3, 111}, }, /* 3 */ { - {0x8002, 48}, - {0x8009, 48}, - {0x8017, 48}, - {0xc028, 48}, - {0x8002, 49}, - {0x8009, 49}, - {0x8017, 49}, - {0xc028, 49}, - {0x8002, 50}, - {0x8009, 50}, - {0x8017, 50}, - {0xc028, 50}, - {0x8002, 97}, - {0x8009, 97}, - {0x8017, 97}, - {0xc028, 97}, + {0x02, 2, 48}, + {0x09, 2, 48}, + {0x17, 2, 48}, + {0x28, 3, 48}, + {0x02, 2, 49}, + {0x09, 2, 49}, + {0x17, 2, 49}, + {0x28, 3, 49}, + {0x02, 2, 50}, + {0x09, 2, 50}, + {0x17, 2, 50}, + {0x28, 3, 50}, + {0x02, 2, 97}, + {0x09, 2, 97}, + {0x17, 2, 97}, + {0x28, 3, 97}, }, /* 4 */ { - {0x8003, 48}, - {0x8006, 48}, - {0x800a, 48}, - {0x800f, 48}, - {0x8018, 48}, - {0x801f, 48}, - {0x8029, 48}, - {0xc038, 48}, - {0x8003, 49}, - {0x8006, 49}, - {0x800a, 49}, - {0x800f, 49}, - {0x8018, 49}, - {0x801f, 49}, - {0x8029, 49}, - {0xc038, 49}, + {0x03, 2, 48}, + {0x06, 2, 48}, + {0x0a, 2, 48}, + {0x0f, 2, 48}, + {0x18, 2, 48}, + {0x1f, 2, 48}, + {0x29, 2, 48}, + {0x38, 3, 48}, + {0x03, 2, 49}, + {0x06, 2, 49}, + {0x0a, 2, 49}, + {0x0f, 2, 49}, + {0x18, 2, 49}, + {0x1f, 2, 49}, + {0x29, 2, 49}, + {0x38, 3, 49}, }, /* 5 */ { - {0x8003, 50}, - {0x8006, 50}, - {0x800a, 50}, - {0x800f, 50}, - {0x8018, 50}, - {0x801f, 50}, - {0x8029, 50}, - {0xc038, 50}, - {0x8003, 97}, - {0x8006, 97}, - {0x800a, 97}, - {0x800f, 97}, - {0x8018, 97}, - {0x801f, 97}, - {0x8029, 97}, - {0xc038, 97}, + {0x03, 2, 50}, + {0x06, 2, 50}, + {0x0a, 2, 50}, + {0x0f, 2, 50}, + {0x18, 2, 50}, + {0x1f, 2, 50}, + {0x29, 2, 50}, + {0x38, 3, 50}, + {0x03, 2, 97}, + {0x06, 2, 97}, + {0x0a, 2, 97}, + {0x0f, 2, 97}, + {0x18, 2, 97}, + {0x1f, 2, 97}, + {0x29, 2, 97}, + {0x38, 3, 97}, }, /* 6 */ { - {0x8002, 99}, - {0x8009, 99}, - {0x8017, 99}, - {0xc028, 99}, - {0x8002, 101}, - {0x8009, 101}, - {0x8017, 101}, - {0xc028, 101}, - {0x8002, 105}, - {0x8009, 105}, - {0x8017, 105}, - {0xc028, 105}, - {0x8002, 111}, - {0x8009, 111}, - {0x8017, 111}, - {0xc028, 111}, + {0x02, 2, 99}, + {0x09, 2, 99}, + {0x17, 2, 99}, + {0x28, 3, 99}, + {0x02, 2, 101}, + {0x09, 2, 101}, + {0x17, 2, 101}, + {0x28, 3, 101}, + {0x02, 2, 105}, + {0x09, 2, 105}, + {0x17, 2, 105}, + {0x28, 3, 105}, + {0x02, 2, 111}, + {0x09, 2, 111}, + {0x17, 2, 111}, + {0x28, 3, 111}, }, /* 7 */ { - {0x8003, 99}, - {0x8006, 99}, - {0x800a, 99}, - {0x800f, 99}, - {0x8018, 99}, - {0x801f, 99}, - {0x8029, 99}, - {0xc038, 99}, - {0x8003, 101}, - {0x8006, 101}, - {0x800a, 101}, - {0x800f, 101}, - {0x8018, 101}, - {0x801f, 101}, - {0x8029, 101}, - {0xc038, 101}, + {0x03, 2, 99}, + {0x06, 2, 99}, + {0x0a, 2, 99}, + {0x0f, 2, 99}, + {0x18, 2, 99}, + {0x1f, 2, 99}, + {0x29, 2, 99}, + {0x38, 3, 99}, + {0x03, 2, 101}, + {0x06, 2, 101}, + {0x0a, 2, 101}, + {0x0f, 2, 101}, + {0x18, 2, 101}, + {0x1f, 2, 101}, + {0x29, 2, 101}, + {0x38, 3, 101}, }, /* 8 */ { - {0x8003, 105}, - {0x8006, 105}, - {0x800a, 105}, - {0x800f, 105}, - {0x8018, 105}, - {0x801f, 105}, - {0x8029, 105}, - {0xc038, 105}, - {0x8003, 111}, - {0x8006, 111}, - {0x800a, 111}, - {0x800f, 111}, - {0x8018, 111}, - {0x801f, 111}, - {0x8029, 111}, - {0xc038, 111}, + {0x03, 2, 105}, + {0x06, 2, 105}, + {0x0a, 2, 105}, + {0x0f, 2, 105}, + {0x18, 2, 105}, + {0x1f, 2, 105}, + {0x29, 2, 105}, + {0x38, 3, 105}, + {0x03, 2, 111}, + {0x06, 2, 111}, + {0x0a, 2, 111}, + {0x0f, 2, 111}, + {0x18, 2, 111}, + {0x1f, 2, 111}, + {0x29, 2, 111}, + {0x38, 3, 111}, }, /* 9 */ { - {0x8001, 115}, - {0xc016, 115}, - {0x8001, 116}, - {0xc016, 116}, - {0xc000, 32}, - {0xc000, 37}, - {0xc000, 45}, - {0xc000, 46}, - {0xc000, 47}, - {0xc000, 51}, - {0xc000, 52}, - {0xc000, 53}, - {0xc000, 54}, - {0xc000, 55}, - {0xc000, 56}, - {0xc000, 57}, + {0x01, 2, 115}, + {0x16, 3, 115}, + {0x01, 2, 116}, + {0x16, 3, 116}, + {0x00, 3, 32}, + {0x00, 3, 37}, + {0x00, 3, 45}, + {0x00, 3, 46}, + {0x00, 3, 47}, + {0x00, 3, 51}, + {0x00, 3, 52}, + {0x00, 3, 53}, + {0x00, 3, 54}, + {0x00, 3, 55}, + {0x00, 3, 56}, + {0x00, 3, 57}, }, /* 10 */ { - {0x8002, 115}, - {0x8009, 115}, - {0x8017, 115}, - {0xc028, 115}, - {0x8002, 116}, - {0x8009, 116}, - {0x8017, 116}, - {0xc028, 116}, - {0x8001, 32}, - {0xc016, 32}, - {0x8001, 37}, - {0xc016, 37}, - {0x8001, 45}, - {0xc016, 45}, - {0x8001, 46}, - {0xc016, 46}, + {0x02, 2, 115}, + {0x09, 2, 115}, + {0x17, 2, 115}, + {0x28, 3, 115}, + {0x02, 2, 116}, + {0x09, 2, 116}, + {0x17, 2, 116}, + {0x28, 3, 116}, + {0x01, 2, 32}, + {0x16, 3, 32}, + {0x01, 2, 37}, + {0x16, 3, 37}, + {0x01, 2, 45}, + {0x16, 3, 45}, + {0x01, 2, 46}, + {0x16, 3, 46}, }, /* 11 */ { - {0x8003, 115}, - {0x8006, 115}, - {0x800a, 115}, - {0x800f, 115}, - {0x8018, 115}, - {0x801f, 115}, - {0x8029, 115}, - {0xc038, 115}, - {0x8003, 116}, - {0x8006, 116}, - {0x800a, 116}, - {0x800f, 116}, - {0x8018, 116}, - {0x801f, 116}, - {0x8029, 116}, - {0xc038, 116}, + {0x03, 2, 115}, + {0x06, 2, 115}, + {0x0a, 2, 115}, + {0x0f, 2, 115}, + {0x18, 2, 115}, + {0x1f, 2, 115}, + {0x29, 2, 115}, + {0x38, 3, 115}, + {0x03, 2, 116}, + {0x06, 2, 116}, + {0x0a, 2, 116}, + {0x0f, 2, 116}, + {0x18, 2, 116}, + {0x1f, 2, 116}, + {0x29, 2, 116}, + {0x38, 3, 116}, }, /* 12 */ { - {0x8002, 32}, - {0x8009, 32}, - {0x8017, 32}, - {0xc028, 32}, - {0x8002, 37}, - {0x8009, 37}, - {0x8017, 37}, - {0xc028, 37}, - {0x8002, 45}, - {0x8009, 45}, - {0x8017, 45}, - {0xc028, 45}, - {0x8002, 46}, - {0x8009, 46}, - {0x8017, 46}, - {0xc028, 46}, + {0x02, 2, 32}, + {0x09, 2, 32}, + {0x17, 2, 32}, + {0x28, 3, 32}, + {0x02, 2, 37}, + {0x09, 2, 37}, + {0x17, 2, 37}, + {0x28, 3, 37}, + {0x02, 2, 45}, + {0x09, 2, 45}, + {0x17, 2, 45}, + {0x28, 3, 45}, + {0x02, 2, 46}, + {0x09, 2, 46}, + {0x17, 2, 46}, + {0x28, 3, 46}, }, /* 13 */ { - {0x8003, 32}, - {0x8006, 32}, - {0x800a, 32}, - {0x800f, 32}, - {0x8018, 32}, - {0x801f, 32}, - {0x8029, 32}, - {0xc038, 32}, - {0x8003, 37}, - {0x8006, 37}, - {0x800a, 37}, - {0x800f, 37}, - {0x8018, 37}, - {0x801f, 37}, - {0x8029, 37}, - {0xc038, 37}, + {0x03, 2, 32}, + {0x06, 2, 32}, + {0x0a, 2, 32}, + {0x0f, 2, 32}, + {0x18, 2, 32}, + {0x1f, 2, 32}, + {0x29, 2, 32}, + {0x38, 3, 32}, + {0x03, 2, 37}, + {0x06, 2, 37}, + {0x0a, 2, 37}, + {0x0f, 2, 37}, + {0x18, 2, 37}, + {0x1f, 2, 37}, + {0x29, 2, 37}, + {0x38, 3, 37}, }, /* 14 */ { - {0x8003, 45}, - {0x8006, 45}, - {0x800a, 45}, - {0x800f, 45}, - {0x8018, 45}, - {0x801f, 45}, - {0x8029, 45}, - {0xc038, 45}, - {0x8003, 46}, - {0x8006, 46}, - {0x800a, 46}, - {0x800f, 46}, - {0x8018, 46}, - {0x801f, 46}, - {0x8029, 46}, - {0xc038, 46}, + {0x03, 2, 45}, + {0x06, 2, 45}, + {0x0a, 2, 45}, + {0x0f, 2, 45}, + {0x18, 2, 45}, + {0x1f, 2, 45}, + {0x29, 2, 45}, + {0x38, 3, 45}, + {0x03, 2, 46}, + {0x06, 2, 46}, + {0x0a, 2, 46}, + {0x0f, 2, 46}, + {0x18, 2, 46}, + {0x1f, 2, 46}, + {0x29, 2, 46}, + {0x38, 3, 46}, }, /* 15 */ { - {0x8001, 47}, - {0xc016, 47}, - {0x8001, 51}, - {0xc016, 51}, - {0x8001, 52}, - {0xc016, 52}, - {0x8001, 53}, - {0xc016, 53}, - {0x8001, 54}, - {0xc016, 54}, - {0x8001, 55}, - {0xc016, 55}, - {0x8001, 56}, - {0xc016, 56}, - {0x8001, 57}, - {0xc016, 57}, + {0x01, 2, 47}, + {0x16, 3, 47}, + {0x01, 2, 51}, + {0x16, 3, 51}, + {0x01, 2, 52}, + {0x16, 3, 52}, + {0x01, 2, 53}, + {0x16, 3, 53}, + {0x01, 2, 54}, + {0x16, 3, 54}, + {0x01, 2, 55}, + {0x16, 3, 55}, + {0x01, 2, 56}, + {0x16, 3, 56}, + {0x01, 2, 57}, + {0x16, 3, 57}, }, /* 16 */ { - {0x8002, 47}, - {0x8009, 47}, - {0x8017, 47}, - {0xc028, 47}, - {0x8002, 51}, - {0x8009, 51}, - {0x8017, 51}, - {0xc028, 51}, - {0x8002, 52}, - {0x8009, 52}, - {0x8017, 52}, - {0xc028, 52}, - {0x8002, 53}, - {0x8009, 53}, - {0x8017, 53}, - {0xc028, 53}, + {0x02, 2, 47}, + {0x09, 2, 47}, + {0x17, 2, 47}, + {0x28, 3, 47}, + {0x02, 2, 51}, + {0x09, 2, 51}, + {0x17, 2, 51}, + {0x28, 3, 51}, + {0x02, 2, 52}, + {0x09, 2, 52}, + {0x17, 2, 52}, + {0x28, 3, 52}, + {0x02, 2, 53}, + {0x09, 2, 53}, + {0x17, 2, 53}, + {0x28, 3, 53}, }, /* 17 */ { - {0x8003, 47}, - {0x8006, 47}, - {0x800a, 47}, - {0x800f, 47}, - {0x8018, 47}, - {0x801f, 47}, - {0x8029, 47}, - {0xc038, 47}, - {0x8003, 51}, - {0x8006, 51}, - {0x800a, 51}, - {0x800f, 51}, - {0x8018, 51}, - {0x801f, 51}, - {0x8029, 51}, - {0xc038, 51}, + {0x03, 2, 47}, + {0x06, 2, 47}, + {0x0a, 2, 47}, + {0x0f, 2, 47}, + {0x18, 2, 47}, + {0x1f, 2, 47}, + {0x29, 2, 47}, + {0x38, 3, 47}, + {0x03, 2, 51}, + {0x06, 2, 51}, + {0x0a, 2, 51}, + {0x0f, 2, 51}, + {0x18, 2, 51}, + {0x1f, 2, 51}, + {0x29, 2, 51}, + {0x38, 3, 51}, }, /* 18 */ { - {0x8003, 52}, - {0x8006, 52}, - {0x800a, 52}, - {0x800f, 52}, - {0x8018, 52}, - {0x801f, 52}, - {0x8029, 52}, - {0xc038, 52}, - {0x8003, 53}, - {0x8006, 53}, - {0x800a, 53}, - {0x800f, 53}, - {0x8018, 53}, - {0x801f, 53}, - {0x8029, 53}, - {0xc038, 53}, + {0x03, 2, 52}, + {0x06, 2, 52}, + {0x0a, 2, 52}, + {0x0f, 2, 52}, + {0x18, 2, 52}, + {0x1f, 2, 52}, + {0x29, 2, 52}, + {0x38, 3, 52}, + {0x03, 2, 53}, + {0x06, 2, 53}, + {0x0a, 2, 53}, + {0x0f, 2, 53}, + {0x18, 2, 53}, + {0x1f, 2, 53}, + {0x29, 2, 53}, + {0x38, 3, 53}, }, /* 19 */ { - {0x8002, 54}, - {0x8009, 54}, - {0x8017, 54}, - {0xc028, 54}, - {0x8002, 55}, - {0x8009, 55}, - {0x8017, 55}, - {0xc028, 55}, - {0x8002, 56}, - {0x8009, 56}, - {0x8017, 56}, - {0xc028, 56}, - {0x8002, 57}, - {0x8009, 57}, - {0x8017, 57}, - {0xc028, 57}, + {0x02, 2, 54}, + {0x09, 2, 54}, + {0x17, 2, 54}, + {0x28, 3, 54}, + {0x02, 2, 55}, + {0x09, 2, 55}, + {0x17, 2, 55}, + {0x28, 3, 55}, + {0x02, 2, 56}, + {0x09, 2, 56}, + {0x17, 2, 56}, + {0x28, 3, 56}, + {0x02, 2, 57}, + {0x09, 2, 57}, + {0x17, 2, 57}, + {0x28, 3, 57}, }, /* 20 */ { - {0x8003, 54}, - {0x8006, 54}, - {0x800a, 54}, - {0x800f, 54}, - {0x8018, 54}, - {0x801f, 54}, - {0x8029, 54}, - {0xc038, 54}, - {0x8003, 55}, - {0x8006, 55}, - {0x800a, 55}, - {0x800f, 55}, - {0x8018, 55}, - {0x801f, 55}, - {0x8029, 55}, - {0xc038, 55}, + {0x03, 2, 54}, + {0x06, 2, 54}, + {0x0a, 2, 54}, + {0x0f, 2, 54}, + {0x18, 2, 54}, + {0x1f, 2, 54}, + {0x29, 2, 54}, + {0x38, 3, 54}, + {0x03, 2, 55}, + {0x06, 2, 55}, + {0x0a, 2, 55}, + {0x0f, 2, 55}, + {0x18, 2, 55}, + {0x1f, 2, 55}, + {0x29, 2, 55}, + {0x38, 3, 55}, }, /* 21 */ { - {0x8003, 56}, - {0x8006, 56}, - {0x800a, 56}, - {0x800f, 56}, - {0x8018, 56}, - {0x801f, 56}, - {0x8029, 56}, - {0xc038, 56}, - {0x8003, 57}, - {0x8006, 57}, - {0x800a, 57}, - {0x800f, 57}, - {0x8018, 57}, - {0x801f, 57}, - {0x8029, 57}, - {0xc038, 57}, + {0x03, 2, 56}, + {0x06, 2, 56}, + {0x0a, 2, 56}, + {0x0f, 2, 56}, + {0x18, 2, 56}, + {0x1f, 2, 56}, + {0x29, 2, 56}, + {0x38, 3, 56}, + {0x03, 2, 57}, + {0x06, 2, 57}, + {0x0a, 2, 57}, + {0x0f, 2, 57}, + {0x18, 2, 57}, + {0x1f, 2, 57}, + {0x29, 2, 57}, + {0x38, 3, 57}, }, /* 22 */ { - {0x1a, 0}, - {0x1b, 0}, - {0x1d, 0}, - {0x1e, 0}, - {0x21, 0}, - {0x22, 0}, - {0x24, 0}, - {0x25, 0}, - {0x2b, 0}, - {0x2e, 0}, - {0x32, 0}, - {0x35, 0}, - {0x3a, 0}, - {0x3d, 0}, - {0x41, 0}, - {0x4044, 0}, + {0x1a, 0, 0}, + {0x1b, 0, 0}, + {0x1d, 0, 0}, + {0x1e, 0, 0}, + {0x21, 0, 0}, + {0x22, 0, 0}, + {0x24, 0, 0}, + {0x25, 0, 0}, + {0x2b, 0, 0}, + {0x2e, 0, 0}, + {0x32, 0, 0}, + {0x35, 0, 0}, + {0x3a, 0, 0}, + {0x3d, 0, 0}, + {0x41, 0, 0}, + {0x44, 1, 0}, }, /* 23 */ { - {0xc000, 61}, - {0xc000, 65}, - {0xc000, 95}, - {0xc000, 98}, - {0xc000, 100}, - {0xc000, 102}, - {0xc000, 103}, - {0xc000, 104}, - {0xc000, 108}, - {0xc000, 109}, - {0xc000, 110}, - {0xc000, 112}, - {0xc000, 114}, - {0xc000, 117}, - {0x26, 0}, - {0x27, 0}, + {0x00, 3, 61}, + {0x00, 3, 65}, + {0x00, 3, 95}, + {0x00, 3, 98}, + {0x00, 3, 100}, + {0x00, 3, 102}, + {0x00, 3, 103}, + {0x00, 3, 104}, + {0x00, 3, 108}, + {0x00, 3, 109}, + {0x00, 3, 110}, + {0x00, 3, 112}, + {0x00, 3, 114}, + {0x00, 3, 117}, + {0x26, 0, 0}, + {0x27, 0, 0}, }, /* 24 */ { - {0x8001, 61}, - {0xc016, 61}, - {0x8001, 65}, - {0xc016, 65}, - {0x8001, 95}, - {0xc016, 95}, - {0x8001, 98}, - {0xc016, 98}, - {0x8001, 100}, - {0xc016, 100}, - {0x8001, 102}, - {0xc016, 102}, - {0x8001, 103}, - {0xc016, 103}, - {0x8001, 104}, - {0xc016, 104}, + {0x01, 2, 61}, + {0x16, 3, 61}, + {0x01, 2, 65}, + {0x16, 3, 65}, + {0x01, 2, 95}, + {0x16, 3, 95}, + {0x01, 2, 98}, + {0x16, 3, 98}, + {0x01, 2, 100}, + {0x16, 3, 100}, + {0x01, 2, 102}, + {0x16, 3, 102}, + {0x01, 2, 103}, + {0x16, 3, 103}, + {0x01, 2, 104}, + {0x16, 3, 104}, }, /* 25 */ { - {0x8002, 61}, - {0x8009, 61}, - {0x8017, 61}, - {0xc028, 61}, - {0x8002, 65}, - {0x8009, 65}, - {0x8017, 65}, - {0xc028, 65}, - {0x8002, 95}, - {0x8009, 95}, - {0x8017, 95}, - {0xc028, 95}, - {0x8002, 98}, - {0x8009, 98}, - {0x8017, 98}, - {0xc028, 98}, + {0x02, 2, 61}, + {0x09, 2, 61}, + {0x17, 2, 61}, + {0x28, 3, 61}, + {0x02, 2, 65}, + {0x09, 2, 65}, + {0x17, 2, 65}, + {0x28, 3, 65}, + {0x02, 2, 95}, + {0x09, 2, 95}, + {0x17, 2, 95}, + {0x28, 3, 95}, + {0x02, 2, 98}, + {0x09, 2, 98}, + {0x17, 2, 98}, + {0x28, 3, 98}, }, /* 26 */ { - {0x8003, 61}, - {0x8006, 61}, - {0x800a, 61}, - {0x800f, 61}, - {0x8018, 61}, - {0x801f, 61}, - {0x8029, 61}, - {0xc038, 61}, - {0x8003, 65}, - {0x8006, 65}, - {0x800a, 65}, - {0x800f, 65}, - {0x8018, 65}, - {0x801f, 65}, - {0x8029, 65}, - {0xc038, 65}, + {0x03, 2, 61}, + {0x06, 2, 61}, + {0x0a, 2, 61}, + {0x0f, 2, 61}, + {0x18, 2, 61}, + {0x1f, 2, 61}, + {0x29, 2, 61}, + {0x38, 3, 61}, + {0x03, 2, 65}, + {0x06, 2, 65}, + {0x0a, 2, 65}, + {0x0f, 2, 65}, + {0x18, 2, 65}, + {0x1f, 2, 65}, + {0x29, 2, 65}, + {0x38, 3, 65}, }, /* 27 */ { - {0x8003, 95}, - {0x8006, 95}, - {0x800a, 95}, - {0x800f, 95}, - {0x8018, 95}, - {0x801f, 95}, - {0x8029, 95}, - {0xc038, 95}, - {0x8003, 98}, - {0x8006, 98}, - {0x800a, 98}, - {0x800f, 98}, - {0x8018, 98}, - {0x801f, 98}, - {0x8029, 98}, - {0xc038, 98}, + {0x03, 2, 95}, + {0x06, 2, 95}, + {0x0a, 2, 95}, + {0x0f, 2, 95}, + {0x18, 2, 95}, + {0x1f, 2, 95}, + {0x29, 2, 95}, + {0x38, 3, 95}, + {0x03, 2, 98}, + {0x06, 2, 98}, + {0x0a, 2, 98}, + {0x0f, 2, 98}, + {0x18, 2, 98}, + {0x1f, 2, 98}, + {0x29, 2, 98}, + {0x38, 3, 98}, }, /* 28 */ { - {0x8002, 100}, - {0x8009, 100}, - {0x8017, 100}, - {0xc028, 100}, - {0x8002, 102}, - {0x8009, 102}, - {0x8017, 102}, - {0xc028, 102}, - {0x8002, 103}, - {0x8009, 103}, - {0x8017, 103}, - {0xc028, 103}, - {0x8002, 104}, - {0x8009, 104}, - {0x8017, 104}, - {0xc028, 104}, + {0x02, 2, 100}, + {0x09, 2, 100}, + {0x17, 2, 100}, + {0x28, 3, 100}, + {0x02, 2, 102}, + {0x09, 2, 102}, + {0x17, 2, 102}, + {0x28, 3, 102}, + {0x02, 2, 103}, + {0x09, 2, 103}, + {0x17, 2, 103}, + {0x28, 3, 103}, + {0x02, 2, 104}, + {0x09, 2, 104}, + {0x17, 2, 104}, + {0x28, 3, 104}, }, /* 29 */ { - {0x8003, 100}, - {0x8006, 100}, - {0x800a, 100}, - {0x800f, 100}, - {0x8018, 100}, - {0x801f, 100}, - {0x8029, 100}, - {0xc038, 100}, - {0x8003, 102}, - {0x8006, 102}, - {0x800a, 102}, - {0x800f, 102}, - {0x8018, 102}, - {0x801f, 102}, - {0x8029, 102}, - {0xc038, 102}, + {0x03, 2, 100}, + {0x06, 2, 100}, + {0x0a, 2, 100}, + {0x0f, 2, 100}, + {0x18, 2, 100}, + {0x1f, 2, 100}, + {0x29, 2, 100}, + {0x38, 3, 100}, + {0x03, 2, 102}, + {0x06, 2, 102}, + {0x0a, 2, 102}, + {0x0f, 2, 102}, + {0x18, 2, 102}, + {0x1f, 2, 102}, + {0x29, 2, 102}, + {0x38, 3, 102}, }, /* 30 */ { - {0x8003, 103}, - {0x8006, 103}, - {0x800a, 103}, - {0x800f, 103}, - {0x8018, 103}, - {0x801f, 103}, - {0x8029, 103}, - {0xc038, 103}, - {0x8003, 104}, - {0x8006, 104}, - {0x800a, 104}, - {0x800f, 104}, - {0x8018, 104}, - {0x801f, 104}, - {0x8029, 104}, - {0xc038, 104}, + {0x03, 2, 103}, + {0x06, 2, 103}, + {0x0a, 2, 103}, + {0x0f, 2, 103}, + {0x18, 2, 103}, + {0x1f, 2, 103}, + {0x29, 2, 103}, + {0x38, 3, 103}, + {0x03, 2, 104}, + {0x06, 2, 104}, + {0x0a, 2, 104}, + {0x0f, 2, 104}, + {0x18, 2, 104}, + {0x1f, 2, 104}, + {0x29, 2, 104}, + {0x38, 3, 104}, }, /* 31 */ { - {0x8001, 108}, - {0xc016, 108}, - {0x8001, 109}, - {0xc016, 109}, - {0x8001, 110}, - {0xc016, 110}, - {0x8001, 112}, - {0xc016, 112}, - {0x8001, 114}, - {0xc016, 114}, - {0x8001, 117}, - {0xc016, 117}, - {0xc000, 58}, - {0xc000, 66}, - {0xc000, 67}, - {0xc000, 68}, + {0x01, 2, 108}, + {0x16, 3, 108}, + {0x01, 2, 109}, + {0x16, 3, 109}, + {0x01, 2, 110}, + {0x16, 3, 110}, + {0x01, 2, 112}, + {0x16, 3, 112}, + {0x01, 2, 114}, + {0x16, 3, 114}, + {0x01, 2, 117}, + {0x16, 3, 117}, + {0x00, 3, 58}, + {0x00, 3, 66}, + {0x00, 3, 67}, + {0x00, 3, 68}, }, /* 32 */ { - {0x8002, 108}, - {0x8009, 108}, - {0x8017, 108}, - {0xc028, 108}, - {0x8002, 109}, - {0x8009, 109}, - {0x8017, 109}, - {0xc028, 109}, - {0x8002, 110}, - {0x8009, 110}, - {0x8017, 110}, - {0xc028, 110}, - {0x8002, 112}, - {0x8009, 112}, - {0x8017, 112}, - {0xc028, 112}, + {0x02, 2, 108}, + {0x09, 2, 108}, + {0x17, 2, 108}, + {0x28, 3, 108}, + {0x02, 2, 109}, + {0x09, 2, 109}, + {0x17, 2, 109}, + {0x28, 3, 109}, + {0x02, 2, 110}, + {0x09, 2, 110}, + {0x17, 2, 110}, + {0x28, 3, 110}, + {0x02, 2, 112}, + {0x09, 2, 112}, + {0x17, 2, 112}, + {0x28, 3, 112}, }, /* 33 */ { - {0x8003, 108}, - {0x8006, 108}, - {0x800a, 108}, - {0x800f, 108}, - {0x8018, 108}, - {0x801f, 108}, - {0x8029, 108}, - {0xc038, 108}, - {0x8003, 109}, - {0x8006, 109}, - {0x800a, 109}, - {0x800f, 109}, - {0x8018, 109}, - {0x801f, 109}, - {0x8029, 109}, - {0xc038, 109}, + {0x03, 2, 108}, + {0x06, 2, 108}, + {0x0a, 2, 108}, + {0x0f, 2, 108}, + {0x18, 2, 108}, + {0x1f, 2, 108}, + {0x29, 2, 108}, + {0x38, 3, 108}, + {0x03, 2, 109}, + {0x06, 2, 109}, + {0x0a, 2, 109}, + {0x0f, 2, 109}, + {0x18, 2, 109}, + {0x1f, 2, 109}, + {0x29, 2, 109}, + {0x38, 3, 109}, }, /* 34 */ { - {0x8003, 110}, - {0x8006, 110}, - {0x800a, 110}, - {0x800f, 110}, - {0x8018, 110}, - {0x801f, 110}, - {0x8029, 110}, - {0xc038, 110}, - {0x8003, 112}, - {0x8006, 112}, - {0x800a, 112}, - {0x800f, 112}, - {0x8018, 112}, - {0x801f, 112}, - {0x8029, 112}, - {0xc038, 112}, + {0x03, 2, 110}, + {0x06, 2, 110}, + {0x0a, 2, 110}, + {0x0f, 2, 110}, + {0x18, 2, 110}, + {0x1f, 2, 110}, + {0x29, 2, 110}, + {0x38, 3, 110}, + {0x03, 2, 112}, + {0x06, 2, 112}, + {0x0a, 2, 112}, + {0x0f, 2, 112}, + {0x18, 2, 112}, + {0x1f, 2, 112}, + {0x29, 2, 112}, + {0x38, 3, 112}, }, /* 35 */ { - {0x8002, 114}, - {0x8009, 114}, - {0x8017, 114}, - {0xc028, 114}, - {0x8002, 117}, - {0x8009, 117}, - {0x8017, 117}, - {0xc028, 117}, - {0x8001, 58}, - {0xc016, 58}, - {0x8001, 66}, - {0xc016, 66}, - {0x8001, 67}, - {0xc016, 67}, - {0x8001, 68}, - {0xc016, 68}, + {0x02, 2, 114}, + {0x09, 2, 114}, + {0x17, 2, 114}, + {0x28, 3, 114}, + {0x02, 2, 117}, + {0x09, 2, 117}, + {0x17, 2, 117}, + {0x28, 3, 117}, + {0x01, 2, 58}, + {0x16, 3, 58}, + {0x01, 2, 66}, + {0x16, 3, 66}, + {0x01, 2, 67}, + {0x16, 3, 67}, + {0x01, 2, 68}, + {0x16, 3, 68}, }, /* 36 */ { - {0x8003, 114}, - {0x8006, 114}, - {0x800a, 114}, - {0x800f, 114}, - {0x8018, 114}, - {0x801f, 114}, - {0x8029, 114}, - {0xc038, 114}, - {0x8003, 117}, - {0x8006, 117}, - {0x800a, 117}, - {0x800f, 117}, - {0x8018, 117}, - {0x801f, 117}, - {0x8029, 117}, - {0xc038, 117}, + {0x03, 2, 114}, + {0x06, 2, 114}, + {0x0a, 2, 114}, + {0x0f, 2, 114}, + {0x18, 2, 114}, + {0x1f, 2, 114}, + {0x29, 2, 114}, + {0x38, 3, 114}, + {0x03, 2, 117}, + {0x06, 2, 117}, + {0x0a, 2, 117}, + {0x0f, 2, 117}, + {0x18, 2, 117}, + {0x1f, 2, 117}, + {0x29, 2, 117}, + {0x38, 3, 117}, }, /* 37 */ { - {0x8002, 58}, - {0x8009, 58}, - {0x8017, 58}, - {0xc028, 58}, - {0x8002, 66}, - {0x8009, 66}, - {0x8017, 66}, - {0xc028, 66}, - {0x8002, 67}, - {0x8009, 67}, - {0x8017, 67}, - {0xc028, 67}, - {0x8002, 68}, - {0x8009, 68}, - {0x8017, 68}, - {0xc028, 68}, + {0x02, 2, 58}, + {0x09, 2, 58}, + {0x17, 2, 58}, + {0x28, 3, 58}, + {0x02, 2, 66}, + {0x09, 2, 66}, + {0x17, 2, 66}, + {0x28, 3, 66}, + {0x02, 2, 67}, + {0x09, 2, 67}, + {0x17, 2, 67}, + {0x28, 3, 67}, + {0x02, 2, 68}, + {0x09, 2, 68}, + {0x17, 2, 68}, + {0x28, 3, 68}, }, /* 38 */ { - {0x8003, 58}, - {0x8006, 58}, - {0x800a, 58}, - {0x800f, 58}, - {0x8018, 58}, - {0x801f, 58}, - {0x8029, 58}, - {0xc038, 58}, - {0x8003, 66}, - {0x8006, 66}, - {0x800a, 66}, - {0x800f, 66}, - {0x8018, 66}, - {0x801f, 66}, - {0x8029, 66}, - {0xc038, 66}, + {0x03, 2, 58}, + {0x06, 2, 58}, + {0x0a, 2, 58}, + {0x0f, 2, 58}, + {0x18, 2, 58}, + {0x1f, 2, 58}, + {0x29, 2, 58}, + {0x38, 3, 58}, + {0x03, 2, 66}, + {0x06, 2, 66}, + {0x0a, 2, 66}, + {0x0f, 2, 66}, + {0x18, 2, 66}, + {0x1f, 2, 66}, + {0x29, 2, 66}, + {0x38, 3, 66}, }, /* 39 */ { - {0x8003, 67}, - {0x8006, 67}, - {0x800a, 67}, - {0x800f, 67}, - {0x8018, 67}, - {0x801f, 67}, - {0x8029, 67}, - {0xc038, 67}, - {0x8003, 68}, - {0x8006, 68}, - {0x800a, 68}, - {0x800f, 68}, - {0x8018, 68}, - {0x801f, 68}, - {0x8029, 68}, - {0xc038, 68}, + {0x03, 2, 67}, + {0x06, 2, 67}, + {0x0a, 2, 67}, + {0x0f, 2, 67}, + {0x18, 2, 67}, + {0x1f, 2, 67}, + {0x29, 2, 67}, + {0x38, 3, 67}, + {0x03, 2, 68}, + {0x06, 2, 68}, + {0x0a, 2, 68}, + {0x0f, 2, 68}, + {0x18, 2, 68}, + {0x1f, 2, 68}, + {0x29, 2, 68}, + {0x38, 3, 68}, }, /* 40 */ { - {0x2c, 0}, - {0x2d, 0}, - {0x2f, 0}, - {0x30, 0}, - {0x33, 0}, - {0x34, 0}, - {0x36, 0}, - {0x37, 0}, - {0x3b, 0}, - {0x3c, 0}, - {0x3e, 0}, - {0x3f, 0}, - {0x42, 0}, - {0x43, 0}, - {0x45, 0}, - {0x4048, 0}, + {0x2c, 0, 0}, + {0x2d, 0, 0}, + {0x2f, 0, 0}, + {0x30, 0, 0}, + {0x33, 0, 0}, + {0x34, 0, 0}, + {0x36, 0, 0}, + {0x37, 0, 0}, + {0x3b, 0, 0}, + {0x3c, 0, 0}, + {0x3e, 0, 0}, + {0x3f, 0, 0}, + {0x42, 0, 0}, + {0x43, 0, 0}, + {0x45, 0, 0}, + {0x48, 1, 0}, }, /* 41 */ { - {0xc000, 69}, - {0xc000, 70}, - {0xc000, 71}, - {0xc000, 72}, - {0xc000, 73}, - {0xc000, 74}, - {0xc000, 75}, - {0xc000, 76}, - {0xc000, 77}, - {0xc000, 78}, - {0xc000, 79}, - {0xc000, 80}, - {0xc000, 81}, - {0xc000, 82}, - {0xc000, 83}, - {0xc000, 84}, + {0x00, 3, 69}, + {0x00, 3, 70}, + {0x00, 3, 71}, + {0x00, 3, 72}, + {0x00, 3, 73}, + {0x00, 3, 74}, + {0x00, 3, 75}, + {0x00, 3, 76}, + {0x00, 3, 77}, + {0x00, 3, 78}, + {0x00, 3, 79}, + {0x00, 3, 80}, + {0x00, 3, 81}, + {0x00, 3, 82}, + {0x00, 3, 83}, + {0x00, 3, 84}, }, /* 42 */ { - {0x8001, 69}, - {0xc016, 69}, - {0x8001, 70}, - {0xc016, 70}, - {0x8001, 71}, - {0xc016, 71}, - {0x8001, 72}, - {0xc016, 72}, - {0x8001, 73}, - {0xc016, 73}, - {0x8001, 74}, - {0xc016, 74}, - {0x8001, 75}, - {0xc016, 75}, - {0x8001, 76}, - {0xc016, 76}, + {0x01, 2, 69}, + {0x16, 3, 69}, + {0x01, 2, 70}, + {0x16, 3, 70}, + {0x01, 2, 71}, + {0x16, 3, 71}, + {0x01, 2, 72}, + {0x16, 3, 72}, + {0x01, 2, 73}, + {0x16, 3, 73}, + {0x01, 2, 74}, + {0x16, 3, 74}, + {0x01, 2, 75}, + {0x16, 3, 75}, + {0x01, 2, 76}, + {0x16, 3, 76}, }, /* 43 */ { - {0x8002, 69}, - {0x8009, 69}, - {0x8017, 69}, - {0xc028, 69}, - {0x8002, 70}, - {0x8009, 70}, - {0x8017, 70}, - {0xc028, 70}, - {0x8002, 71}, - {0x8009, 71}, - {0x8017, 71}, - {0xc028, 71}, - {0x8002, 72}, - {0x8009, 72}, - {0x8017, 72}, - {0xc028, 72}, + {0x02, 2, 69}, + {0x09, 2, 69}, + {0x17, 2, 69}, + {0x28, 3, 69}, + {0x02, 2, 70}, + {0x09, 2, 70}, + {0x17, 2, 70}, + {0x28, 3, 70}, + {0x02, 2, 71}, + {0x09, 2, 71}, + {0x17, 2, 71}, + {0x28, 3, 71}, + {0x02, 2, 72}, + {0x09, 2, 72}, + {0x17, 2, 72}, + {0x28, 3, 72}, }, /* 44 */ { - {0x8003, 69}, - {0x8006, 69}, - {0x800a, 69}, - {0x800f, 69}, - {0x8018, 69}, - {0x801f, 69}, - {0x8029, 69}, - {0xc038, 69}, - {0x8003, 70}, - {0x8006, 70}, - {0x800a, 70}, - {0x800f, 70}, - {0x8018, 70}, - {0x801f, 70}, - {0x8029, 70}, - {0xc038, 70}, + {0x03, 2, 69}, + {0x06, 2, 69}, + {0x0a, 2, 69}, + {0x0f, 2, 69}, + {0x18, 2, 69}, + {0x1f, 2, 69}, + {0x29, 2, 69}, + {0x38, 3, 69}, + {0x03, 2, 70}, + {0x06, 2, 70}, + {0x0a, 2, 70}, + {0x0f, 2, 70}, + {0x18, 2, 70}, + {0x1f, 2, 70}, + {0x29, 2, 70}, + {0x38, 3, 70}, }, /* 45 */ { - {0x8003, 71}, - {0x8006, 71}, - {0x800a, 71}, - {0x800f, 71}, - {0x8018, 71}, - {0x801f, 71}, - {0x8029, 71}, - {0xc038, 71}, - {0x8003, 72}, - {0x8006, 72}, - {0x800a, 72}, - {0x800f, 72}, - {0x8018, 72}, - {0x801f, 72}, - {0x8029, 72}, - {0xc038, 72}, + {0x03, 2, 71}, + {0x06, 2, 71}, + {0x0a, 2, 71}, + {0x0f, 2, 71}, + {0x18, 2, 71}, + {0x1f, 2, 71}, + {0x29, 2, 71}, + {0x38, 3, 71}, + {0x03, 2, 72}, + {0x06, 2, 72}, + {0x0a, 2, 72}, + {0x0f, 2, 72}, + {0x18, 2, 72}, + {0x1f, 2, 72}, + {0x29, 2, 72}, + {0x38, 3, 72}, }, /* 46 */ { - {0x8002, 73}, - {0x8009, 73}, - {0x8017, 73}, - {0xc028, 73}, - {0x8002, 74}, - {0x8009, 74}, - {0x8017, 74}, - {0xc028, 74}, - {0x8002, 75}, - {0x8009, 75}, - {0x8017, 75}, - {0xc028, 75}, - {0x8002, 76}, - {0x8009, 76}, - {0x8017, 76}, - {0xc028, 76}, + {0x02, 2, 73}, + {0x09, 2, 73}, + {0x17, 2, 73}, + {0x28, 3, 73}, + {0x02, 2, 74}, + {0x09, 2, 74}, + {0x17, 2, 74}, + {0x28, 3, 74}, + {0x02, 2, 75}, + {0x09, 2, 75}, + {0x17, 2, 75}, + {0x28, 3, 75}, + {0x02, 2, 76}, + {0x09, 2, 76}, + {0x17, 2, 76}, + {0x28, 3, 76}, }, /* 47 */ { - {0x8003, 73}, - {0x8006, 73}, - {0x800a, 73}, - {0x800f, 73}, - {0x8018, 73}, - {0x801f, 73}, - {0x8029, 73}, - {0xc038, 73}, - {0x8003, 74}, - {0x8006, 74}, - {0x800a, 74}, - {0x800f, 74}, - {0x8018, 74}, - {0x801f, 74}, - {0x8029, 74}, - {0xc038, 74}, + {0x03, 2, 73}, + {0x06, 2, 73}, + {0x0a, 2, 73}, + {0x0f, 2, 73}, + {0x18, 2, 73}, + {0x1f, 2, 73}, + {0x29, 2, 73}, + {0x38, 3, 73}, + {0x03, 2, 74}, + {0x06, 2, 74}, + {0x0a, 2, 74}, + {0x0f, 2, 74}, + {0x18, 2, 74}, + {0x1f, 2, 74}, + {0x29, 2, 74}, + {0x38, 3, 74}, }, /* 48 */ { - {0x8003, 75}, - {0x8006, 75}, - {0x800a, 75}, - {0x800f, 75}, - {0x8018, 75}, - {0x801f, 75}, - {0x8029, 75}, - {0xc038, 75}, - {0x8003, 76}, - {0x8006, 76}, - {0x800a, 76}, - {0x800f, 76}, - {0x8018, 76}, - {0x801f, 76}, - {0x8029, 76}, - {0xc038, 76}, + {0x03, 2, 75}, + {0x06, 2, 75}, + {0x0a, 2, 75}, + {0x0f, 2, 75}, + {0x18, 2, 75}, + {0x1f, 2, 75}, + {0x29, 2, 75}, + {0x38, 3, 75}, + {0x03, 2, 76}, + {0x06, 2, 76}, + {0x0a, 2, 76}, + {0x0f, 2, 76}, + {0x18, 2, 76}, + {0x1f, 2, 76}, + {0x29, 2, 76}, + {0x38, 3, 76}, }, /* 49 */ { - {0x8001, 77}, - {0xc016, 77}, - {0x8001, 78}, - {0xc016, 78}, - {0x8001, 79}, - {0xc016, 79}, - {0x8001, 80}, - {0xc016, 80}, - {0x8001, 81}, - {0xc016, 81}, - {0x8001, 82}, - {0xc016, 82}, - {0x8001, 83}, - {0xc016, 83}, - {0x8001, 84}, - {0xc016, 84}, + {0x01, 2, 77}, + {0x16, 3, 77}, + {0x01, 2, 78}, + {0x16, 3, 78}, + {0x01, 2, 79}, + {0x16, 3, 79}, + {0x01, 2, 80}, + {0x16, 3, 80}, + {0x01, 2, 81}, + {0x16, 3, 81}, + {0x01, 2, 82}, + {0x16, 3, 82}, + {0x01, 2, 83}, + {0x16, 3, 83}, + {0x01, 2, 84}, + {0x16, 3, 84}, }, /* 50 */ { - {0x8002, 77}, - {0x8009, 77}, - {0x8017, 77}, - {0xc028, 77}, - {0x8002, 78}, - {0x8009, 78}, - {0x8017, 78}, - {0xc028, 78}, - {0x8002, 79}, - {0x8009, 79}, - {0x8017, 79}, - {0xc028, 79}, - {0x8002, 80}, - {0x8009, 80}, - {0x8017, 80}, - {0xc028, 80}, + {0x02, 2, 77}, + {0x09, 2, 77}, + {0x17, 2, 77}, + {0x28, 3, 77}, + {0x02, 2, 78}, + {0x09, 2, 78}, + {0x17, 2, 78}, + {0x28, 3, 78}, + {0x02, 2, 79}, + {0x09, 2, 79}, + {0x17, 2, 79}, + {0x28, 3, 79}, + {0x02, 2, 80}, + {0x09, 2, 80}, + {0x17, 2, 80}, + {0x28, 3, 80}, }, /* 51 */ { - {0x8003, 77}, - {0x8006, 77}, - {0x800a, 77}, - {0x800f, 77}, - {0x8018, 77}, - {0x801f, 77}, - {0x8029, 77}, - {0xc038, 77}, - {0x8003, 78}, - {0x8006, 78}, - {0x800a, 78}, - {0x800f, 78}, - {0x8018, 78}, - {0x801f, 78}, - {0x8029, 78}, - {0xc038, 78}, + {0x03, 2, 77}, + {0x06, 2, 77}, + {0x0a, 2, 77}, + {0x0f, 2, 77}, + {0x18, 2, 77}, + {0x1f, 2, 77}, + {0x29, 2, 77}, + {0x38, 3, 77}, + {0x03, 2, 78}, + {0x06, 2, 78}, + {0x0a, 2, 78}, + {0x0f, 2, 78}, + {0x18, 2, 78}, + {0x1f, 2, 78}, + {0x29, 2, 78}, + {0x38, 3, 78}, }, /* 52 */ { - {0x8003, 79}, - {0x8006, 79}, - {0x800a, 79}, - {0x800f, 79}, - {0x8018, 79}, - {0x801f, 79}, - {0x8029, 79}, - {0xc038, 79}, - {0x8003, 80}, - {0x8006, 80}, - {0x800a, 80}, - {0x800f, 80}, - {0x8018, 80}, - {0x801f, 80}, - {0x8029, 80}, - {0xc038, 80}, + {0x03, 2, 79}, + {0x06, 2, 79}, + {0x0a, 2, 79}, + {0x0f, 2, 79}, + {0x18, 2, 79}, + {0x1f, 2, 79}, + {0x29, 2, 79}, + {0x38, 3, 79}, + {0x03, 2, 80}, + {0x06, 2, 80}, + {0x0a, 2, 80}, + {0x0f, 2, 80}, + {0x18, 2, 80}, + {0x1f, 2, 80}, + {0x29, 2, 80}, + {0x38, 3, 80}, }, /* 53 */ { - {0x8002, 81}, - {0x8009, 81}, - {0x8017, 81}, - {0xc028, 81}, - {0x8002, 82}, - {0x8009, 82}, - {0x8017, 82}, - {0xc028, 82}, - {0x8002, 83}, - {0x8009, 83}, - {0x8017, 83}, - {0xc028, 83}, - {0x8002, 84}, - {0x8009, 84}, - {0x8017, 84}, - {0xc028, 84}, + {0x02, 2, 81}, + {0x09, 2, 81}, + {0x17, 2, 81}, + {0x28, 3, 81}, + {0x02, 2, 82}, + {0x09, 2, 82}, + {0x17, 2, 82}, + {0x28, 3, 82}, + {0x02, 2, 83}, + {0x09, 2, 83}, + {0x17, 2, 83}, + {0x28, 3, 83}, + {0x02, 2, 84}, + {0x09, 2, 84}, + {0x17, 2, 84}, + {0x28, 3, 84}, }, /* 54 */ { - {0x8003, 81}, - {0x8006, 81}, - {0x800a, 81}, - {0x800f, 81}, - {0x8018, 81}, - {0x801f, 81}, - {0x8029, 81}, - {0xc038, 81}, - {0x8003, 82}, - {0x8006, 82}, - {0x800a, 82}, - {0x800f, 82}, - {0x8018, 82}, - {0x801f, 82}, - {0x8029, 82}, - {0xc038, 82}, + {0x03, 2, 81}, + {0x06, 2, 81}, + {0x0a, 2, 81}, + {0x0f, 2, 81}, + {0x18, 2, 81}, + {0x1f, 2, 81}, + {0x29, 2, 81}, + {0x38, 3, 81}, + {0x03, 2, 82}, + {0x06, 2, 82}, + {0x0a, 2, 82}, + {0x0f, 2, 82}, + {0x18, 2, 82}, + {0x1f, 2, 82}, + {0x29, 2, 82}, + {0x38, 3, 82}, }, /* 55 */ { - {0x8003, 83}, - {0x8006, 83}, - {0x800a, 83}, - {0x800f, 83}, - {0x8018, 83}, - {0x801f, 83}, - {0x8029, 83}, - {0xc038, 83}, - {0x8003, 84}, - {0x8006, 84}, - {0x800a, 84}, - {0x800f, 84}, - {0x8018, 84}, - {0x801f, 84}, - {0x8029, 84}, - {0xc038, 84}, + {0x03, 2, 83}, + {0x06, 2, 83}, + {0x0a, 2, 83}, + {0x0f, 2, 83}, + {0x18, 2, 83}, + {0x1f, 2, 83}, + {0x29, 2, 83}, + {0x38, 3, 83}, + {0x03, 2, 84}, + {0x06, 2, 84}, + {0x0a, 2, 84}, + {0x0f, 2, 84}, + {0x18, 2, 84}, + {0x1f, 2, 84}, + {0x29, 2, 84}, + {0x38, 3, 84}, }, /* 56 */ { - {0xc000, 85}, - {0xc000, 86}, - {0xc000, 87}, - {0xc000, 89}, - {0xc000, 106}, - {0xc000, 107}, - {0xc000, 113}, - {0xc000, 118}, - {0xc000, 119}, - {0xc000, 120}, - {0xc000, 121}, - {0xc000, 122}, - {0x46, 0}, - {0x47, 0}, - {0x49, 0}, - {0x404a, 0}, + {0x00, 3, 85}, + {0x00, 3, 86}, + {0x00, 3, 87}, + {0x00, 3, 89}, + {0x00, 3, 106}, + {0x00, 3, 107}, + {0x00, 3, 113}, + {0x00, 3, 118}, + {0x00, 3, 119}, + {0x00, 3, 120}, + {0x00, 3, 121}, + {0x00, 3, 122}, + {0x46, 0, 0}, + {0x47, 0, 0}, + {0x49, 0, 0}, + {0x4a, 1, 0}, }, /* 57 */ { - {0x8001, 85}, - {0xc016, 85}, - {0x8001, 86}, - {0xc016, 86}, - {0x8001, 87}, - {0xc016, 87}, - {0x8001, 89}, - {0xc016, 89}, - {0x8001, 106}, - {0xc016, 106}, - {0x8001, 107}, - {0xc016, 107}, - {0x8001, 113}, - {0xc016, 113}, - {0x8001, 118}, - {0xc016, 118}, + {0x01, 2, 85}, + {0x16, 3, 85}, + {0x01, 2, 86}, + {0x16, 3, 86}, + {0x01, 2, 87}, + {0x16, 3, 87}, + {0x01, 2, 89}, + {0x16, 3, 89}, + {0x01, 2, 106}, + {0x16, 3, 106}, + {0x01, 2, 107}, + {0x16, 3, 107}, + {0x01, 2, 113}, + {0x16, 3, 113}, + {0x01, 2, 118}, + {0x16, 3, 118}, }, /* 58 */ { - {0x8002, 85}, - {0x8009, 85}, - {0x8017, 85}, - {0xc028, 85}, - {0x8002, 86}, - {0x8009, 86}, - {0x8017, 86}, - {0xc028, 86}, - {0x8002, 87}, - {0x8009, 87}, - {0x8017, 87}, - {0xc028, 87}, - {0x8002, 89}, - {0x8009, 89}, - {0x8017, 89}, - {0xc028, 89}, + {0x02, 2, 85}, + {0x09, 2, 85}, + {0x17, 2, 85}, + {0x28, 3, 85}, + {0x02, 2, 86}, + {0x09, 2, 86}, + {0x17, 2, 86}, + {0x28, 3, 86}, + {0x02, 2, 87}, + {0x09, 2, 87}, + {0x17, 2, 87}, + {0x28, 3, 87}, + {0x02, 2, 89}, + {0x09, 2, 89}, + {0x17, 2, 89}, + {0x28, 3, 89}, }, /* 59 */ { - {0x8003, 85}, - {0x8006, 85}, - {0x800a, 85}, - {0x800f, 85}, - {0x8018, 85}, - {0x801f, 85}, - {0x8029, 85}, - {0xc038, 85}, - {0x8003, 86}, - {0x8006, 86}, - {0x800a, 86}, - {0x800f, 86}, - {0x8018, 86}, - {0x801f, 86}, - {0x8029, 86}, - {0xc038, 86}, + {0x03, 2, 85}, + {0x06, 2, 85}, + {0x0a, 2, 85}, + {0x0f, 2, 85}, + {0x18, 2, 85}, + {0x1f, 2, 85}, + {0x29, 2, 85}, + {0x38, 3, 85}, + {0x03, 2, 86}, + {0x06, 2, 86}, + {0x0a, 2, 86}, + {0x0f, 2, 86}, + {0x18, 2, 86}, + {0x1f, 2, 86}, + {0x29, 2, 86}, + {0x38, 3, 86}, }, /* 60 */ { - {0x8003, 87}, - {0x8006, 87}, - {0x800a, 87}, - {0x800f, 87}, - {0x8018, 87}, - {0x801f, 87}, - {0x8029, 87}, - {0xc038, 87}, - {0x8003, 89}, - {0x8006, 89}, - {0x800a, 89}, - {0x800f, 89}, - {0x8018, 89}, - {0x801f, 89}, - {0x8029, 89}, - {0xc038, 89}, + {0x03, 2, 87}, + {0x06, 2, 87}, + {0x0a, 2, 87}, + {0x0f, 2, 87}, + {0x18, 2, 87}, + {0x1f, 2, 87}, + {0x29, 2, 87}, + {0x38, 3, 87}, + {0x03, 2, 89}, + {0x06, 2, 89}, + {0x0a, 2, 89}, + {0x0f, 2, 89}, + {0x18, 2, 89}, + {0x1f, 2, 89}, + {0x29, 2, 89}, + {0x38, 3, 89}, }, /* 61 */ { - {0x8002, 106}, - {0x8009, 106}, - {0x8017, 106}, - {0xc028, 106}, - {0x8002, 107}, - {0x8009, 107}, - {0x8017, 107}, - {0xc028, 107}, - {0x8002, 113}, - {0x8009, 113}, - {0x8017, 113}, - {0xc028, 113}, - {0x8002, 118}, - {0x8009, 118}, - {0x8017, 118}, - {0xc028, 118}, + {0x02, 2, 106}, + {0x09, 2, 106}, + {0x17, 2, 106}, + {0x28, 3, 106}, + {0x02, 2, 107}, + {0x09, 2, 107}, + {0x17, 2, 107}, + {0x28, 3, 107}, + {0x02, 2, 113}, + {0x09, 2, 113}, + {0x17, 2, 113}, + {0x28, 3, 113}, + {0x02, 2, 118}, + {0x09, 2, 118}, + {0x17, 2, 118}, + {0x28, 3, 118}, }, /* 62 */ { - {0x8003, 106}, - {0x8006, 106}, - {0x800a, 106}, - {0x800f, 106}, - {0x8018, 106}, - {0x801f, 106}, - {0x8029, 106}, - {0xc038, 106}, - {0x8003, 107}, - {0x8006, 107}, - {0x800a, 107}, - {0x800f, 107}, - {0x8018, 107}, - {0x801f, 107}, - {0x8029, 107}, - {0xc038, 107}, + {0x03, 2, 106}, + {0x06, 2, 106}, + {0x0a, 2, 106}, + {0x0f, 2, 106}, + {0x18, 2, 106}, + {0x1f, 2, 106}, + {0x29, 2, 106}, + {0x38, 3, 106}, + {0x03, 2, 107}, + {0x06, 2, 107}, + {0x0a, 2, 107}, + {0x0f, 2, 107}, + {0x18, 2, 107}, + {0x1f, 2, 107}, + {0x29, 2, 107}, + {0x38, 3, 107}, }, /* 63 */ { - {0x8003, 113}, - {0x8006, 113}, - {0x800a, 113}, - {0x800f, 113}, - {0x8018, 113}, - {0x801f, 113}, - {0x8029, 113}, - {0xc038, 113}, - {0x8003, 118}, - {0x8006, 118}, - {0x800a, 118}, - {0x800f, 118}, - {0x8018, 118}, - {0x801f, 118}, - {0x8029, 118}, - {0xc038, 118}, + {0x03, 2, 113}, + {0x06, 2, 113}, + {0x0a, 2, 113}, + {0x0f, 2, 113}, + {0x18, 2, 113}, + {0x1f, 2, 113}, + {0x29, 2, 113}, + {0x38, 3, 113}, + {0x03, 2, 118}, + {0x06, 2, 118}, + {0x0a, 2, 118}, + {0x0f, 2, 118}, + {0x18, 2, 118}, + {0x1f, 2, 118}, + {0x29, 2, 118}, + {0x38, 3, 118}, }, /* 64 */ { - {0x8001, 119}, - {0xc016, 119}, - {0x8001, 120}, - {0xc016, 120}, - {0x8001, 121}, - {0xc016, 121}, - {0x8001, 122}, - {0xc016, 122}, - {0xc000, 38}, - {0xc000, 42}, - {0xc000, 44}, - {0xc000, 59}, - {0xc000, 88}, - {0xc000, 90}, - {0x4b, 0}, - {0x4e, 0}, + {0x01, 2, 119}, + {0x16, 3, 119}, + {0x01, 2, 120}, + {0x16, 3, 120}, + {0x01, 2, 121}, + {0x16, 3, 121}, + {0x01, 2, 122}, + {0x16, 3, 122}, + {0x00, 3, 38}, + {0x00, 3, 42}, + {0x00, 3, 44}, + {0x00, 3, 59}, + {0x00, 3, 88}, + {0x00, 3, 90}, + {0x4b, 0, 0}, + {0x4e, 0, 0}, }, /* 65 */ { - {0x8002, 119}, - {0x8009, 119}, - {0x8017, 119}, - {0xc028, 119}, - {0x8002, 120}, - {0x8009, 120}, - {0x8017, 120}, - {0xc028, 120}, - {0x8002, 121}, - {0x8009, 121}, - {0x8017, 121}, - {0xc028, 121}, - {0x8002, 122}, - {0x8009, 122}, - {0x8017, 122}, - {0xc028, 122}, + {0x02, 2, 119}, + {0x09, 2, 119}, + {0x17, 2, 119}, + {0x28, 3, 119}, + {0x02, 2, 120}, + {0x09, 2, 120}, + {0x17, 2, 120}, + {0x28, 3, 120}, + {0x02, 2, 121}, + {0x09, 2, 121}, + {0x17, 2, 121}, + {0x28, 3, 121}, + {0x02, 2, 122}, + {0x09, 2, 122}, + {0x17, 2, 122}, + {0x28, 3, 122}, }, /* 66 */ { - {0x8003, 119}, - {0x8006, 119}, - {0x800a, 119}, - {0x800f, 119}, - {0x8018, 119}, - {0x801f, 119}, - {0x8029, 119}, - {0xc038, 119}, - {0x8003, 120}, - {0x8006, 120}, - {0x800a, 120}, - {0x800f, 120}, - {0x8018, 120}, - {0x801f, 120}, - {0x8029, 120}, - {0xc038, 120}, + {0x03, 2, 119}, + {0x06, 2, 119}, + {0x0a, 2, 119}, + {0x0f, 2, 119}, + {0x18, 2, 119}, + {0x1f, 2, 119}, + {0x29, 2, 119}, + {0x38, 3, 119}, + {0x03, 2, 120}, + {0x06, 2, 120}, + {0x0a, 2, 120}, + {0x0f, 2, 120}, + {0x18, 2, 120}, + {0x1f, 2, 120}, + {0x29, 2, 120}, + {0x38, 3, 120}, }, /* 67 */ { - {0x8003, 121}, - {0x8006, 121}, - {0x800a, 121}, - {0x800f, 121}, - {0x8018, 121}, - {0x801f, 121}, - {0x8029, 121}, - {0xc038, 121}, - {0x8003, 122}, - {0x8006, 122}, - {0x800a, 122}, - {0x800f, 122}, - {0x8018, 122}, - {0x801f, 122}, - {0x8029, 122}, - {0xc038, 122}, + {0x03, 2, 121}, + {0x06, 2, 121}, + {0x0a, 2, 121}, + {0x0f, 2, 121}, + {0x18, 2, 121}, + {0x1f, 2, 121}, + {0x29, 2, 121}, + {0x38, 3, 121}, + {0x03, 2, 122}, + {0x06, 2, 122}, + {0x0a, 2, 122}, + {0x0f, 2, 122}, + {0x18, 2, 122}, + {0x1f, 2, 122}, + {0x29, 2, 122}, + {0x38, 3, 122}, }, /* 68 */ { - {0x8001, 38}, - {0xc016, 38}, - {0x8001, 42}, - {0xc016, 42}, - {0x8001, 44}, - {0xc016, 44}, - {0x8001, 59}, - {0xc016, 59}, - {0x8001, 88}, - {0xc016, 88}, - {0x8001, 90}, - {0xc016, 90}, - {0x4c, 0}, - {0x4d, 0}, - {0x4f, 0}, - {0x51, 0}, + {0x01, 2, 38}, + {0x16, 3, 38}, + {0x01, 2, 42}, + {0x16, 3, 42}, + {0x01, 2, 44}, + {0x16, 3, 44}, + {0x01, 2, 59}, + {0x16, 3, 59}, + {0x01, 2, 88}, + {0x16, 3, 88}, + {0x01, 2, 90}, + {0x16, 3, 90}, + {0x4c, 0, 0}, + {0x4d, 0, 0}, + {0x4f, 0, 0}, + {0x51, 0, 0}, }, /* 69 */ { - {0x8002, 38}, - {0x8009, 38}, - {0x8017, 38}, - {0xc028, 38}, - {0x8002, 42}, - {0x8009, 42}, - {0x8017, 42}, - {0xc028, 42}, - {0x8002, 44}, - {0x8009, 44}, - {0x8017, 44}, - {0xc028, 44}, - {0x8002, 59}, - {0x8009, 59}, - {0x8017, 59}, - {0xc028, 59}, + {0x02, 2, 38}, + {0x09, 2, 38}, + {0x17, 2, 38}, + {0x28, 3, 38}, + {0x02, 2, 42}, + {0x09, 2, 42}, + {0x17, 2, 42}, + {0x28, 3, 42}, + {0x02, 2, 44}, + {0x09, 2, 44}, + {0x17, 2, 44}, + {0x28, 3, 44}, + {0x02, 2, 59}, + {0x09, 2, 59}, + {0x17, 2, 59}, + {0x28, 3, 59}, }, /* 70 */ { - {0x8003, 38}, - {0x8006, 38}, - {0x800a, 38}, - {0x800f, 38}, - {0x8018, 38}, - {0x801f, 38}, - {0x8029, 38}, - {0xc038, 38}, - {0x8003, 42}, - {0x8006, 42}, - {0x800a, 42}, - {0x800f, 42}, - {0x8018, 42}, - {0x801f, 42}, - {0x8029, 42}, - {0xc038, 42}, + {0x03, 2, 38}, + {0x06, 2, 38}, + {0x0a, 2, 38}, + {0x0f, 2, 38}, + {0x18, 2, 38}, + {0x1f, 2, 38}, + {0x29, 2, 38}, + {0x38, 3, 38}, + {0x03, 2, 42}, + {0x06, 2, 42}, + {0x0a, 2, 42}, + {0x0f, 2, 42}, + {0x18, 2, 42}, + {0x1f, 2, 42}, + {0x29, 2, 42}, + {0x38, 3, 42}, }, /* 71 */ { - {0x8003, 44}, - {0x8006, 44}, - {0x800a, 44}, - {0x800f, 44}, - {0x8018, 44}, - {0x801f, 44}, - {0x8029, 44}, - {0xc038, 44}, - {0x8003, 59}, - {0x8006, 59}, - {0x800a, 59}, - {0x800f, 59}, - {0x8018, 59}, - {0x801f, 59}, - {0x8029, 59}, - {0xc038, 59}, + {0x03, 2, 44}, + {0x06, 2, 44}, + {0x0a, 2, 44}, + {0x0f, 2, 44}, + {0x18, 2, 44}, + {0x1f, 2, 44}, + {0x29, 2, 44}, + {0x38, 3, 44}, + {0x03, 2, 59}, + {0x06, 2, 59}, + {0x0a, 2, 59}, + {0x0f, 2, 59}, + {0x18, 2, 59}, + {0x1f, 2, 59}, + {0x29, 2, 59}, + {0x38, 3, 59}, }, /* 72 */ { - {0x8002, 88}, - {0x8009, 88}, - {0x8017, 88}, - {0xc028, 88}, - {0x8002, 90}, - {0x8009, 90}, - {0x8017, 90}, - {0xc028, 90}, - {0xc000, 33}, - {0xc000, 34}, - {0xc000, 40}, - {0xc000, 41}, - {0xc000, 63}, - {0x50, 0}, - {0x52, 0}, - {0x54, 0}, + {0x02, 2, 88}, + {0x09, 2, 88}, + {0x17, 2, 88}, + {0x28, 3, 88}, + {0x02, 2, 90}, + {0x09, 2, 90}, + {0x17, 2, 90}, + {0x28, 3, 90}, + {0x00, 3, 33}, + {0x00, 3, 34}, + {0x00, 3, 40}, + {0x00, 3, 41}, + {0x00, 3, 63}, + {0x50, 0, 0}, + {0x52, 0, 0}, + {0x54, 0, 0}, }, /* 73 */ { - {0x8003, 88}, - {0x8006, 88}, - {0x800a, 88}, - {0x800f, 88}, - {0x8018, 88}, - {0x801f, 88}, - {0x8029, 88}, - {0xc038, 88}, - {0x8003, 90}, - {0x8006, 90}, - {0x800a, 90}, - {0x800f, 90}, - {0x8018, 90}, - {0x801f, 90}, - {0x8029, 90}, - {0xc038, 90}, + {0x03, 2, 88}, + {0x06, 2, 88}, + {0x0a, 2, 88}, + {0x0f, 2, 88}, + {0x18, 2, 88}, + {0x1f, 2, 88}, + {0x29, 2, 88}, + {0x38, 3, 88}, + {0x03, 2, 90}, + {0x06, 2, 90}, + {0x0a, 2, 90}, + {0x0f, 2, 90}, + {0x18, 2, 90}, + {0x1f, 2, 90}, + {0x29, 2, 90}, + {0x38, 3, 90}, }, /* 74 */ { - {0x8001, 33}, - {0xc016, 33}, - {0x8001, 34}, - {0xc016, 34}, - {0x8001, 40}, - {0xc016, 40}, - {0x8001, 41}, - {0xc016, 41}, - {0x8001, 63}, - {0xc016, 63}, - {0xc000, 39}, - {0xc000, 43}, - {0xc000, 124}, - {0x53, 0}, - {0x55, 0}, - {0x58, 0}, + {0x01, 2, 33}, + {0x16, 3, 33}, + {0x01, 2, 34}, + {0x16, 3, 34}, + {0x01, 2, 40}, + {0x16, 3, 40}, + {0x01, 2, 41}, + {0x16, 3, 41}, + {0x01, 2, 63}, + {0x16, 3, 63}, + {0x00, 3, 39}, + {0x00, 3, 43}, + {0x00, 3, 124}, + {0x53, 0, 0}, + {0x55, 0, 0}, + {0x58, 0, 0}, }, /* 75 */ { - {0x8002, 33}, - {0x8009, 33}, - {0x8017, 33}, - {0xc028, 33}, - {0x8002, 34}, - {0x8009, 34}, - {0x8017, 34}, - {0xc028, 34}, - {0x8002, 40}, - {0x8009, 40}, - {0x8017, 40}, - {0xc028, 40}, - {0x8002, 41}, - {0x8009, 41}, - {0x8017, 41}, - {0xc028, 41}, + {0x02, 2, 33}, + {0x09, 2, 33}, + {0x17, 2, 33}, + {0x28, 3, 33}, + {0x02, 2, 34}, + {0x09, 2, 34}, + {0x17, 2, 34}, + {0x28, 3, 34}, + {0x02, 2, 40}, + {0x09, 2, 40}, + {0x17, 2, 40}, + {0x28, 3, 40}, + {0x02, 2, 41}, + {0x09, 2, 41}, + {0x17, 2, 41}, + {0x28, 3, 41}, }, /* 76 */ { - {0x8003, 33}, - {0x8006, 33}, - {0x800a, 33}, - {0x800f, 33}, - {0x8018, 33}, - {0x801f, 33}, - {0x8029, 33}, - {0xc038, 33}, - {0x8003, 34}, - {0x8006, 34}, - {0x800a, 34}, - {0x800f, 34}, - {0x8018, 34}, - {0x801f, 34}, - {0x8029, 34}, - {0xc038, 34}, + {0x03, 2, 33}, + {0x06, 2, 33}, + {0x0a, 2, 33}, + {0x0f, 2, 33}, + {0x18, 2, 33}, + {0x1f, 2, 33}, + {0x29, 2, 33}, + {0x38, 3, 33}, + {0x03, 2, 34}, + {0x06, 2, 34}, + {0x0a, 2, 34}, + {0x0f, 2, 34}, + {0x18, 2, 34}, + {0x1f, 2, 34}, + {0x29, 2, 34}, + {0x38, 3, 34}, }, /* 77 */ { - {0x8003, 40}, - {0x8006, 40}, - {0x800a, 40}, - {0x800f, 40}, - {0x8018, 40}, - {0x801f, 40}, - {0x8029, 40}, - {0xc038, 40}, - {0x8003, 41}, - {0x8006, 41}, - {0x800a, 41}, - {0x800f, 41}, - {0x8018, 41}, - {0x801f, 41}, - {0x8029, 41}, - {0xc038, 41}, + {0x03, 2, 40}, + {0x06, 2, 40}, + {0x0a, 2, 40}, + {0x0f, 2, 40}, + {0x18, 2, 40}, + {0x1f, 2, 40}, + {0x29, 2, 40}, + {0x38, 3, 40}, + {0x03, 2, 41}, + {0x06, 2, 41}, + {0x0a, 2, 41}, + {0x0f, 2, 41}, + {0x18, 2, 41}, + {0x1f, 2, 41}, + {0x29, 2, 41}, + {0x38, 3, 41}, }, /* 78 */ { - {0x8002, 63}, - {0x8009, 63}, - {0x8017, 63}, - {0xc028, 63}, - {0x8001, 39}, - {0xc016, 39}, - {0x8001, 43}, - {0xc016, 43}, - {0x8001, 124}, - {0xc016, 124}, - {0xc000, 35}, - {0xc000, 62}, - {0x56, 0}, - {0x57, 0}, - {0x59, 0}, - {0x5a, 0}, + {0x02, 2, 63}, + {0x09, 2, 63}, + {0x17, 2, 63}, + {0x28, 3, 63}, + {0x01, 2, 39}, + {0x16, 3, 39}, + {0x01, 2, 43}, + {0x16, 3, 43}, + {0x01, 2, 124}, + {0x16, 3, 124}, + {0x00, 3, 35}, + {0x00, 3, 62}, + {0x56, 0, 0}, + {0x57, 0, 0}, + {0x59, 0, 0}, + {0x5a, 0, 0}, }, /* 79 */ { - {0x8003, 63}, - {0x8006, 63}, - {0x800a, 63}, - {0x800f, 63}, - {0x8018, 63}, - {0x801f, 63}, - {0x8029, 63}, - {0xc038, 63}, - {0x8002, 39}, - {0x8009, 39}, - {0x8017, 39}, - {0xc028, 39}, - {0x8002, 43}, - {0x8009, 43}, - {0x8017, 43}, - {0xc028, 43}, + {0x03, 2, 63}, + {0x06, 2, 63}, + {0x0a, 2, 63}, + {0x0f, 2, 63}, + {0x18, 2, 63}, + {0x1f, 2, 63}, + {0x29, 2, 63}, + {0x38, 3, 63}, + {0x02, 2, 39}, + {0x09, 2, 39}, + {0x17, 2, 39}, + {0x28, 3, 39}, + {0x02, 2, 43}, + {0x09, 2, 43}, + {0x17, 2, 43}, + {0x28, 3, 43}, }, /* 80 */ { - {0x8003, 39}, - {0x8006, 39}, - {0x800a, 39}, - {0x800f, 39}, - {0x8018, 39}, - {0x801f, 39}, - {0x8029, 39}, - {0xc038, 39}, - {0x8003, 43}, - {0x8006, 43}, - {0x800a, 43}, - {0x800f, 43}, - {0x8018, 43}, - {0x801f, 43}, - {0x8029, 43}, - {0xc038, 43}, + {0x03, 2, 39}, + {0x06, 2, 39}, + {0x0a, 2, 39}, + {0x0f, 2, 39}, + {0x18, 2, 39}, + {0x1f, 2, 39}, + {0x29, 2, 39}, + {0x38, 3, 39}, + {0x03, 2, 43}, + {0x06, 2, 43}, + {0x0a, 2, 43}, + {0x0f, 2, 43}, + {0x18, 2, 43}, + {0x1f, 2, 43}, + {0x29, 2, 43}, + {0x38, 3, 43}, }, /* 81 */ { - {0x8002, 124}, - {0x8009, 124}, - {0x8017, 124}, - {0xc028, 124}, - {0x8001, 35}, - {0xc016, 35}, - {0x8001, 62}, - {0xc016, 62}, - {0xc000, 0}, - {0xc000, 36}, - {0xc000, 64}, - {0xc000, 91}, - {0xc000, 93}, - {0xc000, 126}, - {0x5b, 0}, - {0x5c, 0}, + {0x02, 2, 124}, + {0x09, 2, 124}, + {0x17, 2, 124}, + {0x28, 3, 124}, + {0x01, 2, 35}, + {0x16, 3, 35}, + {0x01, 2, 62}, + {0x16, 3, 62}, + {0x00, 3, 0}, + {0x00, 3, 36}, + {0x00, 3, 64}, + {0x00, 3, 91}, + {0x00, 3, 93}, + {0x00, 3, 126}, + {0x5b, 0, 0}, + {0x5c, 0, 0}, }, /* 82 */ { - {0x8003, 124}, - {0x8006, 124}, - {0x800a, 124}, - {0x800f, 124}, - {0x8018, 124}, - {0x801f, 124}, - {0x8029, 124}, - {0xc038, 124}, - {0x8002, 35}, - {0x8009, 35}, - {0x8017, 35}, - {0xc028, 35}, - {0x8002, 62}, - {0x8009, 62}, - {0x8017, 62}, - {0xc028, 62}, + {0x03, 2, 124}, + {0x06, 2, 124}, + {0x0a, 2, 124}, + {0x0f, 2, 124}, + {0x18, 2, 124}, + {0x1f, 2, 124}, + {0x29, 2, 124}, + {0x38, 3, 124}, + {0x02, 2, 35}, + {0x09, 2, 35}, + {0x17, 2, 35}, + {0x28, 3, 35}, + {0x02, 2, 62}, + {0x09, 2, 62}, + {0x17, 2, 62}, + {0x28, 3, 62}, }, /* 83 */ { - {0x8003, 35}, - {0x8006, 35}, - {0x800a, 35}, - {0x800f, 35}, - {0x8018, 35}, - {0x801f, 35}, - {0x8029, 35}, - {0xc038, 35}, - {0x8003, 62}, - {0x8006, 62}, - {0x800a, 62}, - {0x800f, 62}, - {0x8018, 62}, - {0x801f, 62}, - {0x8029, 62}, - {0xc038, 62}, + {0x03, 2, 35}, + {0x06, 2, 35}, + {0x0a, 2, 35}, + {0x0f, 2, 35}, + {0x18, 2, 35}, + {0x1f, 2, 35}, + {0x29, 2, 35}, + {0x38, 3, 35}, + {0x03, 2, 62}, + {0x06, 2, 62}, + {0x0a, 2, 62}, + {0x0f, 2, 62}, + {0x18, 2, 62}, + {0x1f, 2, 62}, + {0x29, 2, 62}, + {0x38, 3, 62}, }, /* 84 */ { - {0x8001, 0}, - {0xc016, 0}, - {0x8001, 36}, - {0xc016, 36}, - {0x8001, 64}, - {0xc016, 64}, - {0x8001, 91}, - {0xc016, 91}, - {0x8001, 93}, - {0xc016, 93}, - {0x8001, 126}, - {0xc016, 126}, - {0xc000, 94}, - {0xc000, 125}, - {0x5d, 0}, - {0x5e, 0}, + {0x01, 2, 0}, + {0x16, 3, 0}, + {0x01, 2, 36}, + {0x16, 3, 36}, + {0x01, 2, 64}, + {0x16, 3, 64}, + {0x01, 2, 91}, + {0x16, 3, 91}, + {0x01, 2, 93}, + {0x16, 3, 93}, + {0x01, 2, 126}, + {0x16, 3, 126}, + {0x00, 3, 94}, + {0x00, 3, 125}, + {0x5d, 0, 0}, + {0x5e, 0, 0}, }, /* 85 */ { - {0x8002, 0}, - {0x8009, 0}, - {0x8017, 0}, - {0xc028, 0}, - {0x8002, 36}, - {0x8009, 36}, - {0x8017, 36}, - {0xc028, 36}, - {0x8002, 64}, - {0x8009, 64}, - {0x8017, 64}, - {0xc028, 64}, - {0x8002, 91}, - {0x8009, 91}, - {0x8017, 91}, - {0xc028, 91}, + {0x02, 2, 0}, + {0x09, 2, 0}, + {0x17, 2, 0}, + {0x28, 3, 0}, + {0x02, 2, 36}, + {0x09, 2, 36}, + {0x17, 2, 36}, + {0x28, 3, 36}, + {0x02, 2, 64}, + {0x09, 2, 64}, + {0x17, 2, 64}, + {0x28, 3, 64}, + {0x02, 2, 91}, + {0x09, 2, 91}, + {0x17, 2, 91}, + {0x28, 3, 91}, }, /* 86 */ { - {0x8003, 0}, - {0x8006, 0}, - {0x800a, 0}, - {0x800f, 0}, - {0x8018, 0}, - {0x801f, 0}, - {0x8029, 0}, - {0xc038, 0}, - {0x8003, 36}, - {0x8006, 36}, - {0x800a, 36}, - {0x800f, 36}, - {0x8018, 36}, - {0x801f, 36}, - {0x8029, 36}, - {0xc038, 36}, + {0x03, 2, 0}, + {0x06, 2, 0}, + {0x0a, 2, 0}, + {0x0f, 2, 0}, + {0x18, 2, 0}, + {0x1f, 2, 0}, + {0x29, 2, 0}, + {0x38, 3, 0}, + {0x03, 2, 36}, + {0x06, 2, 36}, + {0x0a, 2, 36}, + {0x0f, 2, 36}, + {0x18, 2, 36}, + {0x1f, 2, 36}, + {0x29, 2, 36}, + {0x38, 3, 36}, }, /* 87 */ { - {0x8003, 64}, - {0x8006, 64}, - {0x800a, 64}, - {0x800f, 64}, - {0x8018, 64}, - {0x801f, 64}, - {0x8029, 64}, - {0xc038, 64}, - {0x8003, 91}, - {0x8006, 91}, - {0x800a, 91}, - {0x800f, 91}, - {0x8018, 91}, - {0x801f, 91}, - {0x8029, 91}, - {0xc038, 91}, + {0x03, 2, 64}, + {0x06, 2, 64}, + {0x0a, 2, 64}, + {0x0f, 2, 64}, + {0x18, 2, 64}, + {0x1f, 2, 64}, + {0x29, 2, 64}, + {0x38, 3, 64}, + {0x03, 2, 91}, + {0x06, 2, 91}, + {0x0a, 2, 91}, + {0x0f, 2, 91}, + {0x18, 2, 91}, + {0x1f, 2, 91}, + {0x29, 2, 91}, + {0x38, 3, 91}, }, /* 88 */ { - {0x8002, 93}, - {0x8009, 93}, - {0x8017, 93}, - {0xc028, 93}, - {0x8002, 126}, - {0x8009, 126}, - {0x8017, 126}, - {0xc028, 126}, - {0x8001, 94}, - {0xc016, 94}, - {0x8001, 125}, - {0xc016, 125}, - {0xc000, 60}, - {0xc000, 96}, - {0xc000, 123}, - {0x5f, 0}, + {0x02, 2, 93}, + {0x09, 2, 93}, + {0x17, 2, 93}, + {0x28, 3, 93}, + {0x02, 2, 126}, + {0x09, 2, 126}, + {0x17, 2, 126}, + {0x28, 3, 126}, + {0x01, 2, 94}, + {0x16, 3, 94}, + {0x01, 2, 125}, + {0x16, 3, 125}, + {0x00, 3, 60}, + {0x00, 3, 96}, + {0x00, 3, 123}, + {0x5f, 0, 0}, }, /* 89 */ { - {0x8003, 93}, - {0x8006, 93}, - {0x800a, 93}, - {0x800f, 93}, - {0x8018, 93}, - {0x801f, 93}, - {0x8029, 93}, - {0xc038, 93}, - {0x8003, 126}, - {0x8006, 126}, - {0x800a, 126}, - {0x800f, 126}, - {0x8018, 126}, - {0x801f, 126}, - {0x8029, 126}, - {0xc038, 126}, + {0x03, 2, 93}, + {0x06, 2, 93}, + {0x0a, 2, 93}, + {0x0f, 2, 93}, + {0x18, 2, 93}, + {0x1f, 2, 93}, + {0x29, 2, 93}, + {0x38, 3, 93}, + {0x03, 2, 126}, + {0x06, 2, 126}, + {0x0a, 2, 126}, + {0x0f, 2, 126}, + {0x18, 2, 126}, + {0x1f, 2, 126}, + {0x29, 2, 126}, + {0x38, 3, 126}, }, /* 90 */ { - {0x8002, 94}, - {0x8009, 94}, - {0x8017, 94}, - {0xc028, 94}, - {0x8002, 125}, - {0x8009, 125}, - {0x8017, 125}, - {0xc028, 125}, - {0x8001, 60}, - {0xc016, 60}, - {0x8001, 96}, - {0xc016, 96}, - {0x8001, 123}, - {0xc016, 123}, - {0x60, 0}, - {0x6e, 0}, + {0x02, 2, 94}, + {0x09, 2, 94}, + {0x17, 2, 94}, + {0x28, 3, 94}, + {0x02, 2, 125}, + {0x09, 2, 125}, + {0x17, 2, 125}, + {0x28, 3, 125}, + {0x01, 2, 60}, + {0x16, 3, 60}, + {0x01, 2, 96}, + {0x16, 3, 96}, + {0x01, 2, 123}, + {0x16, 3, 123}, + {0x60, 0, 0}, + {0x6e, 0, 0}, }, /* 91 */ { - {0x8003, 94}, - {0x8006, 94}, - {0x800a, 94}, - {0x800f, 94}, - {0x8018, 94}, - {0x801f, 94}, - {0x8029, 94}, - {0xc038, 94}, - {0x8003, 125}, - {0x8006, 125}, - {0x800a, 125}, - {0x800f, 125}, - {0x8018, 125}, - {0x801f, 125}, - {0x8029, 125}, - {0xc038, 125}, + {0x03, 2, 94}, + {0x06, 2, 94}, + {0x0a, 2, 94}, + {0x0f, 2, 94}, + {0x18, 2, 94}, + {0x1f, 2, 94}, + {0x29, 2, 94}, + {0x38, 3, 94}, + {0x03, 2, 125}, + {0x06, 2, 125}, + {0x0a, 2, 125}, + {0x0f, 2, 125}, + {0x18, 2, 125}, + {0x1f, 2, 125}, + {0x29, 2, 125}, + {0x38, 3, 125}, }, /* 92 */ { - {0x8002, 60}, - {0x8009, 60}, - {0x8017, 60}, - {0xc028, 60}, - {0x8002, 96}, - {0x8009, 96}, - {0x8017, 96}, - {0xc028, 96}, - {0x8002, 123}, - {0x8009, 123}, - {0x8017, 123}, - {0xc028, 123}, - {0x61, 0}, - {0x65, 0}, - {0x6f, 0}, - {0x85, 0}, + {0x02, 2, 60}, + {0x09, 2, 60}, + {0x17, 2, 60}, + {0x28, 3, 60}, + {0x02, 2, 96}, + {0x09, 2, 96}, + {0x17, 2, 96}, + {0x28, 3, 96}, + {0x02, 2, 123}, + {0x09, 2, 123}, + {0x17, 2, 123}, + {0x28, 3, 123}, + {0x61, 0, 0}, + {0x65, 0, 0}, + {0x6f, 0, 0}, + {0x85, 0, 0}, }, /* 93 */ { - {0x8003, 60}, - {0x8006, 60}, - {0x800a, 60}, - {0x800f, 60}, - {0x8018, 60}, - {0x801f, 60}, - {0x8029, 60}, - {0xc038, 60}, - {0x8003, 96}, - {0x8006, 96}, - {0x800a, 96}, - {0x800f, 96}, - {0x8018, 96}, - {0x801f, 96}, - {0x8029, 96}, - {0xc038, 96}, + {0x03, 2, 60}, + {0x06, 2, 60}, + {0x0a, 2, 60}, + {0x0f, 2, 60}, + {0x18, 2, 60}, + {0x1f, 2, 60}, + {0x29, 2, 60}, + {0x38, 3, 60}, + {0x03, 2, 96}, + {0x06, 2, 96}, + {0x0a, 2, 96}, + {0x0f, 2, 96}, + {0x18, 2, 96}, + {0x1f, 2, 96}, + {0x29, 2, 96}, + {0x38, 3, 96}, }, /* 94 */ { - {0x8003, 123}, - {0x8006, 123}, - {0x800a, 123}, - {0x800f, 123}, - {0x8018, 123}, - {0x801f, 123}, - {0x8029, 123}, - {0xc038, 123}, - {0x62, 0}, - {0x63, 0}, - {0x66, 0}, - {0x69, 0}, - {0x70, 0}, - {0x77, 0}, - {0x86, 0}, - {0x99, 0}, + {0x03, 2, 123}, + {0x06, 2, 123}, + {0x0a, 2, 123}, + {0x0f, 2, 123}, + {0x18, 2, 123}, + {0x1f, 2, 123}, + {0x29, 2, 123}, + {0x38, 3, 123}, + {0x62, 0, 0}, + {0x63, 0, 0}, + {0x66, 0, 0}, + {0x69, 0, 0}, + {0x70, 0, 0}, + {0x77, 0, 0}, + {0x86, 0, 0}, + {0x99, 0, 0}, }, /* 95 */ { - {0xc000, 92}, - {0xc000, 195}, - {0xc000, 208}, - {0x64, 0}, - {0x67, 0}, - {0x68, 0}, - {0x6a, 0}, - {0x6b, 0}, - {0x71, 0}, - {0x74, 0}, - {0x78, 0}, - {0x7e, 0}, - {0x87, 0}, - {0x8e, 0}, - {0x9a, 0}, - {0xa9, 0}, + {0x00, 3, 92}, + {0x00, 3, 195}, + {0x00, 3, 208}, + {0x64, 0, 0}, + {0x67, 0, 0}, + {0x68, 0, 0}, + {0x6a, 0, 0}, + {0x6b, 0, 0}, + {0x71, 0, 0}, + {0x74, 0, 0}, + {0x78, 0, 0}, + {0x7e, 0, 0}, + {0x87, 0, 0}, + {0x8e, 0, 0}, + {0x9a, 0, 0}, + {0xa9, 0, 0}, }, /* 96 */ { - {0x8001, 92}, - {0xc016, 92}, - {0x8001, 195}, - {0xc016, 195}, - {0x8001, 208}, - {0xc016, 208}, - {0xc000, 128}, - {0xc000, 130}, - {0xc000, 131}, - {0xc000, 162}, - {0xc000, 184}, - {0xc000, 194}, - {0xc000, 224}, - {0xc000, 226}, - {0x6c, 0}, - {0x6d, 0}, + {0x01, 2, 92}, + {0x16, 3, 92}, + {0x01, 2, 195}, + {0x16, 3, 195}, + {0x01, 2, 208}, + {0x16, 3, 208}, + {0x00, 3, 128}, + {0x00, 3, 130}, + {0x00, 3, 131}, + {0x00, 3, 162}, + {0x00, 3, 184}, + {0x00, 3, 194}, + {0x00, 3, 224}, + {0x00, 3, 226}, + {0x6c, 0, 0}, + {0x6d, 0, 0}, }, /* 97 */ { - {0x8002, 92}, - {0x8009, 92}, - {0x8017, 92}, - {0xc028, 92}, - {0x8002, 195}, - {0x8009, 195}, - {0x8017, 195}, - {0xc028, 195}, - {0x8002, 208}, - {0x8009, 208}, - {0x8017, 208}, - {0xc028, 208}, - {0x8001, 128}, - {0xc016, 128}, - {0x8001, 130}, - {0xc016, 130}, + {0x02, 2, 92}, + {0x09, 2, 92}, + {0x17, 2, 92}, + {0x28, 3, 92}, + {0x02, 2, 195}, + {0x09, 2, 195}, + {0x17, 2, 195}, + {0x28, 3, 195}, + {0x02, 2, 208}, + {0x09, 2, 208}, + {0x17, 2, 208}, + {0x28, 3, 208}, + {0x01, 2, 128}, + {0x16, 3, 128}, + {0x01, 2, 130}, + {0x16, 3, 130}, }, /* 98 */ { - {0x8003, 92}, - {0x8006, 92}, - {0x800a, 92}, - {0x800f, 92}, - {0x8018, 92}, - {0x801f, 92}, - {0x8029, 92}, - {0xc038, 92}, - {0x8003, 195}, - {0x8006, 195}, - {0x800a, 195}, - {0x800f, 195}, - {0x8018, 195}, - {0x801f, 195}, - {0x8029, 195}, - {0xc038, 195}, + {0x03, 2, 92}, + {0x06, 2, 92}, + {0x0a, 2, 92}, + {0x0f, 2, 92}, + {0x18, 2, 92}, + {0x1f, 2, 92}, + {0x29, 2, 92}, + {0x38, 3, 92}, + {0x03, 2, 195}, + {0x06, 2, 195}, + {0x0a, 2, 195}, + {0x0f, 2, 195}, + {0x18, 2, 195}, + {0x1f, 2, 195}, + {0x29, 2, 195}, + {0x38, 3, 195}, }, /* 99 */ { - {0x8003, 208}, - {0x8006, 208}, - {0x800a, 208}, - {0x800f, 208}, - {0x8018, 208}, - {0x801f, 208}, - {0x8029, 208}, - {0xc038, 208}, - {0x8002, 128}, - {0x8009, 128}, - {0x8017, 128}, - {0xc028, 128}, - {0x8002, 130}, - {0x8009, 130}, - {0x8017, 130}, - {0xc028, 130}, + {0x03, 2, 208}, + {0x06, 2, 208}, + {0x0a, 2, 208}, + {0x0f, 2, 208}, + {0x18, 2, 208}, + {0x1f, 2, 208}, + {0x29, 2, 208}, + {0x38, 3, 208}, + {0x02, 2, 128}, + {0x09, 2, 128}, + {0x17, 2, 128}, + {0x28, 3, 128}, + {0x02, 2, 130}, + {0x09, 2, 130}, + {0x17, 2, 130}, + {0x28, 3, 130}, }, /* 100 */ { - {0x8003, 128}, - {0x8006, 128}, - {0x800a, 128}, - {0x800f, 128}, - {0x8018, 128}, - {0x801f, 128}, - {0x8029, 128}, - {0xc038, 128}, - {0x8003, 130}, - {0x8006, 130}, - {0x800a, 130}, - {0x800f, 130}, - {0x8018, 130}, - {0x801f, 130}, - {0x8029, 130}, - {0xc038, 130}, + {0x03, 2, 128}, + {0x06, 2, 128}, + {0x0a, 2, 128}, + {0x0f, 2, 128}, + {0x18, 2, 128}, + {0x1f, 2, 128}, + {0x29, 2, 128}, + {0x38, 3, 128}, + {0x03, 2, 130}, + {0x06, 2, 130}, + {0x0a, 2, 130}, + {0x0f, 2, 130}, + {0x18, 2, 130}, + {0x1f, 2, 130}, + {0x29, 2, 130}, + {0x38, 3, 130}, }, /* 101 */ { - {0x8001, 131}, - {0xc016, 131}, - {0x8001, 162}, - {0xc016, 162}, - {0x8001, 184}, - {0xc016, 184}, - {0x8001, 194}, - {0xc016, 194}, - {0x8001, 224}, - {0xc016, 224}, - {0x8001, 226}, - {0xc016, 226}, - {0xc000, 153}, - {0xc000, 161}, - {0xc000, 167}, - {0xc000, 172}, + {0x01, 2, 131}, + {0x16, 3, 131}, + {0x01, 2, 162}, + {0x16, 3, 162}, + {0x01, 2, 184}, + {0x16, 3, 184}, + {0x01, 2, 194}, + {0x16, 3, 194}, + {0x01, 2, 224}, + {0x16, 3, 224}, + {0x01, 2, 226}, + {0x16, 3, 226}, + {0x00, 3, 153}, + {0x00, 3, 161}, + {0x00, 3, 167}, + {0x00, 3, 172}, }, /* 102 */ { - {0x8002, 131}, - {0x8009, 131}, - {0x8017, 131}, - {0xc028, 131}, - {0x8002, 162}, - {0x8009, 162}, - {0x8017, 162}, - {0xc028, 162}, - {0x8002, 184}, - {0x8009, 184}, - {0x8017, 184}, - {0xc028, 184}, - {0x8002, 194}, - {0x8009, 194}, - {0x8017, 194}, - {0xc028, 194}, + {0x02, 2, 131}, + {0x09, 2, 131}, + {0x17, 2, 131}, + {0x28, 3, 131}, + {0x02, 2, 162}, + {0x09, 2, 162}, + {0x17, 2, 162}, + {0x28, 3, 162}, + {0x02, 2, 184}, + {0x09, 2, 184}, + {0x17, 2, 184}, + {0x28, 3, 184}, + {0x02, 2, 194}, + {0x09, 2, 194}, + {0x17, 2, 194}, + {0x28, 3, 194}, }, /* 103 */ { - {0x8003, 131}, - {0x8006, 131}, - {0x800a, 131}, - {0x800f, 131}, - {0x8018, 131}, - {0x801f, 131}, - {0x8029, 131}, - {0xc038, 131}, - {0x8003, 162}, - {0x8006, 162}, - {0x800a, 162}, - {0x800f, 162}, - {0x8018, 162}, - {0x801f, 162}, - {0x8029, 162}, - {0xc038, 162}, + {0x03, 2, 131}, + {0x06, 2, 131}, + {0x0a, 2, 131}, + {0x0f, 2, 131}, + {0x18, 2, 131}, + {0x1f, 2, 131}, + {0x29, 2, 131}, + {0x38, 3, 131}, + {0x03, 2, 162}, + {0x06, 2, 162}, + {0x0a, 2, 162}, + {0x0f, 2, 162}, + {0x18, 2, 162}, + {0x1f, 2, 162}, + {0x29, 2, 162}, + {0x38, 3, 162}, }, /* 104 */ { - {0x8003, 184}, - {0x8006, 184}, - {0x800a, 184}, - {0x800f, 184}, - {0x8018, 184}, - {0x801f, 184}, - {0x8029, 184}, - {0xc038, 184}, - {0x8003, 194}, - {0x8006, 194}, - {0x800a, 194}, - {0x800f, 194}, - {0x8018, 194}, - {0x801f, 194}, - {0x8029, 194}, - {0xc038, 194}, + {0x03, 2, 184}, + {0x06, 2, 184}, + {0x0a, 2, 184}, + {0x0f, 2, 184}, + {0x18, 2, 184}, + {0x1f, 2, 184}, + {0x29, 2, 184}, + {0x38, 3, 184}, + {0x03, 2, 194}, + {0x06, 2, 194}, + {0x0a, 2, 194}, + {0x0f, 2, 194}, + {0x18, 2, 194}, + {0x1f, 2, 194}, + {0x29, 2, 194}, + {0x38, 3, 194}, }, /* 105 */ { - {0x8002, 224}, - {0x8009, 224}, - {0x8017, 224}, - {0xc028, 224}, - {0x8002, 226}, - {0x8009, 226}, - {0x8017, 226}, - {0xc028, 226}, - {0x8001, 153}, - {0xc016, 153}, - {0x8001, 161}, - {0xc016, 161}, - {0x8001, 167}, - {0xc016, 167}, - {0x8001, 172}, - {0xc016, 172}, + {0x02, 2, 224}, + {0x09, 2, 224}, + {0x17, 2, 224}, + {0x28, 3, 224}, + {0x02, 2, 226}, + {0x09, 2, 226}, + {0x17, 2, 226}, + {0x28, 3, 226}, + {0x01, 2, 153}, + {0x16, 3, 153}, + {0x01, 2, 161}, + {0x16, 3, 161}, + {0x01, 2, 167}, + {0x16, 3, 167}, + {0x01, 2, 172}, + {0x16, 3, 172}, }, /* 106 */ { - {0x8003, 224}, - {0x8006, 224}, - {0x800a, 224}, - {0x800f, 224}, - {0x8018, 224}, - {0x801f, 224}, - {0x8029, 224}, - {0xc038, 224}, - {0x8003, 226}, - {0x8006, 226}, - {0x800a, 226}, - {0x800f, 226}, - {0x8018, 226}, - {0x801f, 226}, - {0x8029, 226}, - {0xc038, 226}, + {0x03, 2, 224}, + {0x06, 2, 224}, + {0x0a, 2, 224}, + {0x0f, 2, 224}, + {0x18, 2, 224}, + {0x1f, 2, 224}, + {0x29, 2, 224}, + {0x38, 3, 224}, + {0x03, 2, 226}, + {0x06, 2, 226}, + {0x0a, 2, 226}, + {0x0f, 2, 226}, + {0x18, 2, 226}, + {0x1f, 2, 226}, + {0x29, 2, 226}, + {0x38, 3, 226}, }, /* 107 */ { - {0x8002, 153}, - {0x8009, 153}, - {0x8017, 153}, - {0xc028, 153}, - {0x8002, 161}, - {0x8009, 161}, - {0x8017, 161}, - {0xc028, 161}, - {0x8002, 167}, - {0x8009, 167}, - {0x8017, 167}, - {0xc028, 167}, - {0x8002, 172}, - {0x8009, 172}, - {0x8017, 172}, - {0xc028, 172}, + {0x02, 2, 153}, + {0x09, 2, 153}, + {0x17, 2, 153}, + {0x28, 3, 153}, + {0x02, 2, 161}, + {0x09, 2, 161}, + {0x17, 2, 161}, + {0x28, 3, 161}, + {0x02, 2, 167}, + {0x09, 2, 167}, + {0x17, 2, 167}, + {0x28, 3, 167}, + {0x02, 2, 172}, + {0x09, 2, 172}, + {0x17, 2, 172}, + {0x28, 3, 172}, }, /* 108 */ { - {0x8003, 153}, - {0x8006, 153}, - {0x800a, 153}, - {0x800f, 153}, - {0x8018, 153}, - {0x801f, 153}, - {0x8029, 153}, - {0xc038, 153}, - {0x8003, 161}, - {0x8006, 161}, - {0x800a, 161}, - {0x800f, 161}, - {0x8018, 161}, - {0x801f, 161}, - {0x8029, 161}, - {0xc038, 161}, + {0x03, 2, 153}, + {0x06, 2, 153}, + {0x0a, 2, 153}, + {0x0f, 2, 153}, + {0x18, 2, 153}, + {0x1f, 2, 153}, + {0x29, 2, 153}, + {0x38, 3, 153}, + {0x03, 2, 161}, + {0x06, 2, 161}, + {0x0a, 2, 161}, + {0x0f, 2, 161}, + {0x18, 2, 161}, + {0x1f, 2, 161}, + {0x29, 2, 161}, + {0x38, 3, 161}, }, /* 109 */ { - {0x8003, 167}, - {0x8006, 167}, - {0x800a, 167}, - {0x800f, 167}, - {0x8018, 167}, - {0x801f, 167}, - {0x8029, 167}, - {0xc038, 167}, - {0x8003, 172}, - {0x8006, 172}, - {0x800a, 172}, - {0x800f, 172}, - {0x8018, 172}, - {0x801f, 172}, - {0x8029, 172}, - {0xc038, 172}, + {0x03, 2, 167}, + {0x06, 2, 167}, + {0x0a, 2, 167}, + {0x0f, 2, 167}, + {0x18, 2, 167}, + {0x1f, 2, 167}, + {0x29, 2, 167}, + {0x38, 3, 167}, + {0x03, 2, 172}, + {0x06, 2, 172}, + {0x0a, 2, 172}, + {0x0f, 2, 172}, + {0x18, 2, 172}, + {0x1f, 2, 172}, + {0x29, 2, 172}, + {0x38, 3, 172}, }, /* 110 */ { - {0x72, 0}, - {0x73, 0}, - {0x75, 0}, - {0x76, 0}, - {0x79, 0}, - {0x7b, 0}, - {0x7f, 0}, - {0x82, 0}, - {0x88, 0}, - {0x8b, 0}, - {0x8f, 0}, - {0x92, 0}, - {0x9b, 0}, - {0xa2, 0}, - {0xaa, 0}, - {0xb4, 0}, + {0x72, 0, 0}, + {0x73, 0, 0}, + {0x75, 0, 0}, + {0x76, 0, 0}, + {0x79, 0, 0}, + {0x7b, 0, 0}, + {0x7f, 0, 0}, + {0x82, 0, 0}, + {0x88, 0, 0}, + {0x8b, 0, 0}, + {0x8f, 0, 0}, + {0x92, 0, 0}, + {0x9b, 0, 0}, + {0xa2, 0, 0}, + {0xaa, 0, 0}, + {0xb4, 0, 0}, }, /* 111 */ { - {0xc000, 176}, - {0xc000, 177}, - {0xc000, 179}, - {0xc000, 209}, - {0xc000, 216}, - {0xc000, 217}, - {0xc000, 227}, - {0xc000, 229}, - {0xc000, 230}, - {0x7a, 0}, - {0x7c, 0}, - {0x7d, 0}, - {0x80, 0}, - {0x81, 0}, - {0x83, 0}, - {0x84, 0}, + {0x00, 3, 176}, + {0x00, 3, 177}, + {0x00, 3, 179}, + {0x00, 3, 209}, + {0x00, 3, 216}, + {0x00, 3, 217}, + {0x00, 3, 227}, + {0x00, 3, 229}, + {0x00, 3, 230}, + {0x7a, 0, 0}, + {0x7c, 0, 0}, + {0x7d, 0, 0}, + {0x80, 0, 0}, + {0x81, 0, 0}, + {0x83, 0, 0}, + {0x84, 0, 0}, }, /* 112 */ { - {0x8001, 176}, - {0xc016, 176}, - {0x8001, 177}, - {0xc016, 177}, - {0x8001, 179}, - {0xc016, 179}, - {0x8001, 209}, - {0xc016, 209}, - {0x8001, 216}, - {0xc016, 216}, - {0x8001, 217}, - {0xc016, 217}, - {0x8001, 227}, - {0xc016, 227}, - {0x8001, 229}, - {0xc016, 229}, + {0x01, 2, 176}, + {0x16, 3, 176}, + {0x01, 2, 177}, + {0x16, 3, 177}, + {0x01, 2, 179}, + {0x16, 3, 179}, + {0x01, 2, 209}, + {0x16, 3, 209}, + {0x01, 2, 216}, + {0x16, 3, 216}, + {0x01, 2, 217}, + {0x16, 3, 217}, + {0x01, 2, 227}, + {0x16, 3, 227}, + {0x01, 2, 229}, + {0x16, 3, 229}, }, /* 113 */ { - {0x8002, 176}, - {0x8009, 176}, - {0x8017, 176}, - {0xc028, 176}, - {0x8002, 177}, - {0x8009, 177}, - {0x8017, 177}, - {0xc028, 177}, - {0x8002, 179}, - {0x8009, 179}, - {0x8017, 179}, - {0xc028, 179}, - {0x8002, 209}, - {0x8009, 209}, - {0x8017, 209}, - {0xc028, 209}, + {0x02, 2, 176}, + {0x09, 2, 176}, + {0x17, 2, 176}, + {0x28, 3, 176}, + {0x02, 2, 177}, + {0x09, 2, 177}, + {0x17, 2, 177}, + {0x28, 3, 177}, + {0x02, 2, 179}, + {0x09, 2, 179}, + {0x17, 2, 179}, + {0x28, 3, 179}, + {0x02, 2, 209}, + {0x09, 2, 209}, + {0x17, 2, 209}, + {0x28, 3, 209}, }, /* 114 */ { - {0x8003, 176}, - {0x8006, 176}, - {0x800a, 176}, - {0x800f, 176}, - {0x8018, 176}, - {0x801f, 176}, - {0x8029, 176}, - {0xc038, 176}, - {0x8003, 177}, - {0x8006, 177}, - {0x800a, 177}, - {0x800f, 177}, - {0x8018, 177}, - {0x801f, 177}, - {0x8029, 177}, - {0xc038, 177}, + {0x03, 2, 176}, + {0x06, 2, 176}, + {0x0a, 2, 176}, + {0x0f, 2, 176}, + {0x18, 2, 176}, + {0x1f, 2, 176}, + {0x29, 2, 176}, + {0x38, 3, 176}, + {0x03, 2, 177}, + {0x06, 2, 177}, + {0x0a, 2, 177}, + {0x0f, 2, 177}, + {0x18, 2, 177}, + {0x1f, 2, 177}, + {0x29, 2, 177}, + {0x38, 3, 177}, }, /* 115 */ { - {0x8003, 179}, - {0x8006, 179}, - {0x800a, 179}, - {0x800f, 179}, - {0x8018, 179}, - {0x801f, 179}, - {0x8029, 179}, - {0xc038, 179}, - {0x8003, 209}, - {0x8006, 209}, - {0x800a, 209}, - {0x800f, 209}, - {0x8018, 209}, - {0x801f, 209}, - {0x8029, 209}, - {0xc038, 209}, + {0x03, 2, 179}, + {0x06, 2, 179}, + {0x0a, 2, 179}, + {0x0f, 2, 179}, + {0x18, 2, 179}, + {0x1f, 2, 179}, + {0x29, 2, 179}, + {0x38, 3, 179}, + {0x03, 2, 209}, + {0x06, 2, 209}, + {0x0a, 2, 209}, + {0x0f, 2, 209}, + {0x18, 2, 209}, + {0x1f, 2, 209}, + {0x29, 2, 209}, + {0x38, 3, 209}, }, /* 116 */ { - {0x8002, 216}, - {0x8009, 216}, - {0x8017, 216}, - {0xc028, 216}, - {0x8002, 217}, - {0x8009, 217}, - {0x8017, 217}, - {0xc028, 217}, - {0x8002, 227}, - {0x8009, 227}, - {0x8017, 227}, - {0xc028, 227}, - {0x8002, 229}, - {0x8009, 229}, - {0x8017, 229}, - {0xc028, 229}, + {0x02, 2, 216}, + {0x09, 2, 216}, + {0x17, 2, 216}, + {0x28, 3, 216}, + {0x02, 2, 217}, + {0x09, 2, 217}, + {0x17, 2, 217}, + {0x28, 3, 217}, + {0x02, 2, 227}, + {0x09, 2, 227}, + {0x17, 2, 227}, + {0x28, 3, 227}, + {0x02, 2, 229}, + {0x09, 2, 229}, + {0x17, 2, 229}, + {0x28, 3, 229}, }, /* 117 */ { - {0x8003, 216}, - {0x8006, 216}, - {0x800a, 216}, - {0x800f, 216}, - {0x8018, 216}, - {0x801f, 216}, - {0x8029, 216}, - {0xc038, 216}, - {0x8003, 217}, - {0x8006, 217}, - {0x800a, 217}, - {0x800f, 217}, - {0x8018, 217}, - {0x801f, 217}, - {0x8029, 217}, - {0xc038, 217}, + {0x03, 2, 216}, + {0x06, 2, 216}, + {0x0a, 2, 216}, + {0x0f, 2, 216}, + {0x18, 2, 216}, + {0x1f, 2, 216}, + {0x29, 2, 216}, + {0x38, 3, 216}, + {0x03, 2, 217}, + {0x06, 2, 217}, + {0x0a, 2, 217}, + {0x0f, 2, 217}, + {0x18, 2, 217}, + {0x1f, 2, 217}, + {0x29, 2, 217}, + {0x38, 3, 217}, }, /* 118 */ { - {0x8003, 227}, - {0x8006, 227}, - {0x800a, 227}, - {0x800f, 227}, - {0x8018, 227}, - {0x801f, 227}, - {0x8029, 227}, - {0xc038, 227}, - {0x8003, 229}, - {0x8006, 229}, - {0x800a, 229}, - {0x800f, 229}, - {0x8018, 229}, - {0x801f, 229}, - {0x8029, 229}, - {0xc038, 229}, + {0x03, 2, 227}, + {0x06, 2, 227}, + {0x0a, 2, 227}, + {0x0f, 2, 227}, + {0x18, 2, 227}, + {0x1f, 2, 227}, + {0x29, 2, 227}, + {0x38, 3, 227}, + {0x03, 2, 229}, + {0x06, 2, 229}, + {0x0a, 2, 229}, + {0x0f, 2, 229}, + {0x18, 2, 229}, + {0x1f, 2, 229}, + {0x29, 2, 229}, + {0x38, 3, 229}, }, /* 119 */ { - {0x8001, 230}, - {0xc016, 230}, - {0xc000, 129}, - {0xc000, 132}, - {0xc000, 133}, - {0xc000, 134}, - {0xc000, 136}, - {0xc000, 146}, - {0xc000, 154}, - {0xc000, 156}, - {0xc000, 160}, - {0xc000, 163}, - {0xc000, 164}, - {0xc000, 169}, - {0xc000, 170}, - {0xc000, 173}, + {0x01, 2, 230}, + {0x16, 3, 230}, + {0x00, 3, 129}, + {0x00, 3, 132}, + {0x00, 3, 133}, + {0x00, 3, 134}, + {0x00, 3, 136}, + {0x00, 3, 146}, + {0x00, 3, 154}, + {0x00, 3, 156}, + {0x00, 3, 160}, + {0x00, 3, 163}, + {0x00, 3, 164}, + {0x00, 3, 169}, + {0x00, 3, 170}, + {0x00, 3, 173}, }, /* 120 */ { - {0x8002, 230}, - {0x8009, 230}, - {0x8017, 230}, - {0xc028, 230}, - {0x8001, 129}, - {0xc016, 129}, - {0x8001, 132}, - {0xc016, 132}, - {0x8001, 133}, - {0xc016, 133}, - {0x8001, 134}, - {0xc016, 134}, - {0x8001, 136}, - {0xc016, 136}, - {0x8001, 146}, - {0xc016, 146}, + {0x02, 2, 230}, + {0x09, 2, 230}, + {0x17, 2, 230}, + {0x28, 3, 230}, + {0x01, 2, 129}, + {0x16, 3, 129}, + {0x01, 2, 132}, + {0x16, 3, 132}, + {0x01, 2, 133}, + {0x16, 3, 133}, + {0x01, 2, 134}, + {0x16, 3, 134}, + {0x01, 2, 136}, + {0x16, 3, 136}, + {0x01, 2, 146}, + {0x16, 3, 146}, }, /* 121 */ { - {0x8003, 230}, - {0x8006, 230}, - {0x800a, 230}, - {0x800f, 230}, - {0x8018, 230}, - {0x801f, 230}, - {0x8029, 230}, - {0xc038, 230}, - {0x8002, 129}, - {0x8009, 129}, - {0x8017, 129}, - {0xc028, 129}, - {0x8002, 132}, - {0x8009, 132}, - {0x8017, 132}, - {0xc028, 132}, + {0x03, 2, 230}, + {0x06, 2, 230}, + {0x0a, 2, 230}, + {0x0f, 2, 230}, + {0x18, 2, 230}, + {0x1f, 2, 230}, + {0x29, 2, 230}, + {0x38, 3, 230}, + {0x02, 2, 129}, + {0x09, 2, 129}, + {0x17, 2, 129}, + {0x28, 3, 129}, + {0x02, 2, 132}, + {0x09, 2, 132}, + {0x17, 2, 132}, + {0x28, 3, 132}, }, /* 122 */ { - {0x8003, 129}, - {0x8006, 129}, - {0x800a, 129}, - {0x800f, 129}, - {0x8018, 129}, - {0x801f, 129}, - {0x8029, 129}, - {0xc038, 129}, - {0x8003, 132}, - {0x8006, 132}, - {0x800a, 132}, - {0x800f, 132}, - {0x8018, 132}, - {0x801f, 132}, - {0x8029, 132}, - {0xc038, 132}, + {0x03, 2, 129}, + {0x06, 2, 129}, + {0x0a, 2, 129}, + {0x0f, 2, 129}, + {0x18, 2, 129}, + {0x1f, 2, 129}, + {0x29, 2, 129}, + {0x38, 3, 129}, + {0x03, 2, 132}, + {0x06, 2, 132}, + {0x0a, 2, 132}, + {0x0f, 2, 132}, + {0x18, 2, 132}, + {0x1f, 2, 132}, + {0x29, 2, 132}, + {0x38, 3, 132}, }, /* 123 */ { - {0x8002, 133}, - {0x8009, 133}, - {0x8017, 133}, - {0xc028, 133}, - {0x8002, 134}, - {0x8009, 134}, - {0x8017, 134}, - {0xc028, 134}, - {0x8002, 136}, - {0x8009, 136}, - {0x8017, 136}, - {0xc028, 136}, - {0x8002, 146}, - {0x8009, 146}, - {0x8017, 146}, - {0xc028, 146}, + {0x02, 2, 133}, + {0x09, 2, 133}, + {0x17, 2, 133}, + {0x28, 3, 133}, + {0x02, 2, 134}, + {0x09, 2, 134}, + {0x17, 2, 134}, + {0x28, 3, 134}, + {0x02, 2, 136}, + {0x09, 2, 136}, + {0x17, 2, 136}, + {0x28, 3, 136}, + {0x02, 2, 146}, + {0x09, 2, 146}, + {0x17, 2, 146}, + {0x28, 3, 146}, }, /* 124 */ { - {0x8003, 133}, - {0x8006, 133}, - {0x800a, 133}, - {0x800f, 133}, - {0x8018, 133}, - {0x801f, 133}, - {0x8029, 133}, - {0xc038, 133}, - {0x8003, 134}, - {0x8006, 134}, - {0x800a, 134}, - {0x800f, 134}, - {0x8018, 134}, - {0x801f, 134}, - {0x8029, 134}, - {0xc038, 134}, + {0x03, 2, 133}, + {0x06, 2, 133}, + {0x0a, 2, 133}, + {0x0f, 2, 133}, + {0x18, 2, 133}, + {0x1f, 2, 133}, + {0x29, 2, 133}, + {0x38, 3, 133}, + {0x03, 2, 134}, + {0x06, 2, 134}, + {0x0a, 2, 134}, + {0x0f, 2, 134}, + {0x18, 2, 134}, + {0x1f, 2, 134}, + {0x29, 2, 134}, + {0x38, 3, 134}, }, /* 125 */ { - {0x8003, 136}, - {0x8006, 136}, - {0x800a, 136}, - {0x800f, 136}, - {0x8018, 136}, - {0x801f, 136}, - {0x8029, 136}, - {0xc038, 136}, - {0x8003, 146}, - {0x8006, 146}, - {0x800a, 146}, - {0x800f, 146}, - {0x8018, 146}, - {0x801f, 146}, - {0x8029, 146}, - {0xc038, 146}, + {0x03, 2, 136}, + {0x06, 2, 136}, + {0x0a, 2, 136}, + {0x0f, 2, 136}, + {0x18, 2, 136}, + {0x1f, 2, 136}, + {0x29, 2, 136}, + {0x38, 3, 136}, + {0x03, 2, 146}, + {0x06, 2, 146}, + {0x0a, 2, 146}, + {0x0f, 2, 146}, + {0x18, 2, 146}, + {0x1f, 2, 146}, + {0x29, 2, 146}, + {0x38, 3, 146}, }, /* 126 */ { - {0x8001, 154}, - {0xc016, 154}, - {0x8001, 156}, - {0xc016, 156}, - {0x8001, 160}, - {0xc016, 160}, - {0x8001, 163}, - {0xc016, 163}, - {0x8001, 164}, - {0xc016, 164}, - {0x8001, 169}, - {0xc016, 169}, - {0x8001, 170}, - {0xc016, 170}, - {0x8001, 173}, - {0xc016, 173}, + {0x01, 2, 154}, + {0x16, 3, 154}, + {0x01, 2, 156}, + {0x16, 3, 156}, + {0x01, 2, 160}, + {0x16, 3, 160}, + {0x01, 2, 163}, + {0x16, 3, 163}, + {0x01, 2, 164}, + {0x16, 3, 164}, + {0x01, 2, 169}, + {0x16, 3, 169}, + {0x01, 2, 170}, + {0x16, 3, 170}, + {0x01, 2, 173}, + {0x16, 3, 173}, }, /* 127 */ { - {0x8002, 154}, - {0x8009, 154}, - {0x8017, 154}, - {0xc028, 154}, - {0x8002, 156}, - {0x8009, 156}, - {0x8017, 156}, - {0xc028, 156}, - {0x8002, 160}, - {0x8009, 160}, - {0x8017, 160}, - {0xc028, 160}, - {0x8002, 163}, - {0x8009, 163}, - {0x8017, 163}, - {0xc028, 163}, + {0x02, 2, 154}, + {0x09, 2, 154}, + {0x17, 2, 154}, + {0x28, 3, 154}, + {0x02, 2, 156}, + {0x09, 2, 156}, + {0x17, 2, 156}, + {0x28, 3, 156}, + {0x02, 2, 160}, + {0x09, 2, 160}, + {0x17, 2, 160}, + {0x28, 3, 160}, + {0x02, 2, 163}, + {0x09, 2, 163}, + {0x17, 2, 163}, + {0x28, 3, 163}, }, /* 128 */ { - {0x8003, 154}, - {0x8006, 154}, - {0x800a, 154}, - {0x800f, 154}, - {0x8018, 154}, - {0x801f, 154}, - {0x8029, 154}, - {0xc038, 154}, - {0x8003, 156}, - {0x8006, 156}, - {0x800a, 156}, - {0x800f, 156}, - {0x8018, 156}, - {0x801f, 156}, - {0x8029, 156}, - {0xc038, 156}, + {0x03, 2, 154}, + {0x06, 2, 154}, + {0x0a, 2, 154}, + {0x0f, 2, 154}, + {0x18, 2, 154}, + {0x1f, 2, 154}, + {0x29, 2, 154}, + {0x38, 3, 154}, + {0x03, 2, 156}, + {0x06, 2, 156}, + {0x0a, 2, 156}, + {0x0f, 2, 156}, + {0x18, 2, 156}, + {0x1f, 2, 156}, + {0x29, 2, 156}, + {0x38, 3, 156}, }, /* 129 */ { - {0x8003, 160}, - {0x8006, 160}, - {0x800a, 160}, - {0x800f, 160}, - {0x8018, 160}, - {0x801f, 160}, - {0x8029, 160}, - {0xc038, 160}, - {0x8003, 163}, - {0x8006, 163}, - {0x800a, 163}, - {0x800f, 163}, - {0x8018, 163}, - {0x801f, 163}, - {0x8029, 163}, - {0xc038, 163}, + {0x03, 2, 160}, + {0x06, 2, 160}, + {0x0a, 2, 160}, + {0x0f, 2, 160}, + {0x18, 2, 160}, + {0x1f, 2, 160}, + {0x29, 2, 160}, + {0x38, 3, 160}, + {0x03, 2, 163}, + {0x06, 2, 163}, + {0x0a, 2, 163}, + {0x0f, 2, 163}, + {0x18, 2, 163}, + {0x1f, 2, 163}, + {0x29, 2, 163}, + {0x38, 3, 163}, }, /* 130 */ { - {0x8002, 164}, - {0x8009, 164}, - {0x8017, 164}, - {0xc028, 164}, - {0x8002, 169}, - {0x8009, 169}, - {0x8017, 169}, - {0xc028, 169}, - {0x8002, 170}, - {0x8009, 170}, - {0x8017, 170}, - {0xc028, 170}, - {0x8002, 173}, - {0x8009, 173}, - {0x8017, 173}, - {0xc028, 173}, + {0x02, 2, 164}, + {0x09, 2, 164}, + {0x17, 2, 164}, + {0x28, 3, 164}, + {0x02, 2, 169}, + {0x09, 2, 169}, + {0x17, 2, 169}, + {0x28, 3, 169}, + {0x02, 2, 170}, + {0x09, 2, 170}, + {0x17, 2, 170}, + {0x28, 3, 170}, + {0x02, 2, 173}, + {0x09, 2, 173}, + {0x17, 2, 173}, + {0x28, 3, 173}, }, /* 131 */ { - {0x8003, 164}, - {0x8006, 164}, - {0x800a, 164}, - {0x800f, 164}, - {0x8018, 164}, - {0x801f, 164}, - {0x8029, 164}, - {0xc038, 164}, - {0x8003, 169}, - {0x8006, 169}, - {0x800a, 169}, - {0x800f, 169}, - {0x8018, 169}, - {0x801f, 169}, - {0x8029, 169}, - {0xc038, 169}, + {0x03, 2, 164}, + {0x06, 2, 164}, + {0x0a, 2, 164}, + {0x0f, 2, 164}, + {0x18, 2, 164}, + {0x1f, 2, 164}, + {0x29, 2, 164}, + {0x38, 3, 164}, + {0x03, 2, 169}, + {0x06, 2, 169}, + {0x0a, 2, 169}, + {0x0f, 2, 169}, + {0x18, 2, 169}, + {0x1f, 2, 169}, + {0x29, 2, 169}, + {0x38, 3, 169}, }, /* 132 */ { - {0x8003, 170}, - {0x8006, 170}, - {0x800a, 170}, - {0x800f, 170}, - {0x8018, 170}, - {0x801f, 170}, - {0x8029, 170}, - {0xc038, 170}, - {0x8003, 173}, - {0x8006, 173}, - {0x800a, 173}, - {0x800f, 173}, - {0x8018, 173}, - {0x801f, 173}, - {0x8029, 173}, - {0xc038, 173}, + {0x03, 2, 170}, + {0x06, 2, 170}, + {0x0a, 2, 170}, + {0x0f, 2, 170}, + {0x18, 2, 170}, + {0x1f, 2, 170}, + {0x29, 2, 170}, + {0x38, 3, 170}, + {0x03, 2, 173}, + {0x06, 2, 173}, + {0x0a, 2, 173}, + {0x0f, 2, 173}, + {0x18, 2, 173}, + {0x1f, 2, 173}, + {0x29, 2, 173}, + {0x38, 3, 173}, }, /* 133 */ { - {0x89, 0}, - {0x8a, 0}, - {0x8c, 0}, - {0x8d, 0}, - {0x90, 0}, - {0x91, 0}, - {0x93, 0}, - {0x96, 0}, - {0x9c, 0}, - {0x9f, 0}, - {0xa3, 0}, - {0xa6, 0}, - {0xab, 0}, - {0xae, 0}, - {0xb5, 0}, - {0xbe, 0}, + {0x89, 0, 0}, + {0x8a, 0, 0}, + {0x8c, 0, 0}, + {0x8d, 0, 0}, + {0x90, 0, 0}, + {0x91, 0, 0}, + {0x93, 0, 0}, + {0x96, 0, 0}, + {0x9c, 0, 0}, + {0x9f, 0, 0}, + {0xa3, 0, 0}, + {0xa6, 0, 0}, + {0xab, 0, 0}, + {0xae, 0, 0}, + {0xb5, 0, 0}, + {0xbe, 0, 0}, }, /* 134 */ { - {0xc000, 178}, - {0xc000, 181}, - {0xc000, 185}, - {0xc000, 186}, - {0xc000, 187}, - {0xc000, 189}, - {0xc000, 190}, - {0xc000, 196}, - {0xc000, 198}, - {0xc000, 228}, - {0xc000, 232}, - {0xc000, 233}, - {0x94, 0}, - {0x95, 0}, - {0x97, 0}, - {0x98, 0}, + {0x00, 3, 178}, + {0x00, 3, 181}, + {0x00, 3, 185}, + {0x00, 3, 186}, + {0x00, 3, 187}, + {0x00, 3, 189}, + {0x00, 3, 190}, + {0x00, 3, 196}, + {0x00, 3, 198}, + {0x00, 3, 228}, + {0x00, 3, 232}, + {0x00, 3, 233}, + {0x94, 0, 0}, + {0x95, 0, 0}, + {0x97, 0, 0}, + {0x98, 0, 0}, }, /* 135 */ { - {0x8001, 178}, - {0xc016, 178}, - {0x8001, 181}, - {0xc016, 181}, - {0x8001, 185}, - {0xc016, 185}, - {0x8001, 186}, - {0xc016, 186}, - {0x8001, 187}, - {0xc016, 187}, - {0x8001, 189}, - {0xc016, 189}, - {0x8001, 190}, - {0xc016, 190}, - {0x8001, 196}, - {0xc016, 196}, + {0x01, 2, 178}, + {0x16, 3, 178}, + {0x01, 2, 181}, + {0x16, 3, 181}, + {0x01, 2, 185}, + {0x16, 3, 185}, + {0x01, 2, 186}, + {0x16, 3, 186}, + {0x01, 2, 187}, + {0x16, 3, 187}, + {0x01, 2, 189}, + {0x16, 3, 189}, + {0x01, 2, 190}, + {0x16, 3, 190}, + {0x01, 2, 196}, + {0x16, 3, 196}, }, /* 136 */ { - {0x8002, 178}, - {0x8009, 178}, - {0x8017, 178}, - {0xc028, 178}, - {0x8002, 181}, - {0x8009, 181}, - {0x8017, 181}, - {0xc028, 181}, - {0x8002, 185}, - {0x8009, 185}, - {0x8017, 185}, - {0xc028, 185}, - {0x8002, 186}, - {0x8009, 186}, - {0x8017, 186}, - {0xc028, 186}, + {0x02, 2, 178}, + {0x09, 2, 178}, + {0x17, 2, 178}, + {0x28, 3, 178}, + {0x02, 2, 181}, + {0x09, 2, 181}, + {0x17, 2, 181}, + {0x28, 3, 181}, + {0x02, 2, 185}, + {0x09, 2, 185}, + {0x17, 2, 185}, + {0x28, 3, 185}, + {0x02, 2, 186}, + {0x09, 2, 186}, + {0x17, 2, 186}, + {0x28, 3, 186}, }, /* 137 */ { - {0x8003, 178}, - {0x8006, 178}, - {0x800a, 178}, - {0x800f, 178}, - {0x8018, 178}, - {0x801f, 178}, - {0x8029, 178}, - {0xc038, 178}, - {0x8003, 181}, - {0x8006, 181}, - {0x800a, 181}, - {0x800f, 181}, - {0x8018, 181}, - {0x801f, 181}, - {0x8029, 181}, - {0xc038, 181}, + {0x03, 2, 178}, + {0x06, 2, 178}, + {0x0a, 2, 178}, + {0x0f, 2, 178}, + {0x18, 2, 178}, + {0x1f, 2, 178}, + {0x29, 2, 178}, + {0x38, 3, 178}, + {0x03, 2, 181}, + {0x06, 2, 181}, + {0x0a, 2, 181}, + {0x0f, 2, 181}, + {0x18, 2, 181}, + {0x1f, 2, 181}, + {0x29, 2, 181}, + {0x38, 3, 181}, }, /* 138 */ { - {0x8003, 185}, - {0x8006, 185}, - {0x800a, 185}, - {0x800f, 185}, - {0x8018, 185}, - {0x801f, 185}, - {0x8029, 185}, - {0xc038, 185}, - {0x8003, 186}, - {0x8006, 186}, - {0x800a, 186}, - {0x800f, 186}, - {0x8018, 186}, - {0x801f, 186}, - {0x8029, 186}, - {0xc038, 186}, + {0x03, 2, 185}, + {0x06, 2, 185}, + {0x0a, 2, 185}, + {0x0f, 2, 185}, + {0x18, 2, 185}, + {0x1f, 2, 185}, + {0x29, 2, 185}, + {0x38, 3, 185}, + {0x03, 2, 186}, + {0x06, 2, 186}, + {0x0a, 2, 186}, + {0x0f, 2, 186}, + {0x18, 2, 186}, + {0x1f, 2, 186}, + {0x29, 2, 186}, + {0x38, 3, 186}, }, /* 139 */ { - {0x8002, 187}, - {0x8009, 187}, - {0x8017, 187}, - {0xc028, 187}, - {0x8002, 189}, - {0x8009, 189}, - {0x8017, 189}, - {0xc028, 189}, - {0x8002, 190}, - {0x8009, 190}, - {0x8017, 190}, - {0xc028, 190}, - {0x8002, 196}, - {0x8009, 196}, - {0x8017, 196}, - {0xc028, 196}, + {0x02, 2, 187}, + {0x09, 2, 187}, + {0x17, 2, 187}, + {0x28, 3, 187}, + {0x02, 2, 189}, + {0x09, 2, 189}, + {0x17, 2, 189}, + {0x28, 3, 189}, + {0x02, 2, 190}, + {0x09, 2, 190}, + {0x17, 2, 190}, + {0x28, 3, 190}, + {0x02, 2, 196}, + {0x09, 2, 196}, + {0x17, 2, 196}, + {0x28, 3, 196}, }, /* 140 */ { - {0x8003, 187}, - {0x8006, 187}, - {0x800a, 187}, - {0x800f, 187}, - {0x8018, 187}, - {0x801f, 187}, - {0x8029, 187}, - {0xc038, 187}, - {0x8003, 189}, - {0x8006, 189}, - {0x800a, 189}, - {0x800f, 189}, - {0x8018, 189}, - {0x801f, 189}, - {0x8029, 189}, - {0xc038, 189}, + {0x03, 2, 187}, + {0x06, 2, 187}, + {0x0a, 2, 187}, + {0x0f, 2, 187}, + {0x18, 2, 187}, + {0x1f, 2, 187}, + {0x29, 2, 187}, + {0x38, 3, 187}, + {0x03, 2, 189}, + {0x06, 2, 189}, + {0x0a, 2, 189}, + {0x0f, 2, 189}, + {0x18, 2, 189}, + {0x1f, 2, 189}, + {0x29, 2, 189}, + {0x38, 3, 189}, }, /* 141 */ { - {0x8003, 190}, - {0x8006, 190}, - {0x800a, 190}, - {0x800f, 190}, - {0x8018, 190}, - {0x801f, 190}, - {0x8029, 190}, - {0xc038, 190}, - {0x8003, 196}, - {0x8006, 196}, - {0x800a, 196}, - {0x800f, 196}, - {0x8018, 196}, - {0x801f, 196}, - {0x8029, 196}, - {0xc038, 196}, + {0x03, 2, 190}, + {0x06, 2, 190}, + {0x0a, 2, 190}, + {0x0f, 2, 190}, + {0x18, 2, 190}, + {0x1f, 2, 190}, + {0x29, 2, 190}, + {0x38, 3, 190}, + {0x03, 2, 196}, + {0x06, 2, 196}, + {0x0a, 2, 196}, + {0x0f, 2, 196}, + {0x18, 2, 196}, + {0x1f, 2, 196}, + {0x29, 2, 196}, + {0x38, 3, 196}, }, /* 142 */ { - {0x8001, 198}, - {0xc016, 198}, - {0x8001, 228}, - {0xc016, 228}, - {0x8001, 232}, - {0xc016, 232}, - {0x8001, 233}, - {0xc016, 233}, - {0xc000, 1}, - {0xc000, 135}, - {0xc000, 137}, - {0xc000, 138}, - {0xc000, 139}, - {0xc000, 140}, - {0xc000, 141}, - {0xc000, 143}, + {0x01, 2, 198}, + {0x16, 3, 198}, + {0x01, 2, 228}, + {0x16, 3, 228}, + {0x01, 2, 232}, + {0x16, 3, 232}, + {0x01, 2, 233}, + {0x16, 3, 233}, + {0x00, 3, 1}, + {0x00, 3, 135}, + {0x00, 3, 137}, + {0x00, 3, 138}, + {0x00, 3, 139}, + {0x00, 3, 140}, + {0x00, 3, 141}, + {0x00, 3, 143}, }, /* 143 */ { - {0x8002, 198}, - {0x8009, 198}, - {0x8017, 198}, - {0xc028, 198}, - {0x8002, 228}, - {0x8009, 228}, - {0x8017, 228}, - {0xc028, 228}, - {0x8002, 232}, - {0x8009, 232}, - {0x8017, 232}, - {0xc028, 232}, - {0x8002, 233}, - {0x8009, 233}, - {0x8017, 233}, - {0xc028, 233}, + {0x02, 2, 198}, + {0x09, 2, 198}, + {0x17, 2, 198}, + {0x28, 3, 198}, + {0x02, 2, 228}, + {0x09, 2, 228}, + {0x17, 2, 228}, + {0x28, 3, 228}, + {0x02, 2, 232}, + {0x09, 2, 232}, + {0x17, 2, 232}, + {0x28, 3, 232}, + {0x02, 2, 233}, + {0x09, 2, 233}, + {0x17, 2, 233}, + {0x28, 3, 233}, }, /* 144 */ { - {0x8003, 198}, - {0x8006, 198}, - {0x800a, 198}, - {0x800f, 198}, - {0x8018, 198}, - {0x801f, 198}, - {0x8029, 198}, - {0xc038, 198}, - {0x8003, 228}, - {0x8006, 228}, - {0x800a, 228}, - {0x800f, 228}, - {0x8018, 228}, - {0x801f, 228}, - {0x8029, 228}, - {0xc038, 228}, + {0x03, 2, 198}, + {0x06, 2, 198}, + {0x0a, 2, 198}, + {0x0f, 2, 198}, + {0x18, 2, 198}, + {0x1f, 2, 198}, + {0x29, 2, 198}, + {0x38, 3, 198}, + {0x03, 2, 228}, + {0x06, 2, 228}, + {0x0a, 2, 228}, + {0x0f, 2, 228}, + {0x18, 2, 228}, + {0x1f, 2, 228}, + {0x29, 2, 228}, + {0x38, 3, 228}, }, /* 145 */ { - {0x8003, 232}, - {0x8006, 232}, - {0x800a, 232}, - {0x800f, 232}, - {0x8018, 232}, - {0x801f, 232}, - {0x8029, 232}, - {0xc038, 232}, - {0x8003, 233}, - {0x8006, 233}, - {0x800a, 233}, - {0x800f, 233}, - {0x8018, 233}, - {0x801f, 233}, - {0x8029, 233}, - {0xc038, 233}, + {0x03, 2, 232}, + {0x06, 2, 232}, + {0x0a, 2, 232}, + {0x0f, 2, 232}, + {0x18, 2, 232}, + {0x1f, 2, 232}, + {0x29, 2, 232}, + {0x38, 3, 232}, + {0x03, 2, 233}, + {0x06, 2, 233}, + {0x0a, 2, 233}, + {0x0f, 2, 233}, + {0x18, 2, 233}, + {0x1f, 2, 233}, + {0x29, 2, 233}, + {0x38, 3, 233}, }, /* 146 */ { - {0x8001, 1}, - {0xc016, 1}, - {0x8001, 135}, - {0xc016, 135}, - {0x8001, 137}, - {0xc016, 137}, - {0x8001, 138}, - {0xc016, 138}, - {0x8001, 139}, - {0xc016, 139}, - {0x8001, 140}, - {0xc016, 140}, - {0x8001, 141}, - {0xc016, 141}, - {0x8001, 143}, - {0xc016, 143}, + {0x01, 2, 1}, + {0x16, 3, 1}, + {0x01, 2, 135}, + {0x16, 3, 135}, + {0x01, 2, 137}, + {0x16, 3, 137}, + {0x01, 2, 138}, + {0x16, 3, 138}, + {0x01, 2, 139}, + {0x16, 3, 139}, + {0x01, 2, 140}, + {0x16, 3, 140}, + {0x01, 2, 141}, + {0x16, 3, 141}, + {0x01, 2, 143}, + {0x16, 3, 143}, }, /* 147 */ { - {0x8002, 1}, - {0x8009, 1}, - {0x8017, 1}, - {0xc028, 1}, - {0x8002, 135}, - {0x8009, 135}, - {0x8017, 135}, - {0xc028, 135}, - {0x8002, 137}, - {0x8009, 137}, - {0x8017, 137}, - {0xc028, 137}, - {0x8002, 138}, - {0x8009, 138}, - {0x8017, 138}, - {0xc028, 138}, + {0x02, 2, 1}, + {0x09, 2, 1}, + {0x17, 2, 1}, + {0x28, 3, 1}, + {0x02, 2, 135}, + {0x09, 2, 135}, + {0x17, 2, 135}, + {0x28, 3, 135}, + {0x02, 2, 137}, + {0x09, 2, 137}, + {0x17, 2, 137}, + {0x28, 3, 137}, + {0x02, 2, 138}, + {0x09, 2, 138}, + {0x17, 2, 138}, + {0x28, 3, 138}, }, /* 148 */ { - {0x8003, 1}, - {0x8006, 1}, - {0x800a, 1}, - {0x800f, 1}, - {0x8018, 1}, - {0x801f, 1}, - {0x8029, 1}, - {0xc038, 1}, - {0x8003, 135}, - {0x8006, 135}, - {0x800a, 135}, - {0x800f, 135}, - {0x8018, 135}, - {0x801f, 135}, - {0x8029, 135}, - {0xc038, 135}, + {0x03, 2, 1}, + {0x06, 2, 1}, + {0x0a, 2, 1}, + {0x0f, 2, 1}, + {0x18, 2, 1}, + {0x1f, 2, 1}, + {0x29, 2, 1}, + {0x38, 3, 1}, + {0x03, 2, 135}, + {0x06, 2, 135}, + {0x0a, 2, 135}, + {0x0f, 2, 135}, + {0x18, 2, 135}, + {0x1f, 2, 135}, + {0x29, 2, 135}, + {0x38, 3, 135}, }, /* 149 */ { - {0x8003, 137}, - {0x8006, 137}, - {0x800a, 137}, - {0x800f, 137}, - {0x8018, 137}, - {0x801f, 137}, - {0x8029, 137}, - {0xc038, 137}, - {0x8003, 138}, - {0x8006, 138}, - {0x800a, 138}, - {0x800f, 138}, - {0x8018, 138}, - {0x801f, 138}, - {0x8029, 138}, - {0xc038, 138}, + {0x03, 2, 137}, + {0x06, 2, 137}, + {0x0a, 2, 137}, + {0x0f, 2, 137}, + {0x18, 2, 137}, + {0x1f, 2, 137}, + {0x29, 2, 137}, + {0x38, 3, 137}, + {0x03, 2, 138}, + {0x06, 2, 138}, + {0x0a, 2, 138}, + {0x0f, 2, 138}, + {0x18, 2, 138}, + {0x1f, 2, 138}, + {0x29, 2, 138}, + {0x38, 3, 138}, }, /* 150 */ { - {0x8002, 139}, - {0x8009, 139}, - {0x8017, 139}, - {0xc028, 139}, - {0x8002, 140}, - {0x8009, 140}, - {0x8017, 140}, - {0xc028, 140}, - {0x8002, 141}, - {0x8009, 141}, - {0x8017, 141}, - {0xc028, 141}, - {0x8002, 143}, - {0x8009, 143}, - {0x8017, 143}, - {0xc028, 143}, + {0x02, 2, 139}, + {0x09, 2, 139}, + {0x17, 2, 139}, + {0x28, 3, 139}, + {0x02, 2, 140}, + {0x09, 2, 140}, + {0x17, 2, 140}, + {0x28, 3, 140}, + {0x02, 2, 141}, + {0x09, 2, 141}, + {0x17, 2, 141}, + {0x28, 3, 141}, + {0x02, 2, 143}, + {0x09, 2, 143}, + {0x17, 2, 143}, + {0x28, 3, 143}, }, /* 151 */ { - {0x8003, 139}, - {0x8006, 139}, - {0x800a, 139}, - {0x800f, 139}, - {0x8018, 139}, - {0x801f, 139}, - {0x8029, 139}, - {0xc038, 139}, - {0x8003, 140}, - {0x8006, 140}, - {0x800a, 140}, - {0x800f, 140}, - {0x8018, 140}, - {0x801f, 140}, - {0x8029, 140}, - {0xc038, 140}, + {0x03, 2, 139}, + {0x06, 2, 139}, + {0x0a, 2, 139}, + {0x0f, 2, 139}, + {0x18, 2, 139}, + {0x1f, 2, 139}, + {0x29, 2, 139}, + {0x38, 3, 139}, + {0x03, 2, 140}, + {0x06, 2, 140}, + {0x0a, 2, 140}, + {0x0f, 2, 140}, + {0x18, 2, 140}, + {0x1f, 2, 140}, + {0x29, 2, 140}, + {0x38, 3, 140}, }, /* 152 */ { - {0x8003, 141}, - {0x8006, 141}, - {0x800a, 141}, - {0x800f, 141}, - {0x8018, 141}, - {0x801f, 141}, - {0x8029, 141}, - {0xc038, 141}, - {0x8003, 143}, - {0x8006, 143}, - {0x800a, 143}, - {0x800f, 143}, - {0x8018, 143}, - {0x801f, 143}, - {0x8029, 143}, - {0xc038, 143}, + {0x03, 2, 141}, + {0x06, 2, 141}, + {0x0a, 2, 141}, + {0x0f, 2, 141}, + {0x18, 2, 141}, + {0x1f, 2, 141}, + {0x29, 2, 141}, + {0x38, 3, 141}, + {0x03, 2, 143}, + {0x06, 2, 143}, + {0x0a, 2, 143}, + {0x0f, 2, 143}, + {0x18, 2, 143}, + {0x1f, 2, 143}, + {0x29, 2, 143}, + {0x38, 3, 143}, }, /* 153 */ { - {0x9d, 0}, - {0x9e, 0}, - {0xa0, 0}, - {0xa1, 0}, - {0xa4, 0}, - {0xa5, 0}, - {0xa7, 0}, - {0xa8, 0}, - {0xac, 0}, - {0xad, 0}, - {0xaf, 0}, - {0xb1, 0}, - {0xb6, 0}, - {0xb9, 0}, - {0xbf, 0}, - {0xcf, 0}, + {0x9d, 0, 0}, + {0x9e, 0, 0}, + {0xa0, 0, 0}, + {0xa1, 0, 0}, + {0xa4, 0, 0}, + {0xa5, 0, 0}, + {0xa7, 0, 0}, + {0xa8, 0, 0}, + {0xac, 0, 0}, + {0xad, 0, 0}, + {0xaf, 0, 0}, + {0xb1, 0, 0}, + {0xb6, 0, 0}, + {0xb9, 0, 0}, + {0xbf, 0, 0}, + {0xcf, 0, 0}, }, /* 154 */ { - {0xc000, 147}, - {0xc000, 149}, - {0xc000, 150}, - {0xc000, 151}, - {0xc000, 152}, - {0xc000, 155}, - {0xc000, 157}, - {0xc000, 158}, - {0xc000, 165}, - {0xc000, 166}, - {0xc000, 168}, - {0xc000, 174}, - {0xc000, 175}, - {0xc000, 180}, - {0xc000, 182}, - {0xc000, 183}, + {0x00, 3, 147}, + {0x00, 3, 149}, + {0x00, 3, 150}, + {0x00, 3, 151}, + {0x00, 3, 152}, + {0x00, 3, 155}, + {0x00, 3, 157}, + {0x00, 3, 158}, + {0x00, 3, 165}, + {0x00, 3, 166}, + {0x00, 3, 168}, + {0x00, 3, 174}, + {0x00, 3, 175}, + {0x00, 3, 180}, + {0x00, 3, 182}, + {0x00, 3, 183}, }, /* 155 */ { - {0x8001, 147}, - {0xc016, 147}, - {0x8001, 149}, - {0xc016, 149}, - {0x8001, 150}, - {0xc016, 150}, - {0x8001, 151}, - {0xc016, 151}, - {0x8001, 152}, - {0xc016, 152}, - {0x8001, 155}, - {0xc016, 155}, - {0x8001, 157}, - {0xc016, 157}, - {0x8001, 158}, - {0xc016, 158}, + {0x01, 2, 147}, + {0x16, 3, 147}, + {0x01, 2, 149}, + {0x16, 3, 149}, + {0x01, 2, 150}, + {0x16, 3, 150}, + {0x01, 2, 151}, + {0x16, 3, 151}, + {0x01, 2, 152}, + {0x16, 3, 152}, + {0x01, 2, 155}, + {0x16, 3, 155}, + {0x01, 2, 157}, + {0x16, 3, 157}, + {0x01, 2, 158}, + {0x16, 3, 158}, }, /* 156 */ { - {0x8002, 147}, - {0x8009, 147}, - {0x8017, 147}, - {0xc028, 147}, - {0x8002, 149}, - {0x8009, 149}, - {0x8017, 149}, - {0xc028, 149}, - {0x8002, 150}, - {0x8009, 150}, - {0x8017, 150}, - {0xc028, 150}, - {0x8002, 151}, - {0x8009, 151}, - {0x8017, 151}, - {0xc028, 151}, + {0x02, 2, 147}, + {0x09, 2, 147}, + {0x17, 2, 147}, + {0x28, 3, 147}, + {0x02, 2, 149}, + {0x09, 2, 149}, + {0x17, 2, 149}, + {0x28, 3, 149}, + {0x02, 2, 150}, + {0x09, 2, 150}, + {0x17, 2, 150}, + {0x28, 3, 150}, + {0x02, 2, 151}, + {0x09, 2, 151}, + {0x17, 2, 151}, + {0x28, 3, 151}, }, /* 157 */ { - {0x8003, 147}, - {0x8006, 147}, - {0x800a, 147}, - {0x800f, 147}, - {0x8018, 147}, - {0x801f, 147}, - {0x8029, 147}, - {0xc038, 147}, - {0x8003, 149}, - {0x8006, 149}, - {0x800a, 149}, - {0x800f, 149}, - {0x8018, 149}, - {0x801f, 149}, - {0x8029, 149}, - {0xc038, 149}, + {0x03, 2, 147}, + {0x06, 2, 147}, + {0x0a, 2, 147}, + {0x0f, 2, 147}, + {0x18, 2, 147}, + {0x1f, 2, 147}, + {0x29, 2, 147}, + {0x38, 3, 147}, + {0x03, 2, 149}, + {0x06, 2, 149}, + {0x0a, 2, 149}, + {0x0f, 2, 149}, + {0x18, 2, 149}, + {0x1f, 2, 149}, + {0x29, 2, 149}, + {0x38, 3, 149}, }, /* 158 */ { - {0x8003, 150}, - {0x8006, 150}, - {0x800a, 150}, - {0x800f, 150}, - {0x8018, 150}, - {0x801f, 150}, - {0x8029, 150}, - {0xc038, 150}, - {0x8003, 151}, - {0x8006, 151}, - {0x800a, 151}, - {0x800f, 151}, - {0x8018, 151}, - {0x801f, 151}, - {0x8029, 151}, - {0xc038, 151}, + {0x03, 2, 150}, + {0x06, 2, 150}, + {0x0a, 2, 150}, + {0x0f, 2, 150}, + {0x18, 2, 150}, + {0x1f, 2, 150}, + {0x29, 2, 150}, + {0x38, 3, 150}, + {0x03, 2, 151}, + {0x06, 2, 151}, + {0x0a, 2, 151}, + {0x0f, 2, 151}, + {0x18, 2, 151}, + {0x1f, 2, 151}, + {0x29, 2, 151}, + {0x38, 3, 151}, }, /* 159 */ { - {0x8002, 152}, - {0x8009, 152}, - {0x8017, 152}, - {0xc028, 152}, - {0x8002, 155}, - {0x8009, 155}, - {0x8017, 155}, - {0xc028, 155}, - {0x8002, 157}, - {0x8009, 157}, - {0x8017, 157}, - {0xc028, 157}, - {0x8002, 158}, - {0x8009, 158}, - {0x8017, 158}, - {0xc028, 158}, + {0x02, 2, 152}, + {0x09, 2, 152}, + {0x17, 2, 152}, + {0x28, 3, 152}, + {0x02, 2, 155}, + {0x09, 2, 155}, + {0x17, 2, 155}, + {0x28, 3, 155}, + {0x02, 2, 157}, + {0x09, 2, 157}, + {0x17, 2, 157}, + {0x28, 3, 157}, + {0x02, 2, 158}, + {0x09, 2, 158}, + {0x17, 2, 158}, + {0x28, 3, 158}, }, /* 160 */ { - {0x8003, 152}, - {0x8006, 152}, - {0x800a, 152}, - {0x800f, 152}, - {0x8018, 152}, - {0x801f, 152}, - {0x8029, 152}, - {0xc038, 152}, - {0x8003, 155}, - {0x8006, 155}, - {0x800a, 155}, - {0x800f, 155}, - {0x8018, 155}, - {0x801f, 155}, - {0x8029, 155}, - {0xc038, 155}, + {0x03, 2, 152}, + {0x06, 2, 152}, + {0x0a, 2, 152}, + {0x0f, 2, 152}, + {0x18, 2, 152}, + {0x1f, 2, 152}, + {0x29, 2, 152}, + {0x38, 3, 152}, + {0x03, 2, 155}, + {0x06, 2, 155}, + {0x0a, 2, 155}, + {0x0f, 2, 155}, + {0x18, 2, 155}, + {0x1f, 2, 155}, + {0x29, 2, 155}, + {0x38, 3, 155}, }, /* 161 */ { - {0x8003, 157}, - {0x8006, 157}, - {0x800a, 157}, - {0x800f, 157}, - {0x8018, 157}, - {0x801f, 157}, - {0x8029, 157}, - {0xc038, 157}, - {0x8003, 158}, - {0x8006, 158}, - {0x800a, 158}, - {0x800f, 158}, - {0x8018, 158}, - {0x801f, 158}, - {0x8029, 158}, - {0xc038, 158}, + {0x03, 2, 157}, + {0x06, 2, 157}, + {0x0a, 2, 157}, + {0x0f, 2, 157}, + {0x18, 2, 157}, + {0x1f, 2, 157}, + {0x29, 2, 157}, + {0x38, 3, 157}, + {0x03, 2, 158}, + {0x06, 2, 158}, + {0x0a, 2, 158}, + {0x0f, 2, 158}, + {0x18, 2, 158}, + {0x1f, 2, 158}, + {0x29, 2, 158}, + {0x38, 3, 158}, }, /* 162 */ { - {0x8001, 165}, - {0xc016, 165}, - {0x8001, 166}, - {0xc016, 166}, - {0x8001, 168}, - {0xc016, 168}, - {0x8001, 174}, - {0xc016, 174}, - {0x8001, 175}, - {0xc016, 175}, - {0x8001, 180}, - {0xc016, 180}, - {0x8001, 182}, - {0xc016, 182}, - {0x8001, 183}, - {0xc016, 183}, + {0x01, 2, 165}, + {0x16, 3, 165}, + {0x01, 2, 166}, + {0x16, 3, 166}, + {0x01, 2, 168}, + {0x16, 3, 168}, + {0x01, 2, 174}, + {0x16, 3, 174}, + {0x01, 2, 175}, + {0x16, 3, 175}, + {0x01, 2, 180}, + {0x16, 3, 180}, + {0x01, 2, 182}, + {0x16, 3, 182}, + {0x01, 2, 183}, + {0x16, 3, 183}, }, /* 163 */ { - {0x8002, 165}, - {0x8009, 165}, - {0x8017, 165}, - {0xc028, 165}, - {0x8002, 166}, - {0x8009, 166}, - {0x8017, 166}, - {0xc028, 166}, - {0x8002, 168}, - {0x8009, 168}, - {0x8017, 168}, - {0xc028, 168}, - {0x8002, 174}, - {0x8009, 174}, - {0x8017, 174}, - {0xc028, 174}, + {0x02, 2, 165}, + {0x09, 2, 165}, + {0x17, 2, 165}, + {0x28, 3, 165}, + {0x02, 2, 166}, + {0x09, 2, 166}, + {0x17, 2, 166}, + {0x28, 3, 166}, + {0x02, 2, 168}, + {0x09, 2, 168}, + {0x17, 2, 168}, + {0x28, 3, 168}, + {0x02, 2, 174}, + {0x09, 2, 174}, + {0x17, 2, 174}, + {0x28, 3, 174}, }, /* 164 */ { - {0x8003, 165}, - {0x8006, 165}, - {0x800a, 165}, - {0x800f, 165}, - {0x8018, 165}, - {0x801f, 165}, - {0x8029, 165}, - {0xc038, 165}, - {0x8003, 166}, - {0x8006, 166}, - {0x800a, 166}, - {0x800f, 166}, - {0x8018, 166}, - {0x801f, 166}, - {0x8029, 166}, - {0xc038, 166}, + {0x03, 2, 165}, + {0x06, 2, 165}, + {0x0a, 2, 165}, + {0x0f, 2, 165}, + {0x18, 2, 165}, + {0x1f, 2, 165}, + {0x29, 2, 165}, + {0x38, 3, 165}, + {0x03, 2, 166}, + {0x06, 2, 166}, + {0x0a, 2, 166}, + {0x0f, 2, 166}, + {0x18, 2, 166}, + {0x1f, 2, 166}, + {0x29, 2, 166}, + {0x38, 3, 166}, }, /* 165 */ { - {0x8003, 168}, - {0x8006, 168}, - {0x800a, 168}, - {0x800f, 168}, - {0x8018, 168}, - {0x801f, 168}, - {0x8029, 168}, - {0xc038, 168}, - {0x8003, 174}, - {0x8006, 174}, - {0x800a, 174}, - {0x800f, 174}, - {0x8018, 174}, - {0x801f, 174}, - {0x8029, 174}, - {0xc038, 174}, + {0x03, 2, 168}, + {0x06, 2, 168}, + {0x0a, 2, 168}, + {0x0f, 2, 168}, + {0x18, 2, 168}, + {0x1f, 2, 168}, + {0x29, 2, 168}, + {0x38, 3, 168}, + {0x03, 2, 174}, + {0x06, 2, 174}, + {0x0a, 2, 174}, + {0x0f, 2, 174}, + {0x18, 2, 174}, + {0x1f, 2, 174}, + {0x29, 2, 174}, + {0x38, 3, 174}, }, /* 166 */ { - {0x8002, 175}, - {0x8009, 175}, - {0x8017, 175}, - {0xc028, 175}, - {0x8002, 180}, - {0x8009, 180}, - {0x8017, 180}, - {0xc028, 180}, - {0x8002, 182}, - {0x8009, 182}, - {0x8017, 182}, - {0xc028, 182}, - {0x8002, 183}, - {0x8009, 183}, - {0x8017, 183}, - {0xc028, 183}, + {0x02, 2, 175}, + {0x09, 2, 175}, + {0x17, 2, 175}, + {0x28, 3, 175}, + {0x02, 2, 180}, + {0x09, 2, 180}, + {0x17, 2, 180}, + {0x28, 3, 180}, + {0x02, 2, 182}, + {0x09, 2, 182}, + {0x17, 2, 182}, + {0x28, 3, 182}, + {0x02, 2, 183}, + {0x09, 2, 183}, + {0x17, 2, 183}, + {0x28, 3, 183}, }, /* 167 */ { - {0x8003, 175}, - {0x8006, 175}, - {0x800a, 175}, - {0x800f, 175}, - {0x8018, 175}, - {0x801f, 175}, - {0x8029, 175}, - {0xc038, 175}, - {0x8003, 180}, - {0x8006, 180}, - {0x800a, 180}, - {0x800f, 180}, - {0x8018, 180}, - {0x801f, 180}, - {0x8029, 180}, - {0xc038, 180}, + {0x03, 2, 175}, + {0x06, 2, 175}, + {0x0a, 2, 175}, + {0x0f, 2, 175}, + {0x18, 2, 175}, + {0x1f, 2, 175}, + {0x29, 2, 175}, + {0x38, 3, 175}, + {0x03, 2, 180}, + {0x06, 2, 180}, + {0x0a, 2, 180}, + {0x0f, 2, 180}, + {0x18, 2, 180}, + {0x1f, 2, 180}, + {0x29, 2, 180}, + {0x38, 3, 180}, }, /* 168 */ { - {0x8003, 182}, - {0x8006, 182}, - {0x800a, 182}, - {0x800f, 182}, - {0x8018, 182}, - {0x801f, 182}, - {0x8029, 182}, - {0xc038, 182}, - {0x8003, 183}, - {0x8006, 183}, - {0x800a, 183}, - {0x800f, 183}, - {0x8018, 183}, - {0x801f, 183}, - {0x8029, 183}, - {0xc038, 183}, + {0x03, 2, 182}, + {0x06, 2, 182}, + {0x0a, 2, 182}, + {0x0f, 2, 182}, + {0x18, 2, 182}, + {0x1f, 2, 182}, + {0x29, 2, 182}, + {0x38, 3, 182}, + {0x03, 2, 183}, + {0x06, 2, 183}, + {0x0a, 2, 183}, + {0x0f, 2, 183}, + {0x18, 2, 183}, + {0x1f, 2, 183}, + {0x29, 2, 183}, + {0x38, 3, 183}, }, /* 169 */ { - {0xc000, 188}, - {0xc000, 191}, - {0xc000, 197}, - {0xc000, 231}, - {0xc000, 239}, - {0xb0, 0}, - {0xb2, 0}, - {0xb3, 0}, - {0xb7, 0}, - {0xb8, 0}, - {0xba, 0}, - {0xbb, 0}, - {0xc0, 0}, - {0xc7, 0}, - {0xd0, 0}, - {0xdf, 0}, + {0x00, 3, 188}, + {0x00, 3, 191}, + {0x00, 3, 197}, + {0x00, 3, 231}, + {0x00, 3, 239}, + {0xb0, 0, 0}, + {0xb2, 0, 0}, + {0xb3, 0, 0}, + {0xb7, 0, 0}, + {0xb8, 0, 0}, + {0xba, 0, 0}, + {0xbb, 0, 0}, + {0xc0, 0, 0}, + {0xc7, 0, 0}, + {0xd0, 0, 0}, + {0xdf, 0, 0}, }, /* 170 */ { - {0x8001, 188}, - {0xc016, 188}, - {0x8001, 191}, - {0xc016, 191}, - {0x8001, 197}, - {0xc016, 197}, - {0x8001, 231}, - {0xc016, 231}, - {0x8001, 239}, - {0xc016, 239}, - {0xc000, 9}, - {0xc000, 142}, - {0xc000, 144}, - {0xc000, 145}, - {0xc000, 148}, - {0xc000, 159}, + {0x01, 2, 188}, + {0x16, 3, 188}, + {0x01, 2, 191}, + {0x16, 3, 191}, + {0x01, 2, 197}, + {0x16, 3, 197}, + {0x01, 2, 231}, + {0x16, 3, 231}, + {0x01, 2, 239}, + {0x16, 3, 239}, + {0x00, 3, 9}, + {0x00, 3, 142}, + {0x00, 3, 144}, + {0x00, 3, 145}, + {0x00, 3, 148}, + {0x00, 3, 159}, }, /* 171 */ { - {0x8002, 188}, - {0x8009, 188}, - {0x8017, 188}, - {0xc028, 188}, - {0x8002, 191}, - {0x8009, 191}, - {0x8017, 191}, - {0xc028, 191}, - {0x8002, 197}, - {0x8009, 197}, - {0x8017, 197}, - {0xc028, 197}, - {0x8002, 231}, - {0x8009, 231}, - {0x8017, 231}, - {0xc028, 231}, + {0x02, 2, 188}, + {0x09, 2, 188}, + {0x17, 2, 188}, + {0x28, 3, 188}, + {0x02, 2, 191}, + {0x09, 2, 191}, + {0x17, 2, 191}, + {0x28, 3, 191}, + {0x02, 2, 197}, + {0x09, 2, 197}, + {0x17, 2, 197}, + {0x28, 3, 197}, + {0x02, 2, 231}, + {0x09, 2, 231}, + {0x17, 2, 231}, + {0x28, 3, 231}, }, /* 172 */ { - {0x8003, 188}, - {0x8006, 188}, - {0x800a, 188}, - {0x800f, 188}, - {0x8018, 188}, - {0x801f, 188}, - {0x8029, 188}, - {0xc038, 188}, - {0x8003, 191}, - {0x8006, 191}, - {0x800a, 191}, - {0x800f, 191}, - {0x8018, 191}, - {0x801f, 191}, - {0x8029, 191}, - {0xc038, 191}, + {0x03, 2, 188}, + {0x06, 2, 188}, + {0x0a, 2, 188}, + {0x0f, 2, 188}, + {0x18, 2, 188}, + {0x1f, 2, 188}, + {0x29, 2, 188}, + {0x38, 3, 188}, + {0x03, 2, 191}, + {0x06, 2, 191}, + {0x0a, 2, 191}, + {0x0f, 2, 191}, + {0x18, 2, 191}, + {0x1f, 2, 191}, + {0x29, 2, 191}, + {0x38, 3, 191}, }, /* 173 */ { - {0x8003, 197}, - {0x8006, 197}, - {0x800a, 197}, - {0x800f, 197}, - {0x8018, 197}, - {0x801f, 197}, - {0x8029, 197}, - {0xc038, 197}, - {0x8003, 231}, - {0x8006, 231}, - {0x800a, 231}, - {0x800f, 231}, - {0x8018, 231}, - {0x801f, 231}, - {0x8029, 231}, - {0xc038, 231}, + {0x03, 2, 197}, + {0x06, 2, 197}, + {0x0a, 2, 197}, + {0x0f, 2, 197}, + {0x18, 2, 197}, + {0x1f, 2, 197}, + {0x29, 2, 197}, + {0x38, 3, 197}, + {0x03, 2, 231}, + {0x06, 2, 231}, + {0x0a, 2, 231}, + {0x0f, 2, 231}, + {0x18, 2, 231}, + {0x1f, 2, 231}, + {0x29, 2, 231}, + {0x38, 3, 231}, }, /* 174 */ { - {0x8002, 239}, - {0x8009, 239}, - {0x8017, 239}, - {0xc028, 239}, - {0x8001, 9}, - {0xc016, 9}, - {0x8001, 142}, - {0xc016, 142}, - {0x8001, 144}, - {0xc016, 144}, - {0x8001, 145}, - {0xc016, 145}, - {0x8001, 148}, - {0xc016, 148}, - {0x8001, 159}, - {0xc016, 159}, + {0x02, 2, 239}, + {0x09, 2, 239}, + {0x17, 2, 239}, + {0x28, 3, 239}, + {0x01, 2, 9}, + {0x16, 3, 9}, + {0x01, 2, 142}, + {0x16, 3, 142}, + {0x01, 2, 144}, + {0x16, 3, 144}, + {0x01, 2, 145}, + {0x16, 3, 145}, + {0x01, 2, 148}, + {0x16, 3, 148}, + {0x01, 2, 159}, + {0x16, 3, 159}, }, /* 175 */ { - {0x8003, 239}, - {0x8006, 239}, - {0x800a, 239}, - {0x800f, 239}, - {0x8018, 239}, - {0x801f, 239}, - {0x8029, 239}, - {0xc038, 239}, - {0x8002, 9}, - {0x8009, 9}, - {0x8017, 9}, - {0xc028, 9}, - {0x8002, 142}, - {0x8009, 142}, - {0x8017, 142}, - {0xc028, 142}, + {0x03, 2, 239}, + {0x06, 2, 239}, + {0x0a, 2, 239}, + {0x0f, 2, 239}, + {0x18, 2, 239}, + {0x1f, 2, 239}, + {0x29, 2, 239}, + {0x38, 3, 239}, + {0x02, 2, 9}, + {0x09, 2, 9}, + {0x17, 2, 9}, + {0x28, 3, 9}, + {0x02, 2, 142}, + {0x09, 2, 142}, + {0x17, 2, 142}, + {0x28, 3, 142}, }, /* 176 */ { - {0x8003, 9}, - {0x8006, 9}, - {0x800a, 9}, - {0x800f, 9}, - {0x8018, 9}, - {0x801f, 9}, - {0x8029, 9}, - {0xc038, 9}, - {0x8003, 142}, - {0x8006, 142}, - {0x800a, 142}, - {0x800f, 142}, - {0x8018, 142}, - {0x801f, 142}, - {0x8029, 142}, - {0xc038, 142}, + {0x03, 2, 9}, + {0x06, 2, 9}, + {0x0a, 2, 9}, + {0x0f, 2, 9}, + {0x18, 2, 9}, + {0x1f, 2, 9}, + {0x29, 2, 9}, + {0x38, 3, 9}, + {0x03, 2, 142}, + {0x06, 2, 142}, + {0x0a, 2, 142}, + {0x0f, 2, 142}, + {0x18, 2, 142}, + {0x1f, 2, 142}, + {0x29, 2, 142}, + {0x38, 3, 142}, }, /* 177 */ { - {0x8002, 144}, - {0x8009, 144}, - {0x8017, 144}, - {0xc028, 144}, - {0x8002, 145}, - {0x8009, 145}, - {0x8017, 145}, - {0xc028, 145}, - {0x8002, 148}, - {0x8009, 148}, - {0x8017, 148}, - {0xc028, 148}, - {0x8002, 159}, - {0x8009, 159}, - {0x8017, 159}, - {0xc028, 159}, + {0x02, 2, 144}, + {0x09, 2, 144}, + {0x17, 2, 144}, + {0x28, 3, 144}, + {0x02, 2, 145}, + {0x09, 2, 145}, + {0x17, 2, 145}, + {0x28, 3, 145}, + {0x02, 2, 148}, + {0x09, 2, 148}, + {0x17, 2, 148}, + {0x28, 3, 148}, + {0x02, 2, 159}, + {0x09, 2, 159}, + {0x17, 2, 159}, + {0x28, 3, 159}, }, /* 178 */ { - {0x8003, 144}, - {0x8006, 144}, - {0x800a, 144}, - {0x800f, 144}, - {0x8018, 144}, - {0x801f, 144}, - {0x8029, 144}, - {0xc038, 144}, - {0x8003, 145}, - {0x8006, 145}, - {0x800a, 145}, - {0x800f, 145}, - {0x8018, 145}, - {0x801f, 145}, - {0x8029, 145}, - {0xc038, 145}, + {0x03, 2, 144}, + {0x06, 2, 144}, + {0x0a, 2, 144}, + {0x0f, 2, 144}, + {0x18, 2, 144}, + {0x1f, 2, 144}, + {0x29, 2, 144}, + {0x38, 3, 144}, + {0x03, 2, 145}, + {0x06, 2, 145}, + {0x0a, 2, 145}, + {0x0f, 2, 145}, + {0x18, 2, 145}, + {0x1f, 2, 145}, + {0x29, 2, 145}, + {0x38, 3, 145}, }, /* 179 */ { - {0x8003, 148}, - {0x8006, 148}, - {0x800a, 148}, - {0x800f, 148}, - {0x8018, 148}, - {0x801f, 148}, - {0x8029, 148}, - {0xc038, 148}, - {0x8003, 159}, - {0x8006, 159}, - {0x800a, 159}, - {0x800f, 159}, - {0x8018, 159}, - {0x801f, 159}, - {0x8029, 159}, - {0xc038, 159}, + {0x03, 2, 148}, + {0x06, 2, 148}, + {0x0a, 2, 148}, + {0x0f, 2, 148}, + {0x18, 2, 148}, + {0x1f, 2, 148}, + {0x29, 2, 148}, + {0x38, 3, 148}, + {0x03, 2, 159}, + {0x06, 2, 159}, + {0x0a, 2, 159}, + {0x0f, 2, 159}, + {0x18, 2, 159}, + {0x1f, 2, 159}, + {0x29, 2, 159}, + {0x38, 3, 159}, }, /* 180 */ { - {0xc000, 171}, - {0xc000, 206}, - {0xc000, 215}, - {0xc000, 225}, - {0xc000, 236}, - {0xc000, 237}, - {0xbc, 0}, - {0xbd, 0}, - {0xc1, 0}, - {0xc4, 0}, - {0xc8, 0}, - {0xcb, 0}, - {0xd1, 0}, - {0xd8, 0}, - {0xe0, 0}, - {0xee, 0}, + {0x00, 3, 171}, + {0x00, 3, 206}, + {0x00, 3, 215}, + {0x00, 3, 225}, + {0x00, 3, 236}, + {0x00, 3, 237}, + {0xbc, 0, 0}, + {0xbd, 0, 0}, + {0xc1, 0, 0}, + {0xc4, 0, 0}, + {0xc8, 0, 0}, + {0xcb, 0, 0}, + {0xd1, 0, 0}, + {0xd8, 0, 0}, + {0xe0, 0, 0}, + {0xee, 0, 0}, }, /* 181 */ { - {0x8001, 171}, - {0xc016, 171}, - {0x8001, 206}, - {0xc016, 206}, - {0x8001, 215}, - {0xc016, 215}, - {0x8001, 225}, - {0xc016, 225}, - {0x8001, 236}, - {0xc016, 236}, - {0x8001, 237}, - {0xc016, 237}, - {0xc000, 199}, - {0xc000, 207}, - {0xc000, 234}, - {0xc000, 235}, + {0x01, 2, 171}, + {0x16, 3, 171}, + {0x01, 2, 206}, + {0x16, 3, 206}, + {0x01, 2, 215}, + {0x16, 3, 215}, + {0x01, 2, 225}, + {0x16, 3, 225}, + {0x01, 2, 236}, + {0x16, 3, 236}, + {0x01, 2, 237}, + {0x16, 3, 237}, + {0x00, 3, 199}, + {0x00, 3, 207}, + {0x00, 3, 234}, + {0x00, 3, 235}, }, /* 182 */ { - {0x8002, 171}, - {0x8009, 171}, - {0x8017, 171}, - {0xc028, 171}, - {0x8002, 206}, - {0x8009, 206}, - {0x8017, 206}, - {0xc028, 206}, - {0x8002, 215}, - {0x8009, 215}, - {0x8017, 215}, - {0xc028, 215}, - {0x8002, 225}, - {0x8009, 225}, - {0x8017, 225}, - {0xc028, 225}, + {0x02, 2, 171}, + {0x09, 2, 171}, + {0x17, 2, 171}, + {0x28, 3, 171}, + {0x02, 2, 206}, + {0x09, 2, 206}, + {0x17, 2, 206}, + {0x28, 3, 206}, + {0x02, 2, 215}, + {0x09, 2, 215}, + {0x17, 2, 215}, + {0x28, 3, 215}, + {0x02, 2, 225}, + {0x09, 2, 225}, + {0x17, 2, 225}, + {0x28, 3, 225}, }, /* 183 */ { - {0x8003, 171}, - {0x8006, 171}, - {0x800a, 171}, - {0x800f, 171}, - {0x8018, 171}, - {0x801f, 171}, - {0x8029, 171}, - {0xc038, 171}, - {0x8003, 206}, - {0x8006, 206}, - {0x800a, 206}, - {0x800f, 206}, - {0x8018, 206}, - {0x801f, 206}, - {0x8029, 206}, - {0xc038, 206}, + {0x03, 2, 171}, + {0x06, 2, 171}, + {0x0a, 2, 171}, + {0x0f, 2, 171}, + {0x18, 2, 171}, + {0x1f, 2, 171}, + {0x29, 2, 171}, + {0x38, 3, 171}, + {0x03, 2, 206}, + {0x06, 2, 206}, + {0x0a, 2, 206}, + {0x0f, 2, 206}, + {0x18, 2, 206}, + {0x1f, 2, 206}, + {0x29, 2, 206}, + {0x38, 3, 206}, }, /* 184 */ { - {0x8003, 215}, - {0x8006, 215}, - {0x800a, 215}, - {0x800f, 215}, - {0x8018, 215}, - {0x801f, 215}, - {0x8029, 215}, - {0xc038, 215}, - {0x8003, 225}, - {0x8006, 225}, - {0x800a, 225}, - {0x800f, 225}, - {0x8018, 225}, - {0x801f, 225}, - {0x8029, 225}, - {0xc038, 225}, + {0x03, 2, 215}, + {0x06, 2, 215}, + {0x0a, 2, 215}, + {0x0f, 2, 215}, + {0x18, 2, 215}, + {0x1f, 2, 215}, + {0x29, 2, 215}, + {0x38, 3, 215}, + {0x03, 2, 225}, + {0x06, 2, 225}, + {0x0a, 2, 225}, + {0x0f, 2, 225}, + {0x18, 2, 225}, + {0x1f, 2, 225}, + {0x29, 2, 225}, + {0x38, 3, 225}, }, /* 185 */ { - {0x8002, 236}, - {0x8009, 236}, - {0x8017, 236}, - {0xc028, 236}, - {0x8002, 237}, - {0x8009, 237}, - {0x8017, 237}, - {0xc028, 237}, - {0x8001, 199}, - {0xc016, 199}, - {0x8001, 207}, - {0xc016, 207}, - {0x8001, 234}, - {0xc016, 234}, - {0x8001, 235}, - {0xc016, 235}, + {0x02, 2, 236}, + {0x09, 2, 236}, + {0x17, 2, 236}, + {0x28, 3, 236}, + {0x02, 2, 237}, + {0x09, 2, 237}, + {0x17, 2, 237}, + {0x28, 3, 237}, + {0x01, 2, 199}, + {0x16, 3, 199}, + {0x01, 2, 207}, + {0x16, 3, 207}, + {0x01, 2, 234}, + {0x16, 3, 234}, + {0x01, 2, 235}, + {0x16, 3, 235}, }, /* 186 */ { - {0x8003, 236}, - {0x8006, 236}, - {0x800a, 236}, - {0x800f, 236}, - {0x8018, 236}, - {0x801f, 236}, - {0x8029, 236}, - {0xc038, 236}, - {0x8003, 237}, - {0x8006, 237}, - {0x800a, 237}, - {0x800f, 237}, - {0x8018, 237}, - {0x801f, 237}, - {0x8029, 237}, - {0xc038, 237}, + {0x03, 2, 236}, + {0x06, 2, 236}, + {0x0a, 2, 236}, + {0x0f, 2, 236}, + {0x18, 2, 236}, + {0x1f, 2, 236}, + {0x29, 2, 236}, + {0x38, 3, 236}, + {0x03, 2, 237}, + {0x06, 2, 237}, + {0x0a, 2, 237}, + {0x0f, 2, 237}, + {0x18, 2, 237}, + {0x1f, 2, 237}, + {0x29, 2, 237}, + {0x38, 3, 237}, }, /* 187 */ { - {0x8002, 199}, - {0x8009, 199}, - {0x8017, 199}, - {0xc028, 199}, - {0x8002, 207}, - {0x8009, 207}, - {0x8017, 207}, - {0xc028, 207}, - {0x8002, 234}, - {0x8009, 234}, - {0x8017, 234}, - {0xc028, 234}, - {0x8002, 235}, - {0x8009, 235}, - {0x8017, 235}, - {0xc028, 235}, + {0x02, 2, 199}, + {0x09, 2, 199}, + {0x17, 2, 199}, + {0x28, 3, 199}, + {0x02, 2, 207}, + {0x09, 2, 207}, + {0x17, 2, 207}, + {0x28, 3, 207}, + {0x02, 2, 234}, + {0x09, 2, 234}, + {0x17, 2, 234}, + {0x28, 3, 234}, + {0x02, 2, 235}, + {0x09, 2, 235}, + {0x17, 2, 235}, + {0x28, 3, 235}, }, /* 188 */ { - {0x8003, 199}, - {0x8006, 199}, - {0x800a, 199}, - {0x800f, 199}, - {0x8018, 199}, - {0x801f, 199}, - {0x8029, 199}, - {0xc038, 199}, - {0x8003, 207}, - {0x8006, 207}, - {0x800a, 207}, - {0x800f, 207}, - {0x8018, 207}, - {0x801f, 207}, - {0x8029, 207}, - {0xc038, 207}, + {0x03, 2, 199}, + {0x06, 2, 199}, + {0x0a, 2, 199}, + {0x0f, 2, 199}, + {0x18, 2, 199}, + {0x1f, 2, 199}, + {0x29, 2, 199}, + {0x38, 3, 199}, + {0x03, 2, 207}, + {0x06, 2, 207}, + {0x0a, 2, 207}, + {0x0f, 2, 207}, + {0x18, 2, 207}, + {0x1f, 2, 207}, + {0x29, 2, 207}, + {0x38, 3, 207}, }, /* 189 */ { - {0x8003, 234}, - {0x8006, 234}, - {0x800a, 234}, - {0x800f, 234}, - {0x8018, 234}, - {0x801f, 234}, - {0x8029, 234}, - {0xc038, 234}, - {0x8003, 235}, - {0x8006, 235}, - {0x800a, 235}, - {0x800f, 235}, - {0x8018, 235}, - {0x801f, 235}, - {0x8029, 235}, - {0xc038, 235}, + {0x03, 2, 234}, + {0x06, 2, 234}, + {0x0a, 2, 234}, + {0x0f, 2, 234}, + {0x18, 2, 234}, + {0x1f, 2, 234}, + {0x29, 2, 234}, + {0x38, 3, 234}, + {0x03, 2, 235}, + {0x06, 2, 235}, + {0x0a, 2, 235}, + {0x0f, 2, 235}, + {0x18, 2, 235}, + {0x1f, 2, 235}, + {0x29, 2, 235}, + {0x38, 3, 235}, }, /* 190 */ { - {0xc2, 0}, - {0xc3, 0}, - {0xc5, 0}, - {0xc6, 0}, - {0xc9, 0}, - {0xca, 0}, - {0xcc, 0}, - {0xcd, 0}, - {0xd2, 0}, - {0xd5, 0}, - {0xd9, 0}, - {0xdc, 0}, - {0xe1, 0}, - {0xe7, 0}, - {0xef, 0}, - {0xf6, 0}, + {0xc2, 0, 0}, + {0xc3, 0, 0}, + {0xc5, 0, 0}, + {0xc6, 0, 0}, + {0xc9, 0, 0}, + {0xca, 0, 0}, + {0xcc, 0, 0}, + {0xcd, 0, 0}, + {0xd2, 0, 0}, + {0xd5, 0, 0}, + {0xd9, 0, 0}, + {0xdc, 0, 0}, + {0xe1, 0, 0}, + {0xe7, 0, 0}, + {0xef, 0, 0}, + {0xf6, 0, 0}, }, /* 191 */ { - {0xc000, 192}, - {0xc000, 193}, - {0xc000, 200}, - {0xc000, 201}, - {0xc000, 202}, - {0xc000, 205}, - {0xc000, 210}, - {0xc000, 213}, - {0xc000, 218}, - {0xc000, 219}, - {0xc000, 238}, - {0xc000, 240}, - {0xc000, 242}, - {0xc000, 243}, - {0xc000, 255}, - {0xce, 0}, + {0x00, 3, 192}, + {0x00, 3, 193}, + {0x00, 3, 200}, + {0x00, 3, 201}, + {0x00, 3, 202}, + {0x00, 3, 205}, + {0x00, 3, 210}, + {0x00, 3, 213}, + {0x00, 3, 218}, + {0x00, 3, 219}, + {0x00, 3, 238}, + {0x00, 3, 240}, + {0x00, 3, 242}, + {0x00, 3, 243}, + {0x00, 3, 255}, + {0xce, 0, 0}, }, /* 192 */ { - {0x8001, 192}, - {0xc016, 192}, - {0x8001, 193}, - {0xc016, 193}, - {0x8001, 200}, - {0xc016, 200}, - {0x8001, 201}, - {0xc016, 201}, - {0x8001, 202}, - {0xc016, 202}, - {0x8001, 205}, - {0xc016, 205}, - {0x8001, 210}, - {0xc016, 210}, - {0x8001, 213}, - {0xc016, 213}, + {0x01, 2, 192}, + {0x16, 3, 192}, + {0x01, 2, 193}, + {0x16, 3, 193}, + {0x01, 2, 200}, + {0x16, 3, 200}, + {0x01, 2, 201}, + {0x16, 3, 201}, + {0x01, 2, 202}, + {0x16, 3, 202}, + {0x01, 2, 205}, + {0x16, 3, 205}, + {0x01, 2, 210}, + {0x16, 3, 210}, + {0x01, 2, 213}, + {0x16, 3, 213}, }, /* 193 */ { - {0x8002, 192}, - {0x8009, 192}, - {0x8017, 192}, - {0xc028, 192}, - {0x8002, 193}, - {0x8009, 193}, - {0x8017, 193}, - {0xc028, 193}, - {0x8002, 200}, - {0x8009, 200}, - {0x8017, 200}, - {0xc028, 200}, - {0x8002, 201}, - {0x8009, 201}, - {0x8017, 201}, - {0xc028, 201}, + {0x02, 2, 192}, + {0x09, 2, 192}, + {0x17, 2, 192}, + {0x28, 3, 192}, + {0x02, 2, 193}, + {0x09, 2, 193}, + {0x17, 2, 193}, + {0x28, 3, 193}, + {0x02, 2, 200}, + {0x09, 2, 200}, + {0x17, 2, 200}, + {0x28, 3, 200}, + {0x02, 2, 201}, + {0x09, 2, 201}, + {0x17, 2, 201}, + {0x28, 3, 201}, }, /* 194 */ { - {0x8003, 192}, - {0x8006, 192}, - {0x800a, 192}, - {0x800f, 192}, - {0x8018, 192}, - {0x801f, 192}, - {0x8029, 192}, - {0xc038, 192}, - {0x8003, 193}, - {0x8006, 193}, - {0x800a, 193}, - {0x800f, 193}, - {0x8018, 193}, - {0x801f, 193}, - {0x8029, 193}, - {0xc038, 193}, + {0x03, 2, 192}, + {0x06, 2, 192}, + {0x0a, 2, 192}, + {0x0f, 2, 192}, + {0x18, 2, 192}, + {0x1f, 2, 192}, + {0x29, 2, 192}, + {0x38, 3, 192}, + {0x03, 2, 193}, + {0x06, 2, 193}, + {0x0a, 2, 193}, + {0x0f, 2, 193}, + {0x18, 2, 193}, + {0x1f, 2, 193}, + {0x29, 2, 193}, + {0x38, 3, 193}, }, /* 195 */ { - {0x8003, 200}, - {0x8006, 200}, - {0x800a, 200}, - {0x800f, 200}, - {0x8018, 200}, - {0x801f, 200}, - {0x8029, 200}, - {0xc038, 200}, - {0x8003, 201}, - {0x8006, 201}, - {0x800a, 201}, - {0x800f, 201}, - {0x8018, 201}, - {0x801f, 201}, - {0x8029, 201}, - {0xc038, 201}, + {0x03, 2, 200}, + {0x06, 2, 200}, + {0x0a, 2, 200}, + {0x0f, 2, 200}, + {0x18, 2, 200}, + {0x1f, 2, 200}, + {0x29, 2, 200}, + {0x38, 3, 200}, + {0x03, 2, 201}, + {0x06, 2, 201}, + {0x0a, 2, 201}, + {0x0f, 2, 201}, + {0x18, 2, 201}, + {0x1f, 2, 201}, + {0x29, 2, 201}, + {0x38, 3, 201}, }, /* 196 */ { - {0x8002, 202}, - {0x8009, 202}, - {0x8017, 202}, - {0xc028, 202}, - {0x8002, 205}, - {0x8009, 205}, - {0x8017, 205}, - {0xc028, 205}, - {0x8002, 210}, - {0x8009, 210}, - {0x8017, 210}, - {0xc028, 210}, - {0x8002, 213}, - {0x8009, 213}, - {0x8017, 213}, - {0xc028, 213}, + {0x02, 2, 202}, + {0x09, 2, 202}, + {0x17, 2, 202}, + {0x28, 3, 202}, + {0x02, 2, 205}, + {0x09, 2, 205}, + {0x17, 2, 205}, + {0x28, 3, 205}, + {0x02, 2, 210}, + {0x09, 2, 210}, + {0x17, 2, 210}, + {0x28, 3, 210}, + {0x02, 2, 213}, + {0x09, 2, 213}, + {0x17, 2, 213}, + {0x28, 3, 213}, }, /* 197 */ { - {0x8003, 202}, - {0x8006, 202}, - {0x800a, 202}, - {0x800f, 202}, - {0x8018, 202}, - {0x801f, 202}, - {0x8029, 202}, - {0xc038, 202}, - {0x8003, 205}, - {0x8006, 205}, - {0x800a, 205}, - {0x800f, 205}, - {0x8018, 205}, - {0x801f, 205}, - {0x8029, 205}, - {0xc038, 205}, + {0x03, 2, 202}, + {0x06, 2, 202}, + {0x0a, 2, 202}, + {0x0f, 2, 202}, + {0x18, 2, 202}, + {0x1f, 2, 202}, + {0x29, 2, 202}, + {0x38, 3, 202}, + {0x03, 2, 205}, + {0x06, 2, 205}, + {0x0a, 2, 205}, + {0x0f, 2, 205}, + {0x18, 2, 205}, + {0x1f, 2, 205}, + {0x29, 2, 205}, + {0x38, 3, 205}, }, /* 198 */ { - {0x8003, 210}, - {0x8006, 210}, - {0x800a, 210}, - {0x800f, 210}, - {0x8018, 210}, - {0x801f, 210}, - {0x8029, 210}, - {0xc038, 210}, - {0x8003, 213}, - {0x8006, 213}, - {0x800a, 213}, - {0x800f, 213}, - {0x8018, 213}, - {0x801f, 213}, - {0x8029, 213}, - {0xc038, 213}, + {0x03, 2, 210}, + {0x06, 2, 210}, + {0x0a, 2, 210}, + {0x0f, 2, 210}, + {0x18, 2, 210}, + {0x1f, 2, 210}, + {0x29, 2, 210}, + {0x38, 3, 210}, + {0x03, 2, 213}, + {0x06, 2, 213}, + {0x0a, 2, 213}, + {0x0f, 2, 213}, + {0x18, 2, 213}, + {0x1f, 2, 213}, + {0x29, 2, 213}, + {0x38, 3, 213}, }, /* 199 */ { - {0x8001, 218}, - {0xc016, 218}, - {0x8001, 219}, - {0xc016, 219}, - {0x8001, 238}, - {0xc016, 238}, - {0x8001, 240}, - {0xc016, 240}, - {0x8001, 242}, - {0xc016, 242}, - {0x8001, 243}, - {0xc016, 243}, - {0x8001, 255}, - {0xc016, 255}, - {0xc000, 203}, - {0xc000, 204}, + {0x01, 2, 218}, + {0x16, 3, 218}, + {0x01, 2, 219}, + {0x16, 3, 219}, + {0x01, 2, 238}, + {0x16, 3, 238}, + {0x01, 2, 240}, + {0x16, 3, 240}, + {0x01, 2, 242}, + {0x16, 3, 242}, + {0x01, 2, 243}, + {0x16, 3, 243}, + {0x01, 2, 255}, + {0x16, 3, 255}, + {0x00, 3, 203}, + {0x00, 3, 204}, }, /* 200 */ { - {0x8002, 218}, - {0x8009, 218}, - {0x8017, 218}, - {0xc028, 218}, - {0x8002, 219}, - {0x8009, 219}, - {0x8017, 219}, - {0xc028, 219}, - {0x8002, 238}, - {0x8009, 238}, - {0x8017, 238}, - {0xc028, 238}, - {0x8002, 240}, - {0x8009, 240}, - {0x8017, 240}, - {0xc028, 240}, + {0x02, 2, 218}, + {0x09, 2, 218}, + {0x17, 2, 218}, + {0x28, 3, 218}, + {0x02, 2, 219}, + {0x09, 2, 219}, + {0x17, 2, 219}, + {0x28, 3, 219}, + {0x02, 2, 238}, + {0x09, 2, 238}, + {0x17, 2, 238}, + {0x28, 3, 238}, + {0x02, 2, 240}, + {0x09, 2, 240}, + {0x17, 2, 240}, + {0x28, 3, 240}, }, /* 201 */ { - {0x8003, 218}, - {0x8006, 218}, - {0x800a, 218}, - {0x800f, 218}, - {0x8018, 218}, - {0x801f, 218}, - {0x8029, 218}, - {0xc038, 218}, - {0x8003, 219}, - {0x8006, 219}, - {0x800a, 219}, - {0x800f, 219}, - {0x8018, 219}, - {0x801f, 219}, - {0x8029, 219}, - {0xc038, 219}, + {0x03, 2, 218}, + {0x06, 2, 218}, + {0x0a, 2, 218}, + {0x0f, 2, 218}, + {0x18, 2, 218}, + {0x1f, 2, 218}, + {0x29, 2, 218}, + {0x38, 3, 218}, + {0x03, 2, 219}, + {0x06, 2, 219}, + {0x0a, 2, 219}, + {0x0f, 2, 219}, + {0x18, 2, 219}, + {0x1f, 2, 219}, + {0x29, 2, 219}, + {0x38, 3, 219}, }, /* 202 */ { - {0x8003, 238}, - {0x8006, 238}, - {0x800a, 238}, - {0x800f, 238}, - {0x8018, 238}, - {0x801f, 238}, - {0x8029, 238}, - {0xc038, 238}, - {0x8003, 240}, - {0x8006, 240}, - {0x800a, 240}, - {0x800f, 240}, - {0x8018, 240}, - {0x801f, 240}, - {0x8029, 240}, - {0xc038, 240}, + {0x03, 2, 238}, + {0x06, 2, 238}, + {0x0a, 2, 238}, + {0x0f, 2, 238}, + {0x18, 2, 238}, + {0x1f, 2, 238}, + {0x29, 2, 238}, + {0x38, 3, 238}, + {0x03, 2, 240}, + {0x06, 2, 240}, + {0x0a, 2, 240}, + {0x0f, 2, 240}, + {0x18, 2, 240}, + {0x1f, 2, 240}, + {0x29, 2, 240}, + {0x38, 3, 240}, }, /* 203 */ { - {0x8002, 242}, - {0x8009, 242}, - {0x8017, 242}, - {0xc028, 242}, - {0x8002, 243}, - {0x8009, 243}, - {0x8017, 243}, - {0xc028, 243}, - {0x8002, 255}, - {0x8009, 255}, - {0x8017, 255}, - {0xc028, 255}, - {0x8001, 203}, - {0xc016, 203}, - {0x8001, 204}, - {0xc016, 204}, + {0x02, 2, 242}, + {0x09, 2, 242}, + {0x17, 2, 242}, + {0x28, 3, 242}, + {0x02, 2, 243}, + {0x09, 2, 243}, + {0x17, 2, 243}, + {0x28, 3, 243}, + {0x02, 2, 255}, + {0x09, 2, 255}, + {0x17, 2, 255}, + {0x28, 3, 255}, + {0x01, 2, 203}, + {0x16, 3, 203}, + {0x01, 2, 204}, + {0x16, 3, 204}, }, /* 204 */ { - {0x8003, 242}, - {0x8006, 242}, - {0x800a, 242}, - {0x800f, 242}, - {0x8018, 242}, - {0x801f, 242}, - {0x8029, 242}, - {0xc038, 242}, - {0x8003, 243}, - {0x8006, 243}, - {0x800a, 243}, - {0x800f, 243}, - {0x8018, 243}, - {0x801f, 243}, - {0x8029, 243}, - {0xc038, 243}, + {0x03, 2, 242}, + {0x06, 2, 242}, + {0x0a, 2, 242}, + {0x0f, 2, 242}, + {0x18, 2, 242}, + {0x1f, 2, 242}, + {0x29, 2, 242}, + {0x38, 3, 242}, + {0x03, 2, 243}, + {0x06, 2, 243}, + {0x0a, 2, 243}, + {0x0f, 2, 243}, + {0x18, 2, 243}, + {0x1f, 2, 243}, + {0x29, 2, 243}, + {0x38, 3, 243}, }, /* 205 */ { - {0x8003, 255}, - {0x8006, 255}, - {0x800a, 255}, - {0x800f, 255}, - {0x8018, 255}, - {0x801f, 255}, - {0x8029, 255}, - {0xc038, 255}, - {0x8002, 203}, - {0x8009, 203}, - {0x8017, 203}, - {0xc028, 203}, - {0x8002, 204}, - {0x8009, 204}, - {0x8017, 204}, - {0xc028, 204}, + {0x03, 2, 255}, + {0x06, 2, 255}, + {0x0a, 2, 255}, + {0x0f, 2, 255}, + {0x18, 2, 255}, + {0x1f, 2, 255}, + {0x29, 2, 255}, + {0x38, 3, 255}, + {0x02, 2, 203}, + {0x09, 2, 203}, + {0x17, 2, 203}, + {0x28, 3, 203}, + {0x02, 2, 204}, + {0x09, 2, 204}, + {0x17, 2, 204}, + {0x28, 3, 204}, }, /* 206 */ { - {0x8003, 203}, - {0x8006, 203}, - {0x800a, 203}, - {0x800f, 203}, - {0x8018, 203}, - {0x801f, 203}, - {0x8029, 203}, - {0xc038, 203}, - {0x8003, 204}, - {0x8006, 204}, - {0x800a, 204}, - {0x800f, 204}, - {0x8018, 204}, - {0x801f, 204}, - {0x8029, 204}, - {0xc038, 204}, + {0x03, 2, 203}, + {0x06, 2, 203}, + {0x0a, 2, 203}, + {0x0f, 2, 203}, + {0x18, 2, 203}, + {0x1f, 2, 203}, + {0x29, 2, 203}, + {0x38, 3, 203}, + {0x03, 2, 204}, + {0x06, 2, 204}, + {0x0a, 2, 204}, + {0x0f, 2, 204}, + {0x18, 2, 204}, + {0x1f, 2, 204}, + {0x29, 2, 204}, + {0x38, 3, 204}, }, /* 207 */ { - {0xd3, 0}, - {0xd4, 0}, - {0xd6, 0}, - {0xd7, 0}, - {0xda, 0}, - {0xdb, 0}, - {0xdd, 0}, - {0xde, 0}, - {0xe2, 0}, - {0xe4, 0}, - {0xe8, 0}, - {0xeb, 0}, - {0xf0, 0}, - {0xf3, 0}, - {0xf7, 0}, - {0xfa, 0}, + {0xd3, 0, 0}, + {0xd4, 0, 0}, + {0xd6, 0, 0}, + {0xd7, 0, 0}, + {0xda, 0, 0}, + {0xdb, 0, 0}, + {0xdd, 0, 0}, + {0xde, 0, 0}, + {0xe2, 0, 0}, + {0xe4, 0, 0}, + {0xe8, 0, 0}, + {0xeb, 0, 0}, + {0xf0, 0, 0}, + {0xf3, 0, 0}, + {0xf7, 0, 0}, + {0xfa, 0, 0}, }, /* 208 */ { - {0xc000, 211}, - {0xc000, 212}, - {0xc000, 214}, - {0xc000, 221}, - {0xc000, 222}, - {0xc000, 223}, - {0xc000, 241}, - {0xc000, 244}, - {0xc000, 245}, - {0xc000, 246}, - {0xc000, 247}, - {0xc000, 248}, - {0xc000, 250}, - {0xc000, 251}, - {0xc000, 252}, - {0xc000, 253}, + {0x00, 3, 211}, + {0x00, 3, 212}, + {0x00, 3, 214}, + {0x00, 3, 221}, + {0x00, 3, 222}, + {0x00, 3, 223}, + {0x00, 3, 241}, + {0x00, 3, 244}, + {0x00, 3, 245}, + {0x00, 3, 246}, + {0x00, 3, 247}, + {0x00, 3, 248}, + {0x00, 3, 250}, + {0x00, 3, 251}, + {0x00, 3, 252}, + {0x00, 3, 253}, }, /* 209 */ { - {0x8001, 211}, - {0xc016, 211}, - {0x8001, 212}, - {0xc016, 212}, - {0x8001, 214}, - {0xc016, 214}, - {0x8001, 221}, - {0xc016, 221}, - {0x8001, 222}, - {0xc016, 222}, - {0x8001, 223}, - {0xc016, 223}, - {0x8001, 241}, - {0xc016, 241}, - {0x8001, 244}, - {0xc016, 244}, + {0x01, 2, 211}, + {0x16, 3, 211}, + {0x01, 2, 212}, + {0x16, 3, 212}, + {0x01, 2, 214}, + {0x16, 3, 214}, + {0x01, 2, 221}, + {0x16, 3, 221}, + {0x01, 2, 222}, + {0x16, 3, 222}, + {0x01, 2, 223}, + {0x16, 3, 223}, + {0x01, 2, 241}, + {0x16, 3, 241}, + {0x01, 2, 244}, + {0x16, 3, 244}, }, /* 210 */ { - {0x8002, 211}, - {0x8009, 211}, - {0x8017, 211}, - {0xc028, 211}, - {0x8002, 212}, - {0x8009, 212}, - {0x8017, 212}, - {0xc028, 212}, - {0x8002, 214}, - {0x8009, 214}, - {0x8017, 214}, - {0xc028, 214}, - {0x8002, 221}, - {0x8009, 221}, - {0x8017, 221}, - {0xc028, 221}, + {0x02, 2, 211}, + {0x09, 2, 211}, + {0x17, 2, 211}, + {0x28, 3, 211}, + {0x02, 2, 212}, + {0x09, 2, 212}, + {0x17, 2, 212}, + {0x28, 3, 212}, + {0x02, 2, 214}, + {0x09, 2, 214}, + {0x17, 2, 214}, + {0x28, 3, 214}, + {0x02, 2, 221}, + {0x09, 2, 221}, + {0x17, 2, 221}, + {0x28, 3, 221}, }, /* 211 */ { - {0x8003, 211}, - {0x8006, 211}, - {0x800a, 211}, - {0x800f, 211}, - {0x8018, 211}, - {0x801f, 211}, - {0x8029, 211}, - {0xc038, 211}, - {0x8003, 212}, - {0x8006, 212}, - {0x800a, 212}, - {0x800f, 212}, - {0x8018, 212}, - {0x801f, 212}, - {0x8029, 212}, - {0xc038, 212}, + {0x03, 2, 211}, + {0x06, 2, 211}, + {0x0a, 2, 211}, + {0x0f, 2, 211}, + {0x18, 2, 211}, + {0x1f, 2, 211}, + {0x29, 2, 211}, + {0x38, 3, 211}, + {0x03, 2, 212}, + {0x06, 2, 212}, + {0x0a, 2, 212}, + {0x0f, 2, 212}, + {0x18, 2, 212}, + {0x1f, 2, 212}, + {0x29, 2, 212}, + {0x38, 3, 212}, }, /* 212 */ { - {0x8003, 214}, - {0x8006, 214}, - {0x800a, 214}, - {0x800f, 214}, - {0x8018, 214}, - {0x801f, 214}, - {0x8029, 214}, - {0xc038, 214}, - {0x8003, 221}, - {0x8006, 221}, - {0x800a, 221}, - {0x800f, 221}, - {0x8018, 221}, - {0x801f, 221}, - {0x8029, 221}, - {0xc038, 221}, + {0x03, 2, 214}, + {0x06, 2, 214}, + {0x0a, 2, 214}, + {0x0f, 2, 214}, + {0x18, 2, 214}, + {0x1f, 2, 214}, + {0x29, 2, 214}, + {0x38, 3, 214}, + {0x03, 2, 221}, + {0x06, 2, 221}, + {0x0a, 2, 221}, + {0x0f, 2, 221}, + {0x18, 2, 221}, + {0x1f, 2, 221}, + {0x29, 2, 221}, + {0x38, 3, 221}, }, /* 213 */ { - {0x8002, 222}, - {0x8009, 222}, - {0x8017, 222}, - {0xc028, 222}, - {0x8002, 223}, - {0x8009, 223}, - {0x8017, 223}, - {0xc028, 223}, - {0x8002, 241}, - {0x8009, 241}, - {0x8017, 241}, - {0xc028, 241}, - {0x8002, 244}, - {0x8009, 244}, - {0x8017, 244}, - {0xc028, 244}, + {0x02, 2, 222}, + {0x09, 2, 222}, + {0x17, 2, 222}, + {0x28, 3, 222}, + {0x02, 2, 223}, + {0x09, 2, 223}, + {0x17, 2, 223}, + {0x28, 3, 223}, + {0x02, 2, 241}, + {0x09, 2, 241}, + {0x17, 2, 241}, + {0x28, 3, 241}, + {0x02, 2, 244}, + {0x09, 2, 244}, + {0x17, 2, 244}, + {0x28, 3, 244}, }, /* 214 */ { - {0x8003, 222}, - {0x8006, 222}, - {0x800a, 222}, - {0x800f, 222}, - {0x8018, 222}, - {0x801f, 222}, - {0x8029, 222}, - {0xc038, 222}, - {0x8003, 223}, - {0x8006, 223}, - {0x800a, 223}, - {0x800f, 223}, - {0x8018, 223}, - {0x801f, 223}, - {0x8029, 223}, - {0xc038, 223}, + {0x03, 2, 222}, + {0x06, 2, 222}, + {0x0a, 2, 222}, + {0x0f, 2, 222}, + {0x18, 2, 222}, + {0x1f, 2, 222}, + {0x29, 2, 222}, + {0x38, 3, 222}, + {0x03, 2, 223}, + {0x06, 2, 223}, + {0x0a, 2, 223}, + {0x0f, 2, 223}, + {0x18, 2, 223}, + {0x1f, 2, 223}, + {0x29, 2, 223}, + {0x38, 3, 223}, }, /* 215 */ { - {0x8003, 241}, - {0x8006, 241}, - {0x800a, 241}, - {0x800f, 241}, - {0x8018, 241}, - {0x801f, 241}, - {0x8029, 241}, - {0xc038, 241}, - {0x8003, 244}, - {0x8006, 244}, - {0x800a, 244}, - {0x800f, 244}, - {0x8018, 244}, - {0x801f, 244}, - {0x8029, 244}, - {0xc038, 244}, + {0x03, 2, 241}, + {0x06, 2, 241}, + {0x0a, 2, 241}, + {0x0f, 2, 241}, + {0x18, 2, 241}, + {0x1f, 2, 241}, + {0x29, 2, 241}, + {0x38, 3, 241}, + {0x03, 2, 244}, + {0x06, 2, 244}, + {0x0a, 2, 244}, + {0x0f, 2, 244}, + {0x18, 2, 244}, + {0x1f, 2, 244}, + {0x29, 2, 244}, + {0x38, 3, 244}, }, /* 216 */ { - {0x8001, 245}, - {0xc016, 245}, - {0x8001, 246}, - {0xc016, 246}, - {0x8001, 247}, - {0xc016, 247}, - {0x8001, 248}, - {0xc016, 248}, - {0x8001, 250}, - {0xc016, 250}, - {0x8001, 251}, - {0xc016, 251}, - {0x8001, 252}, - {0xc016, 252}, - {0x8001, 253}, - {0xc016, 253}, + {0x01, 2, 245}, + {0x16, 3, 245}, + {0x01, 2, 246}, + {0x16, 3, 246}, + {0x01, 2, 247}, + {0x16, 3, 247}, + {0x01, 2, 248}, + {0x16, 3, 248}, + {0x01, 2, 250}, + {0x16, 3, 250}, + {0x01, 2, 251}, + {0x16, 3, 251}, + {0x01, 2, 252}, + {0x16, 3, 252}, + {0x01, 2, 253}, + {0x16, 3, 253}, }, /* 217 */ { - {0x8002, 245}, - {0x8009, 245}, - {0x8017, 245}, - {0xc028, 245}, - {0x8002, 246}, - {0x8009, 246}, - {0x8017, 246}, - {0xc028, 246}, - {0x8002, 247}, - {0x8009, 247}, - {0x8017, 247}, - {0xc028, 247}, - {0x8002, 248}, - {0x8009, 248}, - {0x8017, 248}, - {0xc028, 248}, + {0x02, 2, 245}, + {0x09, 2, 245}, + {0x17, 2, 245}, + {0x28, 3, 245}, + {0x02, 2, 246}, + {0x09, 2, 246}, + {0x17, 2, 246}, + {0x28, 3, 246}, + {0x02, 2, 247}, + {0x09, 2, 247}, + {0x17, 2, 247}, + {0x28, 3, 247}, + {0x02, 2, 248}, + {0x09, 2, 248}, + {0x17, 2, 248}, + {0x28, 3, 248}, }, /* 218 */ { - {0x8003, 245}, - {0x8006, 245}, - {0x800a, 245}, - {0x800f, 245}, - {0x8018, 245}, - {0x801f, 245}, - {0x8029, 245}, - {0xc038, 245}, - {0x8003, 246}, - {0x8006, 246}, - {0x800a, 246}, - {0x800f, 246}, - {0x8018, 246}, - {0x801f, 246}, - {0x8029, 246}, - {0xc038, 246}, + {0x03, 2, 245}, + {0x06, 2, 245}, + {0x0a, 2, 245}, + {0x0f, 2, 245}, + {0x18, 2, 245}, + {0x1f, 2, 245}, + {0x29, 2, 245}, + {0x38, 3, 245}, + {0x03, 2, 246}, + {0x06, 2, 246}, + {0x0a, 2, 246}, + {0x0f, 2, 246}, + {0x18, 2, 246}, + {0x1f, 2, 246}, + {0x29, 2, 246}, + {0x38, 3, 246}, }, /* 219 */ { - {0x8003, 247}, - {0x8006, 247}, - {0x800a, 247}, - {0x800f, 247}, - {0x8018, 247}, - {0x801f, 247}, - {0x8029, 247}, - {0xc038, 247}, - {0x8003, 248}, - {0x8006, 248}, - {0x800a, 248}, - {0x800f, 248}, - {0x8018, 248}, - {0x801f, 248}, - {0x8029, 248}, - {0xc038, 248}, + {0x03, 2, 247}, + {0x06, 2, 247}, + {0x0a, 2, 247}, + {0x0f, 2, 247}, + {0x18, 2, 247}, + {0x1f, 2, 247}, + {0x29, 2, 247}, + {0x38, 3, 247}, + {0x03, 2, 248}, + {0x06, 2, 248}, + {0x0a, 2, 248}, + {0x0f, 2, 248}, + {0x18, 2, 248}, + {0x1f, 2, 248}, + {0x29, 2, 248}, + {0x38, 3, 248}, }, /* 220 */ { - {0x8002, 250}, - {0x8009, 250}, - {0x8017, 250}, - {0xc028, 250}, - {0x8002, 251}, - {0x8009, 251}, - {0x8017, 251}, - {0xc028, 251}, - {0x8002, 252}, - {0x8009, 252}, - {0x8017, 252}, - {0xc028, 252}, - {0x8002, 253}, - {0x8009, 253}, - {0x8017, 253}, - {0xc028, 253}, + {0x02, 2, 250}, + {0x09, 2, 250}, + {0x17, 2, 250}, + {0x28, 3, 250}, + {0x02, 2, 251}, + {0x09, 2, 251}, + {0x17, 2, 251}, + {0x28, 3, 251}, + {0x02, 2, 252}, + {0x09, 2, 252}, + {0x17, 2, 252}, + {0x28, 3, 252}, + {0x02, 2, 253}, + {0x09, 2, 253}, + {0x17, 2, 253}, + {0x28, 3, 253}, }, /* 221 */ { - {0x8003, 250}, - {0x8006, 250}, - {0x800a, 250}, - {0x800f, 250}, - {0x8018, 250}, - {0x801f, 250}, - {0x8029, 250}, - {0xc038, 250}, - {0x8003, 251}, - {0x8006, 251}, - {0x800a, 251}, - {0x800f, 251}, - {0x8018, 251}, - {0x801f, 251}, - {0x8029, 251}, - {0xc038, 251}, + {0x03, 2, 250}, + {0x06, 2, 250}, + {0x0a, 2, 250}, + {0x0f, 2, 250}, + {0x18, 2, 250}, + {0x1f, 2, 250}, + {0x29, 2, 250}, + {0x38, 3, 250}, + {0x03, 2, 251}, + {0x06, 2, 251}, + {0x0a, 2, 251}, + {0x0f, 2, 251}, + {0x18, 2, 251}, + {0x1f, 2, 251}, + {0x29, 2, 251}, + {0x38, 3, 251}, }, /* 222 */ { - {0x8003, 252}, - {0x8006, 252}, - {0x800a, 252}, - {0x800f, 252}, - {0x8018, 252}, - {0x801f, 252}, - {0x8029, 252}, - {0xc038, 252}, - {0x8003, 253}, - {0x8006, 253}, - {0x800a, 253}, - {0x800f, 253}, - {0x8018, 253}, - {0x801f, 253}, - {0x8029, 253}, - {0xc038, 253}, + {0x03, 2, 252}, + {0x06, 2, 252}, + {0x0a, 2, 252}, + {0x0f, 2, 252}, + {0x18, 2, 252}, + {0x1f, 2, 252}, + {0x29, 2, 252}, + {0x38, 3, 252}, + {0x03, 2, 253}, + {0x06, 2, 253}, + {0x0a, 2, 253}, + {0x0f, 2, 253}, + {0x18, 2, 253}, + {0x1f, 2, 253}, + {0x29, 2, 253}, + {0x38, 3, 253}, }, /* 223 */ { - {0xc000, 254}, - {0xe3, 0}, - {0xe5, 0}, - {0xe6, 0}, - {0xe9, 0}, - {0xea, 0}, - {0xec, 0}, - {0xed, 0}, - {0xf1, 0}, - {0xf2, 0}, - {0xf4, 0}, - {0xf5, 0}, - {0xf8, 0}, - {0xf9, 0}, - {0xfb, 0}, - {0xfc, 0}, + {0x00, 3, 254}, + {0xe3, 0, 0}, + {0xe5, 0, 0}, + {0xe6, 0, 0}, + {0xe9, 0, 0}, + {0xea, 0, 0}, + {0xec, 0, 0}, + {0xed, 0, 0}, + {0xf1, 0, 0}, + {0xf2, 0, 0}, + {0xf4, 0, 0}, + {0xf5, 0, 0}, + {0xf8, 0, 0}, + {0xf9, 0, 0}, + {0xfb, 0, 0}, + {0xfc, 0, 0}, }, /* 224 */ { - {0x8001, 254}, - {0xc016, 254}, - {0xc000, 2}, - {0xc000, 3}, - {0xc000, 4}, - {0xc000, 5}, - {0xc000, 6}, - {0xc000, 7}, - {0xc000, 8}, - {0xc000, 11}, - {0xc000, 12}, - {0xc000, 14}, - {0xc000, 15}, - {0xc000, 16}, - {0xc000, 17}, - {0xc000, 18}, + {0x01, 2, 254}, + {0x16, 3, 254}, + {0x00, 3, 2}, + {0x00, 3, 3}, + {0x00, 3, 4}, + {0x00, 3, 5}, + {0x00, 3, 6}, + {0x00, 3, 7}, + {0x00, 3, 8}, + {0x00, 3, 11}, + {0x00, 3, 12}, + {0x00, 3, 14}, + {0x00, 3, 15}, + {0x00, 3, 16}, + {0x00, 3, 17}, + {0x00, 3, 18}, }, /* 225 */ { - {0x8002, 254}, - {0x8009, 254}, - {0x8017, 254}, - {0xc028, 254}, - {0x8001, 2}, - {0xc016, 2}, - {0x8001, 3}, - {0xc016, 3}, - {0x8001, 4}, - {0xc016, 4}, - {0x8001, 5}, - {0xc016, 5}, - {0x8001, 6}, - {0xc016, 6}, - {0x8001, 7}, - {0xc016, 7}, + {0x02, 2, 254}, + {0x09, 2, 254}, + {0x17, 2, 254}, + {0x28, 3, 254}, + {0x01, 2, 2}, + {0x16, 3, 2}, + {0x01, 2, 3}, + {0x16, 3, 3}, + {0x01, 2, 4}, + {0x16, 3, 4}, + {0x01, 2, 5}, + {0x16, 3, 5}, + {0x01, 2, 6}, + {0x16, 3, 6}, + {0x01, 2, 7}, + {0x16, 3, 7}, }, /* 226 */ { - {0x8003, 254}, - {0x8006, 254}, - {0x800a, 254}, - {0x800f, 254}, - {0x8018, 254}, - {0x801f, 254}, - {0x8029, 254}, - {0xc038, 254}, - {0x8002, 2}, - {0x8009, 2}, - {0x8017, 2}, - {0xc028, 2}, - {0x8002, 3}, - {0x8009, 3}, - {0x8017, 3}, - {0xc028, 3}, + {0x03, 2, 254}, + {0x06, 2, 254}, + {0x0a, 2, 254}, + {0x0f, 2, 254}, + {0x18, 2, 254}, + {0x1f, 2, 254}, + {0x29, 2, 254}, + {0x38, 3, 254}, + {0x02, 2, 2}, + {0x09, 2, 2}, + {0x17, 2, 2}, + {0x28, 3, 2}, + {0x02, 2, 3}, + {0x09, 2, 3}, + {0x17, 2, 3}, + {0x28, 3, 3}, }, /* 227 */ { - {0x8003, 2}, - {0x8006, 2}, - {0x800a, 2}, - {0x800f, 2}, - {0x8018, 2}, - {0x801f, 2}, - {0x8029, 2}, - {0xc038, 2}, - {0x8003, 3}, - {0x8006, 3}, - {0x800a, 3}, - {0x800f, 3}, - {0x8018, 3}, - {0x801f, 3}, - {0x8029, 3}, - {0xc038, 3}, + {0x03, 2, 2}, + {0x06, 2, 2}, + {0x0a, 2, 2}, + {0x0f, 2, 2}, + {0x18, 2, 2}, + {0x1f, 2, 2}, + {0x29, 2, 2}, + {0x38, 3, 2}, + {0x03, 2, 3}, + {0x06, 2, 3}, + {0x0a, 2, 3}, + {0x0f, 2, 3}, + {0x18, 2, 3}, + {0x1f, 2, 3}, + {0x29, 2, 3}, + {0x38, 3, 3}, }, /* 228 */ { - {0x8002, 4}, - {0x8009, 4}, - {0x8017, 4}, - {0xc028, 4}, - {0x8002, 5}, - {0x8009, 5}, - {0x8017, 5}, - {0xc028, 5}, - {0x8002, 6}, - {0x8009, 6}, - {0x8017, 6}, - {0xc028, 6}, - {0x8002, 7}, - {0x8009, 7}, - {0x8017, 7}, - {0xc028, 7}, + {0x02, 2, 4}, + {0x09, 2, 4}, + {0x17, 2, 4}, + {0x28, 3, 4}, + {0x02, 2, 5}, + {0x09, 2, 5}, + {0x17, 2, 5}, + {0x28, 3, 5}, + {0x02, 2, 6}, + {0x09, 2, 6}, + {0x17, 2, 6}, + {0x28, 3, 6}, + {0x02, 2, 7}, + {0x09, 2, 7}, + {0x17, 2, 7}, + {0x28, 3, 7}, }, /* 229 */ { - {0x8003, 4}, - {0x8006, 4}, - {0x800a, 4}, - {0x800f, 4}, - {0x8018, 4}, - {0x801f, 4}, - {0x8029, 4}, - {0xc038, 4}, - {0x8003, 5}, - {0x8006, 5}, - {0x800a, 5}, - {0x800f, 5}, - {0x8018, 5}, - {0x801f, 5}, - {0x8029, 5}, - {0xc038, 5}, + {0x03, 2, 4}, + {0x06, 2, 4}, + {0x0a, 2, 4}, + {0x0f, 2, 4}, + {0x18, 2, 4}, + {0x1f, 2, 4}, + {0x29, 2, 4}, + {0x38, 3, 4}, + {0x03, 2, 5}, + {0x06, 2, 5}, + {0x0a, 2, 5}, + {0x0f, 2, 5}, + {0x18, 2, 5}, + {0x1f, 2, 5}, + {0x29, 2, 5}, + {0x38, 3, 5}, }, /* 230 */ { - {0x8003, 6}, - {0x8006, 6}, - {0x800a, 6}, - {0x800f, 6}, - {0x8018, 6}, - {0x801f, 6}, - {0x8029, 6}, - {0xc038, 6}, - {0x8003, 7}, - {0x8006, 7}, - {0x800a, 7}, - {0x800f, 7}, - {0x8018, 7}, - {0x801f, 7}, - {0x8029, 7}, - {0xc038, 7}, + {0x03, 2, 6}, + {0x06, 2, 6}, + {0x0a, 2, 6}, + {0x0f, 2, 6}, + {0x18, 2, 6}, + {0x1f, 2, 6}, + {0x29, 2, 6}, + {0x38, 3, 6}, + {0x03, 2, 7}, + {0x06, 2, 7}, + {0x0a, 2, 7}, + {0x0f, 2, 7}, + {0x18, 2, 7}, + {0x1f, 2, 7}, + {0x29, 2, 7}, + {0x38, 3, 7}, }, /* 231 */ { - {0x8001, 8}, - {0xc016, 8}, - {0x8001, 11}, - {0xc016, 11}, - {0x8001, 12}, - {0xc016, 12}, - {0x8001, 14}, - {0xc016, 14}, - {0x8001, 15}, - {0xc016, 15}, - {0x8001, 16}, - {0xc016, 16}, - {0x8001, 17}, - {0xc016, 17}, - {0x8001, 18}, - {0xc016, 18}, + {0x01, 2, 8}, + {0x16, 3, 8}, + {0x01, 2, 11}, + {0x16, 3, 11}, + {0x01, 2, 12}, + {0x16, 3, 12}, + {0x01, 2, 14}, + {0x16, 3, 14}, + {0x01, 2, 15}, + {0x16, 3, 15}, + {0x01, 2, 16}, + {0x16, 3, 16}, + {0x01, 2, 17}, + {0x16, 3, 17}, + {0x01, 2, 18}, + {0x16, 3, 18}, }, /* 232 */ { - {0x8002, 8}, - {0x8009, 8}, - {0x8017, 8}, - {0xc028, 8}, - {0x8002, 11}, - {0x8009, 11}, - {0x8017, 11}, - {0xc028, 11}, - {0x8002, 12}, - {0x8009, 12}, - {0x8017, 12}, - {0xc028, 12}, - {0x8002, 14}, - {0x8009, 14}, - {0x8017, 14}, - {0xc028, 14}, + {0x02, 2, 8}, + {0x09, 2, 8}, + {0x17, 2, 8}, + {0x28, 3, 8}, + {0x02, 2, 11}, + {0x09, 2, 11}, + {0x17, 2, 11}, + {0x28, 3, 11}, + {0x02, 2, 12}, + {0x09, 2, 12}, + {0x17, 2, 12}, + {0x28, 3, 12}, + {0x02, 2, 14}, + {0x09, 2, 14}, + {0x17, 2, 14}, + {0x28, 3, 14}, }, /* 233 */ { - {0x8003, 8}, - {0x8006, 8}, - {0x800a, 8}, - {0x800f, 8}, - {0x8018, 8}, - {0x801f, 8}, - {0x8029, 8}, - {0xc038, 8}, - {0x8003, 11}, - {0x8006, 11}, - {0x800a, 11}, - {0x800f, 11}, - {0x8018, 11}, - {0x801f, 11}, - {0x8029, 11}, - {0xc038, 11}, + {0x03, 2, 8}, + {0x06, 2, 8}, + {0x0a, 2, 8}, + {0x0f, 2, 8}, + {0x18, 2, 8}, + {0x1f, 2, 8}, + {0x29, 2, 8}, + {0x38, 3, 8}, + {0x03, 2, 11}, + {0x06, 2, 11}, + {0x0a, 2, 11}, + {0x0f, 2, 11}, + {0x18, 2, 11}, + {0x1f, 2, 11}, + {0x29, 2, 11}, + {0x38, 3, 11}, }, /* 234 */ { - {0x8003, 12}, - {0x8006, 12}, - {0x800a, 12}, - {0x800f, 12}, - {0x8018, 12}, - {0x801f, 12}, - {0x8029, 12}, - {0xc038, 12}, - {0x8003, 14}, - {0x8006, 14}, - {0x800a, 14}, - {0x800f, 14}, - {0x8018, 14}, - {0x801f, 14}, - {0x8029, 14}, - {0xc038, 14}, + {0x03, 2, 12}, + {0x06, 2, 12}, + {0x0a, 2, 12}, + {0x0f, 2, 12}, + {0x18, 2, 12}, + {0x1f, 2, 12}, + {0x29, 2, 12}, + {0x38, 3, 12}, + {0x03, 2, 14}, + {0x06, 2, 14}, + {0x0a, 2, 14}, + {0x0f, 2, 14}, + {0x18, 2, 14}, + {0x1f, 2, 14}, + {0x29, 2, 14}, + {0x38, 3, 14}, }, /* 235 */ { - {0x8002, 15}, - {0x8009, 15}, - {0x8017, 15}, - {0xc028, 15}, - {0x8002, 16}, - {0x8009, 16}, - {0x8017, 16}, - {0xc028, 16}, - {0x8002, 17}, - {0x8009, 17}, - {0x8017, 17}, - {0xc028, 17}, - {0x8002, 18}, - {0x8009, 18}, - {0x8017, 18}, - {0xc028, 18}, + {0x02, 2, 15}, + {0x09, 2, 15}, + {0x17, 2, 15}, + {0x28, 3, 15}, + {0x02, 2, 16}, + {0x09, 2, 16}, + {0x17, 2, 16}, + {0x28, 3, 16}, + {0x02, 2, 17}, + {0x09, 2, 17}, + {0x17, 2, 17}, + {0x28, 3, 17}, + {0x02, 2, 18}, + {0x09, 2, 18}, + {0x17, 2, 18}, + {0x28, 3, 18}, }, /* 236 */ { - {0x8003, 15}, - {0x8006, 15}, - {0x800a, 15}, - {0x800f, 15}, - {0x8018, 15}, - {0x801f, 15}, - {0x8029, 15}, - {0xc038, 15}, - {0x8003, 16}, - {0x8006, 16}, - {0x800a, 16}, - {0x800f, 16}, - {0x8018, 16}, - {0x801f, 16}, - {0x8029, 16}, - {0xc038, 16}, + {0x03, 2, 15}, + {0x06, 2, 15}, + {0x0a, 2, 15}, + {0x0f, 2, 15}, + {0x18, 2, 15}, + {0x1f, 2, 15}, + {0x29, 2, 15}, + {0x38, 3, 15}, + {0x03, 2, 16}, + {0x06, 2, 16}, + {0x0a, 2, 16}, + {0x0f, 2, 16}, + {0x18, 2, 16}, + {0x1f, 2, 16}, + {0x29, 2, 16}, + {0x38, 3, 16}, }, /* 237 */ { - {0x8003, 17}, - {0x8006, 17}, - {0x800a, 17}, - {0x800f, 17}, - {0x8018, 17}, - {0x801f, 17}, - {0x8029, 17}, - {0xc038, 17}, - {0x8003, 18}, - {0x8006, 18}, - {0x800a, 18}, - {0x800f, 18}, - {0x8018, 18}, - {0x801f, 18}, - {0x8029, 18}, - {0xc038, 18}, + {0x03, 2, 17}, + {0x06, 2, 17}, + {0x0a, 2, 17}, + {0x0f, 2, 17}, + {0x18, 2, 17}, + {0x1f, 2, 17}, + {0x29, 2, 17}, + {0x38, 3, 17}, + {0x03, 2, 18}, + {0x06, 2, 18}, + {0x0a, 2, 18}, + {0x0f, 2, 18}, + {0x18, 2, 18}, + {0x1f, 2, 18}, + {0x29, 2, 18}, + {0x38, 3, 18}, }, /* 238 */ { - {0xc000, 19}, - {0xc000, 20}, - {0xc000, 21}, - {0xc000, 23}, - {0xc000, 24}, - {0xc000, 25}, - {0xc000, 26}, - {0xc000, 27}, - {0xc000, 28}, - {0xc000, 29}, - {0xc000, 30}, - {0xc000, 31}, - {0xc000, 127}, - {0xc000, 220}, - {0xc000, 249}, - {0xfd, 0}, + {0x00, 3, 19}, + {0x00, 3, 20}, + {0x00, 3, 21}, + {0x00, 3, 23}, + {0x00, 3, 24}, + {0x00, 3, 25}, + {0x00, 3, 26}, + {0x00, 3, 27}, + {0x00, 3, 28}, + {0x00, 3, 29}, + {0x00, 3, 30}, + {0x00, 3, 31}, + {0x00, 3, 127}, + {0x00, 3, 220}, + {0x00, 3, 249}, + {0xfd, 0, 0}, }, /* 239 */ { - {0x8001, 19}, - {0xc016, 19}, - {0x8001, 20}, - {0xc016, 20}, - {0x8001, 21}, - {0xc016, 21}, - {0x8001, 23}, - {0xc016, 23}, - {0x8001, 24}, - {0xc016, 24}, - {0x8001, 25}, - {0xc016, 25}, - {0x8001, 26}, - {0xc016, 26}, - {0x8001, 27}, - {0xc016, 27}, + {0x01, 2, 19}, + {0x16, 3, 19}, + {0x01, 2, 20}, + {0x16, 3, 20}, + {0x01, 2, 21}, + {0x16, 3, 21}, + {0x01, 2, 23}, + {0x16, 3, 23}, + {0x01, 2, 24}, + {0x16, 3, 24}, + {0x01, 2, 25}, + {0x16, 3, 25}, + {0x01, 2, 26}, + {0x16, 3, 26}, + {0x01, 2, 27}, + {0x16, 3, 27}, }, /* 240 */ { - {0x8002, 19}, - {0x8009, 19}, - {0x8017, 19}, - {0xc028, 19}, - {0x8002, 20}, - {0x8009, 20}, - {0x8017, 20}, - {0xc028, 20}, - {0x8002, 21}, - {0x8009, 21}, - {0x8017, 21}, - {0xc028, 21}, - {0x8002, 23}, - {0x8009, 23}, - {0x8017, 23}, - {0xc028, 23}, + {0x02, 2, 19}, + {0x09, 2, 19}, + {0x17, 2, 19}, + {0x28, 3, 19}, + {0x02, 2, 20}, + {0x09, 2, 20}, + {0x17, 2, 20}, + {0x28, 3, 20}, + {0x02, 2, 21}, + {0x09, 2, 21}, + {0x17, 2, 21}, + {0x28, 3, 21}, + {0x02, 2, 23}, + {0x09, 2, 23}, + {0x17, 2, 23}, + {0x28, 3, 23}, }, /* 241 */ { - {0x8003, 19}, - {0x8006, 19}, - {0x800a, 19}, - {0x800f, 19}, - {0x8018, 19}, - {0x801f, 19}, - {0x8029, 19}, - {0xc038, 19}, - {0x8003, 20}, - {0x8006, 20}, - {0x800a, 20}, - {0x800f, 20}, - {0x8018, 20}, - {0x801f, 20}, - {0x8029, 20}, - {0xc038, 20}, + {0x03, 2, 19}, + {0x06, 2, 19}, + {0x0a, 2, 19}, + {0x0f, 2, 19}, + {0x18, 2, 19}, + {0x1f, 2, 19}, + {0x29, 2, 19}, + {0x38, 3, 19}, + {0x03, 2, 20}, + {0x06, 2, 20}, + {0x0a, 2, 20}, + {0x0f, 2, 20}, + {0x18, 2, 20}, + {0x1f, 2, 20}, + {0x29, 2, 20}, + {0x38, 3, 20}, }, /* 242 */ { - {0x8003, 21}, - {0x8006, 21}, - {0x800a, 21}, - {0x800f, 21}, - {0x8018, 21}, - {0x801f, 21}, - {0x8029, 21}, - {0xc038, 21}, - {0x8003, 23}, - {0x8006, 23}, - {0x800a, 23}, - {0x800f, 23}, - {0x8018, 23}, - {0x801f, 23}, - {0x8029, 23}, - {0xc038, 23}, + {0x03, 2, 21}, + {0x06, 2, 21}, + {0x0a, 2, 21}, + {0x0f, 2, 21}, + {0x18, 2, 21}, + {0x1f, 2, 21}, + {0x29, 2, 21}, + {0x38, 3, 21}, + {0x03, 2, 23}, + {0x06, 2, 23}, + {0x0a, 2, 23}, + {0x0f, 2, 23}, + {0x18, 2, 23}, + {0x1f, 2, 23}, + {0x29, 2, 23}, + {0x38, 3, 23}, }, /* 243 */ { - {0x8002, 24}, - {0x8009, 24}, - {0x8017, 24}, - {0xc028, 24}, - {0x8002, 25}, - {0x8009, 25}, - {0x8017, 25}, - {0xc028, 25}, - {0x8002, 26}, - {0x8009, 26}, - {0x8017, 26}, - {0xc028, 26}, - {0x8002, 27}, - {0x8009, 27}, - {0x8017, 27}, - {0xc028, 27}, + {0x02, 2, 24}, + {0x09, 2, 24}, + {0x17, 2, 24}, + {0x28, 3, 24}, + {0x02, 2, 25}, + {0x09, 2, 25}, + {0x17, 2, 25}, + {0x28, 3, 25}, + {0x02, 2, 26}, + {0x09, 2, 26}, + {0x17, 2, 26}, + {0x28, 3, 26}, + {0x02, 2, 27}, + {0x09, 2, 27}, + {0x17, 2, 27}, + {0x28, 3, 27}, }, /* 244 */ { - {0x8003, 24}, - {0x8006, 24}, - {0x800a, 24}, - {0x800f, 24}, - {0x8018, 24}, - {0x801f, 24}, - {0x8029, 24}, - {0xc038, 24}, - {0x8003, 25}, - {0x8006, 25}, - {0x800a, 25}, - {0x800f, 25}, - {0x8018, 25}, - {0x801f, 25}, - {0x8029, 25}, - {0xc038, 25}, + {0x03, 2, 24}, + {0x06, 2, 24}, + {0x0a, 2, 24}, + {0x0f, 2, 24}, + {0x18, 2, 24}, + {0x1f, 2, 24}, + {0x29, 2, 24}, + {0x38, 3, 24}, + {0x03, 2, 25}, + {0x06, 2, 25}, + {0x0a, 2, 25}, + {0x0f, 2, 25}, + {0x18, 2, 25}, + {0x1f, 2, 25}, + {0x29, 2, 25}, + {0x38, 3, 25}, }, /* 245 */ { - {0x8003, 26}, - {0x8006, 26}, - {0x800a, 26}, - {0x800f, 26}, - {0x8018, 26}, - {0x801f, 26}, - {0x8029, 26}, - {0xc038, 26}, - {0x8003, 27}, - {0x8006, 27}, - {0x800a, 27}, - {0x800f, 27}, - {0x8018, 27}, - {0x801f, 27}, - {0x8029, 27}, - {0xc038, 27}, + {0x03, 2, 26}, + {0x06, 2, 26}, + {0x0a, 2, 26}, + {0x0f, 2, 26}, + {0x18, 2, 26}, + {0x1f, 2, 26}, + {0x29, 2, 26}, + {0x38, 3, 26}, + {0x03, 2, 27}, + {0x06, 2, 27}, + {0x0a, 2, 27}, + {0x0f, 2, 27}, + {0x18, 2, 27}, + {0x1f, 2, 27}, + {0x29, 2, 27}, + {0x38, 3, 27}, }, /* 246 */ { - {0x8001, 28}, - {0xc016, 28}, - {0x8001, 29}, - {0xc016, 29}, - {0x8001, 30}, - {0xc016, 30}, - {0x8001, 31}, - {0xc016, 31}, - {0x8001, 127}, - {0xc016, 127}, - {0x8001, 220}, - {0xc016, 220}, - {0x8001, 249}, - {0xc016, 249}, - {0xfe, 0}, - {0xff, 0}, + {0x01, 2, 28}, + {0x16, 3, 28}, + {0x01, 2, 29}, + {0x16, 3, 29}, + {0x01, 2, 30}, + {0x16, 3, 30}, + {0x01, 2, 31}, + {0x16, 3, 31}, + {0x01, 2, 127}, + {0x16, 3, 127}, + {0x01, 2, 220}, + {0x16, 3, 220}, + {0x01, 2, 249}, + {0x16, 3, 249}, + {0xfe, 0, 0}, + {0xff, 0, 0}, }, /* 247 */ { - {0x8002, 28}, - {0x8009, 28}, - {0x8017, 28}, - {0xc028, 28}, - {0x8002, 29}, - {0x8009, 29}, - {0x8017, 29}, - {0xc028, 29}, - {0x8002, 30}, - {0x8009, 30}, - {0x8017, 30}, - {0xc028, 30}, - {0x8002, 31}, - {0x8009, 31}, - {0x8017, 31}, - {0xc028, 31}, + {0x02, 2, 28}, + {0x09, 2, 28}, + {0x17, 2, 28}, + {0x28, 3, 28}, + {0x02, 2, 29}, + {0x09, 2, 29}, + {0x17, 2, 29}, + {0x28, 3, 29}, + {0x02, 2, 30}, + {0x09, 2, 30}, + {0x17, 2, 30}, + {0x28, 3, 30}, + {0x02, 2, 31}, + {0x09, 2, 31}, + {0x17, 2, 31}, + {0x28, 3, 31}, }, /* 248 */ { - {0x8003, 28}, - {0x8006, 28}, - {0x800a, 28}, - {0x800f, 28}, - {0x8018, 28}, - {0x801f, 28}, - {0x8029, 28}, - {0xc038, 28}, - {0x8003, 29}, - {0x8006, 29}, - {0x800a, 29}, - {0x800f, 29}, - {0x8018, 29}, - {0x801f, 29}, - {0x8029, 29}, - {0xc038, 29}, + {0x03, 2, 28}, + {0x06, 2, 28}, + {0x0a, 2, 28}, + {0x0f, 2, 28}, + {0x18, 2, 28}, + {0x1f, 2, 28}, + {0x29, 2, 28}, + {0x38, 3, 28}, + {0x03, 2, 29}, + {0x06, 2, 29}, + {0x0a, 2, 29}, + {0x0f, 2, 29}, + {0x18, 2, 29}, + {0x1f, 2, 29}, + {0x29, 2, 29}, + {0x38, 3, 29}, }, /* 249 */ { - {0x8003, 30}, - {0x8006, 30}, - {0x800a, 30}, - {0x800f, 30}, - {0x8018, 30}, - {0x801f, 30}, - {0x8029, 30}, - {0xc038, 30}, - {0x8003, 31}, - {0x8006, 31}, - {0x800a, 31}, - {0x800f, 31}, - {0x8018, 31}, - {0x801f, 31}, - {0x8029, 31}, - {0xc038, 31}, + {0x03, 2, 30}, + {0x06, 2, 30}, + {0x0a, 2, 30}, + {0x0f, 2, 30}, + {0x18, 2, 30}, + {0x1f, 2, 30}, + {0x29, 2, 30}, + {0x38, 3, 30}, + {0x03, 2, 31}, + {0x06, 2, 31}, + {0x0a, 2, 31}, + {0x0f, 2, 31}, + {0x18, 2, 31}, + {0x1f, 2, 31}, + {0x29, 2, 31}, + {0x38, 3, 31}, }, /* 250 */ { - {0x8002, 127}, - {0x8009, 127}, - {0x8017, 127}, - {0xc028, 127}, - {0x8002, 220}, - {0x8009, 220}, - {0x8017, 220}, - {0xc028, 220}, - {0x8002, 249}, - {0x8009, 249}, - {0x8017, 249}, - {0xc028, 249}, - {0xc000, 10}, - {0xc000, 13}, - {0xc000, 22}, - {0x100, 0}, + {0x02, 2, 127}, + {0x09, 2, 127}, + {0x17, 2, 127}, + {0x28, 3, 127}, + {0x02, 2, 220}, + {0x09, 2, 220}, + {0x17, 2, 220}, + {0x28, 3, 220}, + {0x02, 2, 249}, + {0x09, 2, 249}, + {0x17, 2, 249}, + {0x28, 3, 249}, + {0x00, 3, 10}, + {0x00, 3, 13}, + {0x00, 3, 22}, + {0x100, 0, 0}, }, /* 251 */ { - {0x8003, 127}, - {0x8006, 127}, - {0x800a, 127}, - {0x800f, 127}, - {0x8018, 127}, - {0x801f, 127}, - {0x8029, 127}, - {0xc038, 127}, - {0x8003, 220}, - {0x8006, 220}, - {0x800a, 220}, - {0x800f, 220}, - {0x8018, 220}, - {0x801f, 220}, - {0x8029, 220}, - {0xc038, 220}, + {0x03, 2, 127}, + {0x06, 2, 127}, + {0x0a, 2, 127}, + {0x0f, 2, 127}, + {0x18, 2, 127}, + {0x1f, 2, 127}, + {0x29, 2, 127}, + {0x38, 3, 127}, + {0x03, 2, 220}, + {0x06, 2, 220}, + {0x0a, 2, 220}, + {0x0f, 2, 220}, + {0x18, 2, 220}, + {0x1f, 2, 220}, + {0x29, 2, 220}, + {0x38, 3, 220}, }, /* 252 */ { - {0x8003, 249}, - {0x8006, 249}, - {0x800a, 249}, - {0x800f, 249}, - {0x8018, 249}, - {0x801f, 249}, - {0x8029, 249}, - {0xc038, 249}, - {0x8001, 10}, - {0xc016, 10}, - {0x8001, 13}, - {0xc016, 13}, - {0x8001, 22}, - {0xc016, 22}, - {0x100, 0}, - {0x100, 0}, + {0x03, 2, 249}, + {0x06, 2, 249}, + {0x0a, 2, 249}, + {0x0f, 2, 249}, + {0x18, 2, 249}, + {0x1f, 2, 249}, + {0x29, 2, 249}, + {0x38, 3, 249}, + {0x01, 2, 10}, + {0x16, 3, 10}, + {0x01, 2, 13}, + {0x16, 3, 13}, + {0x01, 2, 22}, + {0x16, 3, 22}, + {0x100, 0, 0}, + {0x100, 0, 0}, }, /* 253 */ { - {0x8002, 10}, - {0x8009, 10}, - {0x8017, 10}, - {0xc028, 10}, - {0x8002, 13}, - {0x8009, 13}, - {0x8017, 13}, - {0xc028, 13}, - {0x8002, 22}, - {0x8009, 22}, - {0x8017, 22}, - {0xc028, 22}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, + {0x02, 2, 10}, + {0x09, 2, 10}, + {0x17, 2, 10}, + {0x28, 3, 10}, + {0x02, 2, 13}, + {0x09, 2, 13}, + {0x17, 2, 13}, + {0x28, 3, 13}, + {0x02, 2, 22}, + {0x09, 2, 22}, + {0x17, 2, 22}, + {0x28, 3, 22}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, }, /* 254 */ { - {0x8003, 10}, - {0x8006, 10}, - {0x800a, 10}, - {0x800f, 10}, - {0x8018, 10}, - {0x801f, 10}, - {0x8029, 10}, - {0xc038, 10}, - {0x8003, 13}, - {0x8006, 13}, - {0x800a, 13}, - {0x800f, 13}, - {0x8018, 13}, - {0x801f, 13}, - {0x8029, 13}, - {0xc038, 13}, + {0x03, 2, 10}, + {0x06, 2, 10}, + {0x0a, 2, 10}, + {0x0f, 2, 10}, + {0x18, 2, 10}, + {0x1f, 2, 10}, + {0x29, 2, 10}, + {0x38, 3, 10}, + {0x03, 2, 13}, + {0x06, 2, 13}, + {0x0a, 2, 13}, + {0x0f, 2, 13}, + {0x18, 2, 13}, + {0x1f, 2, 13}, + {0x29, 2, 13}, + {0x38, 3, 13}, }, /* 255 */ { - {0x8003, 22}, - {0x8006, 22}, - {0x800a, 22}, - {0x800f, 22}, - {0x8018, 22}, - {0x801f, 22}, - {0x8029, 22}, - {0xc038, 22}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, + {0x03, 2, 22}, + {0x06, 2, 22}, + {0x0a, 2, 22}, + {0x0f, 2, 22}, + {0x18, 2, 22}, + {0x1f, 2, 22}, + {0x29, 2, 22}, + {0x38, 3, 22}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, }, /* 256 */ { - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, - {0x100, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, + {0x100, 0, 0}, }, }; diff --git a/deps/nghttp2/lib/nghttp2_helper.h b/deps/nghttp2/lib/nghttp2_helper.h index 7d64076140ce88..5fde72e370f42b 100644 --- a/deps/nghttp2/lib/nghttp2_helper.h +++ b/deps/nghttp2/lib/nghttp2_helper.h @@ -61,7 +61,15 @@ nghttp2_min_def(uint32, uint32_t) nghttp2_min_def(uint64, uint64_t) nghttp2_min_def(size, size_t) -#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0) +/* + * nghttp2_strlen_lit returns the length of string literal |S|. This + * macro assumes |S| is NULL-terminated string literal. It must not + * be used with pointers. + */ +#define nghttp2_strlen_lit(S) (sizeof(S) - 1) + +#define lstreq(A, B, N) \ + (nghttp2_strlen_lit((A)) == (N) && memcmp((A), (B), (N)) == 0) #define nghttp2_struct_of(ptr, type, member) \ ((type *)(void *)((char *)(ptr) - offsetof(type, member))) diff --git a/deps/nghttp2/lib/nghttp2_http.c b/deps/nghttp2/lib/nghttp2_http.c index 60a0b01e66c1c8..a09005e807877a 100644 --- a/deps/nghttp2/lib/nghttp2_http.c +++ b/deps/nghttp2/lib/nghttp2_http.c @@ -49,7 +49,8 @@ static int memieq(const void *a, const void *b, size_t n) { return 1; } -#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N))) +#define lstrieq(A, B, N) \ + (nghttp2_strlen_lit((A)) == (N) && memieq((A), (B), (N))) static int64_t parse_uint(const uint8_t *s, size_t len) { int64_t n = 0; diff --git a/deps/nghttp2/lib/nghttp2_int.h b/deps/nghttp2/lib/nghttp2_int.h index 4e3b26860daf07..2ac6fdac441498 100644 --- a/deps/nghttp2/lib/nghttp2_int.h +++ b/deps/nghttp2/lib/nghttp2_int.h @@ -39,7 +39,6 @@ typedef int (*nghttp2_less)(const void *lhs, const void *rhs); /* Internal error code. They must be in the range [-499, -100], inclusive. */ typedef enum { - NGHTTP2_ERR_CREDENTIAL_PENDING = -101, NGHTTP2_ERR_IGN_HEADER_BLOCK = -103, NGHTTP2_ERR_IGN_PAYLOAD = -104, /* @@ -52,7 +51,11 @@ typedef enum { * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke * nghttp2_on_invalid_header_callback. */ - NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106 + NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106, + /* + * Cancel pushed stream. + */ + NGHTTP2_ERR_PUSH_CANCEL = -107, } nghttp2_internal_error; #endif /* !defined(NGHTTP2_INT_H) */ diff --git a/deps/nghttp2/lib/nghttp2_map.c b/deps/nghttp2/lib/nghttp2_map.c index f89f310319a1a3..3b703a029328c8 100644 --- a/deps/nghttp2/lib/nghttp2_map.c +++ b/deps/nghttp2/lib/nghttp2_map.c @@ -33,12 +33,11 @@ #define NGHTTP2_INITIAL_HASHBITS 4 -void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem) { - map->mem = mem; - map->hashbits = 0; - map->table = NULL; - map->seed = seed; - map->size = 0; +void nghttp2_map_init(nghttp2_map *map, uint64_t seed, nghttp2_mem *mem) { + *map = (nghttp2_map){ + .mem = mem, + .seed = seed, + }; } void nghttp2_map_free(nghttp2_map *map) { @@ -46,30 +45,27 @@ void nghttp2_map_free(nghttp2_map *map) { return; } - nghttp2_mem_free(map->mem, map->table); + nghttp2_mem_free(map->mem, map->keys); } int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr), void *ptr) { int rv; size_t i; - nghttp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return 0; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = func(bkt->data, ptr); + rv = func(map->data[i], ptr); if (rv != 0) { return rv; } @@ -78,175 +74,230 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr), return 0; } -static size_t map_hash(const nghttp2_map *map, nghttp2_map_key_type key) { - /* hasher from - https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs - We do not perform finalization here because we use top bits - anyway. */ - uint32_t h = ((uint32_t)key + map->seed) * 0x93d765dd; - return (size_t)((h * 2654435769u) >> (32 - map->hashbits)); -} +/* Hasher from + https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs + to maximize the output's sensitivity to all input bits. */ +#define NGHTTP2_MAP_HASHER 0xf1357aea2e62a9c5ull +/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get + the high bits with the good distribution. */ +#define NGHTTP2_MAP_FIBO 0x9e3779b97f4a7c15ull -static void map_bucket_swap(nghttp2_map_bucket *a, nghttp2_map_bucket *b) { - nghttp2_map_bucket c = *a; +static size_t map_index(const nghttp2_map *map, nghttp2_map_key_type key32) { + uint64_t key = (uint64_t)key32; - *a = *b; - *b = c; + key += map->seed; + key *= NGHTTP2_MAP_HASHER; + return (size_t)((key * NGHTTP2_MAP_FIBO) >> (64 - map->hashbits)); } #ifndef WIN32 void nghttp2_map_print_distance(const nghttp2_map *map) { size_t i; size_t idx; - nghttp2_map_bucket *bkt; size_t tablelen; if (map->size == 0) { return; } - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - - if (bkt->data == NULL) { + if (map->psl[i] == 0) { fprintf(stderr, "@%zu \n", i); continue; } - idx = map_hash(map, bkt->key); - fprintf(stderr, "@%zu hash=%zu key=%d base=%zu distance=%u\n", i, - map_hash(map, bkt->key), bkt->key, idx, bkt->psl); + idx = map_index(map, map->keys[i]); + fprintf(stderr, "@%zu key=%d base=%zu distance=%u\n", i, map->keys[i], idx, + map->psl[i] - 1); } } #endif /* !defined(WIN32) */ -static int map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) { - size_t idx = map_hash(map, key); - nghttp2_map_bucket b = { - .key = key, - .data = data, - }; - nghttp2_map_bucket *bkt; - size_t mask = (1u << map->hashbits) - 1; +static void map_set_entry(nghttp2_map *map, size_t idx, + nghttp2_map_key_type key, void *data, size_t psl) { + map->keys[idx] = key; + map->data[idx] = data; + map->psl[idx] = (uint8_t)psl; +} + +#define NGHTTP2_SWAP(TYPE, A, B) \ + do { \ + TYPE t = (TYPE) * (A); \ + \ + *(A) = *(B); \ + *(B) = t; \ + } while (0) + +/* + * map_insert inserts |key| and |data| to |map|, and returns the index + * where the pair is stored if it succeeds. Otherwise, it returns one + * of the following negative error codes: + * + * NGHTTP2_ERR_INVALID_ARGUMENT + * The another data associated to |key| is already present. + */ +static nghttp2_ssize map_insert(nghttp2_map *map, nghttp2_map_key_type key, + void *data) { + size_t idx = map_index(map, key); + size_t mask = ((size_t)1 << map->hashbits) - 1; + size_t psl = 1; + size_t kpsl; for (;;) { - bkt = &map->table[idx]; + kpsl = map->psl[idx]; - if (bkt->data == NULL) { - *bkt = b; + if (kpsl == 0) { + map_set_entry(map, idx, key, data, psl); ++map->size; - return 0; + + return (nghttp2_ssize)idx; } - if (b.psl > bkt->psl) { - map_bucket_swap(bkt, &b); - } else if (bkt->key == key) { - /* TODO This check is just a waste after first swap or if this - function is called from map_resize. That said, there is no - difference with or without this conditional in performance - wise. */ + if (psl > kpsl) { + NGHTTP2_SWAP(nghttp2_map_key_type, &key, &map->keys[idx]); + NGHTTP2_SWAP(void *, &data, &map->data[idx]); + NGHTTP2_SWAP(uint8_t, &psl, &map->psl[idx]); + } else if (map->keys[idx] == key) { + /* This check ensures that no duplicate keys are inserted. But + it is just a waste after first swap or if this function is + called from map_resize. That said, there is no difference + with or without this conditional in performance wise. */ return NGHTTP2_ERR_INVALID_ARGUMENT; } - ++b.psl; + ++psl; idx = (idx + 1) & mask; } } +/* NGHTTP2_MAP_MAX_HASHBITS is the maximum number of bits used for + hash table. The theoretical limit of the maximum number of keys + that can be stored is 1 << NGHTTP2_MAP_MAX_HASHBITS. */ +#define NGHTTP2_MAP_MAX_HASHBITS (sizeof(size_t) * 8 - 1) + static int map_resize(nghttp2_map *map, size_t new_hashbits) { size_t i; - nghttp2_map_bucket *bkt; size_t tablelen; - int rv; + nghttp2_ssize idx; nghttp2_map new_map = { - .table = nghttp2_mem_calloc(map->mem, 1u << new_hashbits, - sizeof(nghttp2_map_bucket)), .mem = map->mem, .seed = map->seed, .hashbits = new_hashbits, }; - (void)rv; + void *buf; + (void)idx; + + if (new_hashbits > NGHTTP2_MAP_MAX_HASHBITS) { + return NGHTTP2_ERR_NOMEM; + } - if (new_map.table == NULL) { + tablelen = (size_t)1 << new_hashbits; + + buf = nghttp2_mem_calloc(map->mem, tablelen, + sizeof(nghttp2_map_key_type) + sizeof(void *) + + sizeof(uint8_t)); + if (buf == NULL) { return NGHTTP2_ERR_NOMEM; } + new_map.keys = buf; + new_map.data = + (void *)((uint8_t *)new_map.keys + tablelen * sizeof(nghttp2_map_key_type)); + new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *); + if (map->size) { - tablelen = 1u << map->hashbits; + tablelen = (size_t)1 << map->hashbits; for (i = 0; i < tablelen; ++i) { - bkt = &map->table[i]; - if (bkt->data == NULL) { + if (map->psl[i] == 0) { continue; } - rv = map_insert(&new_map, bkt->key, bkt->data); + idx = map_insert(&new_map, map->keys[i], map->data[i]); - assert(0 == rv); + /* map_insert must not fail because all keys are unique during + resize. */ + assert(idx >= 0); } } - nghttp2_mem_free(map->mem, map->table); - map->table = new_map.table; + nghttp2_mem_free(map->mem, map->keys); + map->keys = new_map.keys; + map->data = new_map.data; + map->psl = new_map.psl; map->hashbits = new_hashbits; return 0; } +/* NGHTTP2_MAX_PSL_RESIZE_THRESH is the maximum psl threshold. If + reached, resize the table. */ +#define NGHTTP2_MAX_PSL_RESIZE_THRESH 128 + int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) { int rv; + size_t tablelen; + nghttp2_ssize idx; assert(data); - /* Load factor is 7/8 */ - /* Under the very initial condition, that is map->size == 0 and - map->hashbits == 0, 8 > 7 still holds nicely. */ - if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) { - if (map->hashbits) { - rv = map_resize(map, map->hashbits + 1); - if (rv != 0) { - return rv; - } - } else { - rv = map_resize(map, NGHTTP2_INITIAL_HASHBITS); - if (rv != 0) { - return rv; - } + /* tablelen is incorrect if map->hashbits == 0 which leads to + tablelen = 1, but it is only used to check the load factor, and + it works in this special case. */ + tablelen = (size_t)1 << map->hashbits; + + /* Load factor is 7 / 8. Because tablelen is power of 2, (tablelen + - (tablelen >> 3)) computes tablelen * 7 / 8. */ + if (map->size + 1 >= (tablelen - (tablelen >> 3))) { + rv = map_resize(map, map->hashbits ? map->hashbits + 1 + : NGHTTP2_INITIAL_HASHBITS); + if (rv != 0) { + return rv; + } + + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; } + + return 0; } - rv = map_insert(map, key, data); - if (rv != 0) { - return rv; + idx = map_insert(map, key, data); + if (idx < 0) { + return (int)idx; } - return 0; + /* Resize if psl reaches really large value which is almost + improbable, but just in case. */ + if (map->psl[idx] - 1 < NGHTTP2_MAX_PSL_RESIZE_THRESH) { + return 0; + } + + return map_resize(map, map->hashbits + 1); } void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) { size_t idx; - nghttp2_map_bucket *bkt; - size_t psl = 0; + size_t psl = 1; size_t mask; if (map->size == 0) { return NULL; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NULL; } - if (bkt->key == key) { - return bkt->data; + if (map->keys[idx] == key) { + return map->data[idx]; } ++psl; @@ -256,38 +307,36 @@ void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) { int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) { size_t idx; - nghttp2_map_bucket *b, *bkt; - size_t psl = 0; + size_t dest; + size_t psl = 1, kpsl; size_t mask; if (map->size == 0) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - idx = map_hash(map, key); - mask = (1u << map->hashbits) - 1; + idx = map_index(map, key); + mask = ((size_t)1 << map->hashbits) - 1; for (;;) { - bkt = &map->table[idx]; - - if (bkt->data == NULL || psl > bkt->psl) { + if (psl > map->psl[idx]) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - if (bkt->key == key) { - b = bkt; + if (map->keys[idx] == key) { + dest = idx; idx = (idx + 1) & mask; for (;;) { - bkt = &map->table[idx]; - if (bkt->data == NULL || bkt->psl == 0) { - b->data = NULL; + kpsl = map->psl[idx]; + if (kpsl <= 1) { + map->psl[dest] = 0; break; } - --bkt->psl; - *b = *bkt; - b = bkt; + map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1); + + dest = idx; idx = (idx + 1) & mask; } @@ -307,7 +356,7 @@ void nghttp2_map_clear(nghttp2_map *map) { return; } - memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits)); + memset(map->psl, 0, sizeof(*map->psl) * ((size_t)1 << map->hashbits)); map->size = 0; } diff --git a/deps/nghttp2/lib/nghttp2_map.h b/deps/nghttp2/lib/nghttp2_map.h index e45685bce71768..c47b279345dee3 100644 --- a/deps/nghttp2/lib/nghttp2_map.h +++ b/deps/nghttp2/lib/nghttp2_map.h @@ -38,16 +38,15 @@ typedef int32_t nghttp2_map_key_type; -typedef struct nghttp2_map_bucket { - uint32_t psl; - nghttp2_map_key_type key; - void *data; -} nghttp2_map_bucket; - typedef struct nghttp2_map { - nghttp2_map_bucket *table; + nghttp2_map_key_type *keys; + void **data; + /* psl is the Probe Sequence Length. 0 has special meaning that the + element is not stored at i-th position if psl[i] == 0. Because + of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */ + uint8_t *psl; nghttp2_mem *mem; - uint32_t seed; + uint64_t seed; size_t size; size_t hashbits; } nghttp2_map; @@ -55,7 +54,7 @@ typedef struct nghttp2_map { /* * nghttp2_map_init initializes the map |map|. */ -void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem); +void nghttp2_map_init(nghttp2_map *map, uint64_t seed, nghttp2_mem *mem); /* * nghttp2_map_free deallocates any resources allocated for |map|. diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.c b/deps/nghttp2/lib/nghttp2_outbound_item.c index a9e9f7693eda8c..fad1ee0a469086 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.c +++ b/deps/nghttp2/lib/nghttp2_outbound_item.c @@ -53,6 +53,18 @@ nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, return dpw; } +int nghttp2_data_provider_wrap_contains_read_callback( + const nghttp2_data_provider_wrap *dpw) { + switch (dpw->version) { + case NGHTTP2_DATA_PROVIDER_V1: + return dpw->data_prd.v1.read_callback != NULL; + case NGHTTP2_DATA_PROVIDER_V2: + return dpw->data_prd.v2.read_callback != NULL; + default: + return 0; + } +} + void nghttp2_outbound_item_init(nghttp2_outbound_item *item) { item->cycle = 0; item->qnext = NULL; diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.h b/deps/nghttp2/lib/nghttp2_outbound_item.h index 6e8e310cc475dd..9f280e616351d0 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.h +++ b/deps/nghttp2/lib/nghttp2_outbound_item.h @@ -39,10 +39,6 @@ typedef struct nghttp2_data_provider_wrap { int version; union { - struct { - nghttp2_data_source source; - void *read_callback; - }; nghttp2_data_provider v1; nghttp2_data_provider2 v2; } data_prd; @@ -56,6 +52,11 @@ nghttp2_data_provider_wrap * nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, const nghttp2_data_provider2 *data_prd); +/* nghttp2_data_provider_wrap_contains_read_callback returns nonzero + if |dpw| contains read_callback in either version. */ +int nghttp2_data_provider_wrap_contains_read_callback( + const nghttp2_data_provider_wrap *dpw); + /* struct used for HEADERS and PUSH_PROMISE frame */ typedef struct { nghttp2_data_provider_wrap dpw; @@ -110,6 +111,12 @@ typedef struct { uint8_t flags; } nghttp2_goaway_aux_data; +typedef struct { + /* nonzero if RST_STREAM should be sent even if stream is not + found. */ + uint8_t continue_without_stream; +} nghttp2_rst_stream_aux_data; + /* struct used for extension frame */ typedef struct { /* nonzero if this extension frame is serialized by library @@ -122,6 +129,7 @@ typedef union { nghttp2_data_aux_data data; nghttp2_headers_aux_data headers; nghttp2_goaway_aux_data goaway; + nghttp2_rst_stream_aux_data rst_stream; nghttp2_ext_aux_data ext; } nghttp2_aux_data; diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index 97d7fda1d295d5..19e0b767c1639b 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -438,7 +438,7 @@ static int session_new(nghttp2_session **session_ptr, size_t max_deflate_dynamic_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; size_t i; - uint32_t map_seed; + uint64_t map_seed; if (mem == NULL) { mem = nghttp2_mem_default(); @@ -1051,7 +1051,6 @@ int nghttp2_session_add_item(nghttp2_session *session, nghttp2_outbound_queue_push(&session->ob_syn, item); item->queued = 1; return 0; - ; } nghttp2_outbound_queue_push(&session->ob_reg, item); @@ -1189,6 +1188,10 @@ int nghttp2_session_add_rst_stream_continue(nghttp2_session *session, frame = &item->frame; nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code); + + item->aux_data.rst_stream.continue_without_stream = + (uint8_t)(continue_without_stream != 0); + rv = nghttp2_session_add_item(session, item); if (rv != 0) { nghttp2_frame_rst_stream_free(&frame->rst_stream); @@ -2141,6 +2144,12 @@ static int session_prep_frame(nghttp2_session *session, if (session_is_closing(session)) { return NGHTTP2_ERR_SESSION_CLOSING; } + + if (!item->aux_data.rst_stream.continue_without_stream && + !nghttp2_session_get_stream(session, frame->rst_stream.hd.stream_id)) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + nghttp2_frame_pack_rst_stream(&session->aob.framebufs, &frame->rst_stream); return 0; case NGHTTP2_SETTINGS: { @@ -2584,7 +2593,7 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->dpw.data_prd.read_callback) { + if (nghttp2_data_provider_wrap_contains_read_callback(&aux_data->dpw)) { /* nghttp2_submit_data_shared() makes a copy of aux_data->dpw */ rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, @@ -2615,7 +2624,7 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->dpw.data_prd.read_callback) { + if (nghttp2_data_provider_wrap_contains_read_callback(&aux_data->dpw)) { rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, frame->hd.stream_id, &aux_data->dpw); if (nghttp2_is_fatal(rv)) { @@ -2795,7 +2804,10 @@ static int session_call_send_data(nghttp2_session *session, aux_data = &item->aux_data.data; rv = session->callbacks.send_data_callback(session, frame, buf->pos, length, - &aux_data->dpw.data_prd.source, + /* This is fine because + of Common Initial + Sequence rule. */ + &aux_data->dpw.data_prd.v2.source, session->user_data); switch (rv) { @@ -2853,8 +2865,12 @@ static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session, nghttp2_frame *frame = &item->frame; /* The library is responsible for the transmission of WINDOW_UPDATE frame, so we don't call error callback for - it. */ + it. As for RST_STREAM, if it is not sent due to missing + stream, we also do not call error callback because it may + cause a lot of noises.*/ if (frame->hd.type != NGHTTP2_WINDOW_UPDATE && + (frame->hd.type != NGHTTP2_RST_STREAM || + rv != NGHTTP2_ERR_STREAM_CLOSED) && session->callbacks.on_frame_not_send_callback( session, frame, rv, session->user_data) != 0) { nghttp2_outbound_item_free(item, mem); @@ -3272,7 +3288,9 @@ static int session_call_on_invalid_header(nghttp2_session *session, session, frame, nv->name->base, nv->name->len, nv->value->base, nv->value->len, nv->flags, session->user_data); } else { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + /* If both callbacks are not set, the invalid field nv is + ignored. */ + return 0; } if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -3357,6 +3375,10 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_MESSAGING: return NGHTTP2_PROTOCOL_ERROR; + case NGHTTP2_ERR_INTERNAL: + return NGHTTP2_INTERNAL_ERROR; + case NGHTTP2_ERR_PUSH_CANCEL: + return NGHTTP2_CANCEL; default: return NGHTTP2_INTERNAL_ERROR; } @@ -3408,7 +3430,7 @@ static int session_handle_invalid_stream2(nghttp2_session *session, if (rv != 0) { return rv; } - if (session->callbacks.on_invalid_frame_recv_callback) { + if (frame && session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( session, frame, lib_error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3495,6 +3517,7 @@ static int session_inflate_handle_invalid_connection(nghttp2_session *session, static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, size_t *readlen_ptr, uint8_t *in, size_t inlen, int final, int call_header_cb) { + nghttp2_inbound_frame *iframe = &session->iframe; nghttp2_ssize proclen; int rv; int inflate_flags; @@ -3563,7 +3586,29 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, rv2 = session_call_on_invalid_header(session, frame, &nv); if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = NGHTTP2_ERR_HTTP_HEADER; + DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + rv = session_call_error_callback( + session, NGHTTP2_ERR_HTTP_HEADER, + "Invalid HTTP header field was received: frame type: " + "%u, stream: %d, name: [%.*s], value: [%.*s]", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = session_handle_invalid_stream2( + session, subject_stream->stream_id, frame, + NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } else { if (rv2 != 0) { return rv2; @@ -3609,6 +3654,16 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, if (nghttp2_is_fatal(rv)) { return rv; } + + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return 0; + } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } } @@ -3678,6 +3733,7 @@ static int session_end_stream_headers_received(nghttp2_session *session, static int session_after_header_block_received(nghttp2_session *session) { int rv = 0; nghttp2_frame *frame = &session->iframe.frame; + nghttp2_inbound_frame *iframe = &session->iframe; nghttp2_stream *stream; /* We don't call on_frame_recv_callback if stream has been closed @@ -3736,12 +3792,22 @@ static int session_after_header_block_received(nghttp2_session *session) { return rv; } + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return 0; + } + if (frame->hd.type == NGHTTP2_HEADERS && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); /* Don't call nghttp2_session_close_stream_if_shut_rdwr because RST_STREAM has been submitted. */ } + return 0; } } @@ -4078,8 +4144,7 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } /* If window size gets positive, push deferred DATA frame to @@ -4105,6 +4170,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_remote_initial_window_size(nghttp2_session *session, @@ -4128,8 +4195,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return NGHTTP2_ERR_FLOW_CONTROL; } if (stream->window_update_queued) { @@ -4163,6 +4229,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) { * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_FLOW_CONTROL + * Window size gets out of range. */ static int session_update_local_initial_window_size(nghttp2_session *session, @@ -4549,9 +4617,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session->max_incoming_reserved_streams) { /* Currently, client does not retain closed stream, so we don't check NGHTTP2_SHUT_RD condition here. */ - - rv = nghttp2_session_add_rst_stream( - session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); + rv = session_handle_invalid_stream2(session, + frame->push_promise.promised_stream_id, + NULL, NGHTTP2_ERR_PUSH_CANCEL); if (rv != 0) { return rv; } @@ -4708,8 +4776,9 @@ static int session_on_stream_window_update_received(nghttp2_session *session, } if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < stream->remote_window_size) { - return session_handle_invalid_stream(session, frame, - NGHTTP2_ERR_FLOW_CONTROL); + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FLOW_CONTROL, + "WINDOW_UPDATE: window size overflow"); } stream->remote_window_size += frame->window_update.window_size_increment; @@ -4925,6 +4994,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session, nghttp2_frame *frame) { int rv = 0; nghttp2_stream *stream; + nghttp2_inbound_frame *iframe = &session->iframe; /* We don't call on_frame_recv_callback if stream has been closed already or being closed. */ @@ -4939,15 +5009,26 @@ int nghttp2_session_on_data_received(nghttp2_session *session, if (session_enforce_http_messaging(session) && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if (nghttp2_http_on_remote_end_stream(stream) != 0) { - rv = nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_PROTOCOL_ERROR); + rv = session_handle_invalid_stream2(session, stream->stream_id, frame, + NGHTTP2_ERR_HTTP_MESSAGING); if (nghttp2_is_fatal(rv)) { return rv; } + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return 0; + } + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + /* Don't call nghttp2_session_close_stream_if_shut_rdwr because RST_STREAM has been submitted. */ + return 0; } } @@ -5006,8 +5087,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session, rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, stream->local_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_terminate_session(session, + NGHTTP2_FLOW_CONTROL_ERROR); } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ @@ -5469,6 +5550,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, busy = 1; rv = session_on_data_received_fail_fast(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { return (nghttp2_ssize)inlen; } @@ -5476,23 +5561,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, DEBUGF("recv: DATA not allowed stream_id=%d\n", iframe->frame.hd.stream_id); - rv = session_update_glitch_ratelim(session); - if (rv != 0) { - return rv; - } - - if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (nghttp2_ssize)inlen; - } - iframe->state = NGHTTP2_IB_IGN_DATA; break; } - if (nghttp2_is_fatal(rv)) { - return rv; - } - rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); if (rv < 0) { rv = nghttp2_session_terminate_session_with_reason( @@ -5576,6 +5648,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + on_begin_frame_called = 1; rv = session_process_headers_frame(session); @@ -5590,8 +5666,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6044,6 +6120,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } } @@ -6107,8 +6187,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6191,9 +6271,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.push_promise.promised_stream_id, - NGHTTP2_INTERNAL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.push_promise.promised_stream_id, NULL, + NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6296,6 +6376,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; @@ -6371,12 +6455,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, iframe->payloadleft -= hd_proclen; /* Use promised stream ID for PUSH_PROMISE */ - rv = nghttp2_session_add_rst_stream( + rv = session_handle_invalid_stream2( session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE ? iframe->frame.push_promise.promised_stream_id : iframe->frame.hd.stream_id, - NGHTTP2_INTERNAL_ERROR); + NULL, NGHTTP2_ERR_INTERNAL); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6423,6 +6507,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } session_inbound_frame_reset(session); @@ -6598,6 +6686,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } else { iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; } @@ -6648,6 +6740,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, if (nghttp2_is_fatal(rv)) { return rv; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } } busy = 1; @@ -6720,6 +6816,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + data_readlen = inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen); @@ -6763,13 +6863,25 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, } } - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + rv = session_handle_invalid_stream2( + session, iframe->frame.hd.stream_id, &iframe->frame, + NGHTTP2_ERR_PROTO); if (nghttp2_is_fatal(rv)) { return rv; } + + rv = session_update_glitch_ratelim(session); + if (rv != 0) { + return rv; + } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + busy = 1; iframe->state = NGHTTP2_IB_IGN_DATA; + break; } } @@ -6777,13 +6889,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, rv = session->callbacks.on_data_chunk_recv_callback( session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, in - readlen, (size_t)data_readlen, session->user_data); - if (rv == NGHTTP2_ERR_PAUSE) { - return (nghttp2_ssize)(in - first); - } - if (nghttp2_is_fatal(rv)) { return NGHTTP2_ERR_CALLBACK_FAILURE; } + + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + + if (rv == NGHTTP2_ERR_PAUSE) { + return (nghttp2_ssize)(in - first); + } } } } @@ -6797,6 +6913,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; @@ -6863,6 +6983,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + if (rv != 0) { busy = 1; @@ -6881,6 +7005,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; @@ -6909,6 +7037,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, return rv; } + if (iframe->state == NGHTTP2_IB_IGN_ALL) { + return (nghttp2_ssize)inlen; + } + session_inbound_frame_reset(session); break; @@ -7372,13 +7504,13 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, case NGHTTP2_DATA_PROVIDER_V1: payloadlen = (nghttp2_ssize)aux_data->dpw.data_prd.v1.read_callback( session, frame->hd.stream_id, buf->pos, datamax, &data_flags, - &aux_data->dpw.data_prd.source, session->user_data); + &aux_data->dpw.data_prd.v1.source, session->user_data); break; case NGHTTP2_DATA_PROVIDER_V2: payloadlen = aux_data->dpw.data_prd.v2.read_callback( session, frame->hd.stream_id, buf->pos, datamax, &data_flags, - &aux_data->dpw.data_prd.source, session->user_data); + &aux_data->dpw.data_prd.v2.source, session->user_data); break; default: diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h index edbef80d397123..cab30687c075df 100644 --- a/deps/nghttp2/lib/nghttp2_session.h +++ b/deps/nghttp2/lib/nghttp2_session.h @@ -107,8 +107,8 @@ typedef struct { #define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33 /* The default values for glitch rate limiter. */ -#define NGHTTP2_DEFAULT_GLITCH_BURST 1000 -#define NGHTTP2_DEFAULT_GLITCH_RATE 33 +#define NGHTTP2_DEFAULT_GLITCH_BURST 10000 +#define NGHTTP2_DEFAULT_GLITCH_RATE 330 /* The default max number of CONTINUATION frames following an incoming HEADER frame. */ diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index 8a90f714e4a4b5..d6bcae9deaf504 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -57,7 +57,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, nghttp2_outbound_item_init(item); - if (dpw != NULL && dpw->data_prd.read_callback != NULL) { + if (dpw != NULL && nghttp2_data_provider_wrap_contains_read_callback(dpw)) { item->aux_data.headers.dpw = *dpw; } @@ -649,7 +649,7 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags, 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) { + if (dpw == NULL || !nghttp2_data_provider_wrap_contains_read_callback(dpw)) { flags |= NGHTTP2_FLAG_END_STREAM; } @@ -700,7 +700,7 @@ int32_t nghttp2_submit_request2(nghttp2_session *session, static uint8_t set_response_flags(const nghttp2_data_provider_wrap *dpw) { uint8_t flags = NGHTTP2_FLAG_NONE; - if (dpw == NULL || dpw->data_prd.read_callback == NULL) { + if (dpw == NULL || !nghttp2_data_provider_wrap_contains_read_callback(dpw)) { flags |= NGHTTP2_FLAG_END_STREAM; } return flags; From b144b308340ae38717386c83e4c35a444419427d Mon Sep 17 00:00:00 2001 From: Tim Perry Date: Wed, 22 Apr 2026 13:36:27 +0200 Subject: [PATCH 08/10] deps: fix integration issues with the latest nghttp2 This is a set of src & tests fixes for nghttp2 due to changes in v1.67.0+ which require a selection of changes to how we handle low-level protocol errors when using the latest versions of nghttp2, changing both some src error handling and updating some tests to match. Signed-off-by: Tim Perry PR-URL: https://github.com/nodejs/node/pull/62891 Reviewed-By: Luigi Pinca Reviewed-By: Stephen Belanger Reviewed-By: Antoine du Hamel (cherry picked from commit 4a32c00fb8dbe55c3bcf9ef43343968c9fe449e6) --- src/node_http2.cc | 31 +++++++ src/node_http2.h | 2 + ...t-http2-misbehaving-flow-control-paused.js | 33 ++++--- .../test-http2-misbehaving-flow-control.js | 33 ++++--- ...tp2-options-max-headers-exceeds-nghttp2.js | 12 ++- ...http2-session-cleanup-on-nghttp2-goaway.js | 91 +++++++++++++++++++ 6 files changed, 176 insertions(+), 26 deletions(-) create mode 100644 test/parallel/test-http2-session-cleanup-on-nghttp2-goaway.js diff --git a/src/node_http2.cc b/src/node_http2.cc index 65995d12ffeae7..403d9982ebde5a 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1270,6 +1270,24 @@ int Http2Session::OnFrameSent(nghttp2_session* handle, void* user_data) { Http2Session* session = static_cast(user_data); session->statistics_.frame_sent += 1; + + // If nghttp2 has internally terminated the session (e.g. due to a protocol + // error like oversized frames, padding errors, or HPACK compression + // failures), it calls nghttp2_session_terminate_session() directly which + // queues a GOAWAY but does not invoke any application-level callback. + // Detect that case here: a GOAWAY was sent but we never initiated it + // (no Close(), no session.close(), no session.goaway()). + // + // We set a flag here, and then throw the error at the end of + // SendPendingData, to wait until the GOAWAY is written before the session + // is torn down. + if (frame->hd.type == NGHTTP2_GOAWAY && !session->is_closing() && + !session->is_destroyed() && !session->IsGracefulCloseInitiated() && + !session->goaway_initiated_) { + Debug(session, "nghttp2 session terminated internally"); + session->internal_goaway_sent_ = true; + } + return 0; } @@ -2004,6 +2022,18 @@ uint8_t Http2Session::SendPendingData() { MaybeStopReading(); + // If nghttp2 has internally torn down the session (detected in OnFrameSent) + // during the nghttp2_session_mem_send loop above, at this point we error: + if (internal_goaway_sent_) { + internal_goaway_sent_ = false; + if (!is_closing() && !is_destroyed()) { + Isolate* isolate = env()->isolate(); + HandleScope scope(isolate); + Local arg = Integer::New(isolate, NGHTTP2_ERR_PROTO); + MakeCallback(env()->http2session_on_error_function(), 1, &arg); + } + } + return 0; } @@ -2944,6 +2974,7 @@ void Http2Session::Goaway(uint32_t code, if (is_destroyed()) return; + goaway_initiated_ = true; Http2Scope h2scope(this); // the last proc stream id is the most recently created Http2Stream. if (lastStreamID <= 0) diff --git a/src/node_http2.h b/src/node_http2.h index a60a7ba029db3e..91046052927598 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -968,6 +968,8 @@ class Http2Session : public AsyncWrap, // Flag to indicate that JavaScript has initiated a graceful closure bool graceful_close_initiated_ = false; + bool goaway_initiated_ = false; + bool internal_goaway_sent_ = false; }; struct Http2SessionPerformanceEntryTraits { diff --git a/test/parallel/test-http2-misbehaving-flow-control-paused.js b/test/parallel/test-http2-misbehaving-flow-control-paused.js index e54bb83238e7fa..b9a0d5cb81ecd5 100644 --- a/test/parallel/test-http2-misbehaving-flow-control-paused.js +++ b/test/parallel/test-http2-misbehaving-flow-control-paused.js @@ -47,36 +47,45 @@ const data = Buffer.from([ // Bad client! Bad! // // Fortunately, nghttp2 handles this situation for us by keeping track -// of the flow control window and responding with a FLOW_CONTROL_ERROR -// causing the stream to get shut down... -// -// At least, that's what is supposed to happen. +// of the flow control window and sending GOAWAY to end the session. let client; const server = h2.createServer({ settings: { initialWindowSize: 36 } }); -server.on('stream', (stream) => { + +server.on('session', common.mustCall((session) => { + session.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + name: 'Error', + message: 'Protocol error' + })); +})); + +server.on('stream', common.mustCall((stream) => { // Set the high water mark to zero, since otherwise we still accept // reads from the source stream (if we can consume them). stream._readableState.highWaterMark = 0; stream.pause(); stream.on('error', common.expectsError({ - code: 'ERR_HTTP2_STREAM_ERROR', + code: 'ERR_HTTP2_ERROR', name: 'Error', - message: 'Stream closed with error code NGHTTP2_FLOW_CONTROL_ERROR' + message: 'Protocol error' })); stream.on('close', common.mustCall(() => { server.close(); client.destroy(); })); stream.on('end', common.mustNotCall()); -}); +})); -server.listen(0, () => { - client = net.connect(server.address().port, () => { +server.listen(0, common.mustCall(() => { + client = net.connect(server.address().port, common.mustCall(() => { client.write(preamble); client.write(data); client.write(data); client.write(data); - }); -}); + + // TCP connection is closed by the server + client.on('close', common.mustCall()); + })); +})); diff --git a/test/parallel/test-http2-misbehaving-flow-control.js b/test/parallel/test-http2-misbehaving-flow-control.js index 6774be2237b109..fb0f7a1e0f9aff 100644 --- a/test/parallel/test-http2-misbehaving-flow-control.js +++ b/test/parallel/test-http2-misbehaving-flow-control.js @@ -58,18 +58,24 @@ const data = Buffer.from([ // Bad client! Bad! // // Fortunately, nghttp2 handles this situation for us by keeping track -// of the flow control window and responding with a FLOW_CONTROL_ERROR -// causing the stream to get shut down... -// -// At least, that's what is supposed to happen. +// of the flow control window and sending GOAWAY to end the session. let client; const server = h2.createServer({ settings: { initialWindowSize: 18 } }); -server.on('stream', (stream) => { + +server.on('session', common.mustCall((session) => { + session.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + name: 'Error', + message: 'Protocol error' + })); +})); + +server.on('stream', common.mustCall((stream) => { stream.on('error', common.expectsError({ - code: 'ERR_HTTP2_STREAM_ERROR', + code: 'ERR_HTTP2_ERROR', name: 'Error', - message: 'Stream closed with error code NGHTTP2_FLOW_CONTROL_ERROR' + message: 'Protocol error' })); stream.on('close', common.mustCall(() => { server.close(common.mustCall()); @@ -78,14 +84,17 @@ server.on('stream', (stream) => { stream.resume(); stream.respond(); stream.end('ok'); -}); +})); server.on('close', common.mustCall()); -server.listen(0, () => { - client = net.connect(server.address().port, () => { +server.listen(0, common.mustCall(() => { + client = net.connect(server.address().port, common.mustCall(() => { client.write(preamble); client.write(data); client.write(data); - }); -}); + + // TCP connection is closed by the server + client.on('close', common.mustCall()); + })); +})); diff --git a/test/parallel/test-http2-options-max-headers-exceeds-nghttp2.js b/test/parallel/test-http2-options-max-headers-exceeds-nghttp2.js index 7767dbbc503814..46f560f96c27e8 100644 --- a/test/parallel/test-http2-options-max-headers-exceeds-nghttp2.js +++ b/test/parallel/test-http2-options-max-headers-exceeds-nghttp2.js @@ -90,11 +90,19 @@ server.listen(0, common.mustCall(() => { 0, common.mustCall(() => { const client = h2.connect(`http://localhost:${server.address().port}`); - client.on('error', common.mustNotCall()); + // The server sends oversized headers that cause a compression error on + // the client side, so nghttp2 internally terminates the client session. + client.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + name: 'Error', + })); const req = client.request(); req.on('response', common.mustNotCall()); - req.on('error', common.mustNotCall()); + req.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + name: 'Error', + })); req.end(); }), ); diff --git a/test/parallel/test-http2-session-cleanup-on-nghttp2-goaway.js b/test/parallel/test-http2-session-cleanup-on-nghttp2-goaway.js new file mode 100644 index 00000000000000..f3576f9f59bcbf --- /dev/null +++ b/test/parallel/test-http2-session-cleanup-on-nghttp2-goaway.js @@ -0,0 +1,91 @@ +'use strict'; + +const common = require('../common'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const http2 = require('http2'); +const net = require('net'); + +// When nghttp2 internally sends a GOAWAY frame due to a protocol error, it +// may call nghttp2_session_terminate_session() directly, bypassing the +// on_invalid_frame_recv_callback entirely. This test ensures that even +// in that scenario, we still correctly clean up the session & connection. +// +// This test reproduces this with a client who sends a frame header with +// a length exceeding the default max_frame_size (16384). nghttp2 responds +// with GOAWAY(FRAME_SIZE_ERROR) without notifying Node through any callback. + +const server = http2.createServer(); + +server.on('session', common.mustCall((session) => { + session.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + name: 'Error', + message: 'Protocol error' + })); + + session.on('close', common.mustCall(() => server.close())); +})); + +server.listen(0, common.mustCall(() => { + const conn = net.connect({ + port: server.address().port, + allowHalfOpen: true, + }); + + // HTTP/2 client connection preface. + conn.write('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'); + + // Empty SETTINGS frame. + const settingsFrame = Buffer.alloc(9); + settingsFrame[3] = 0x04; // type: SETTINGS + conn.write(settingsFrame); + + let inbuf = Buffer.alloc(0); + let state = 'settingsHeader'; + let settingsFrameLength; + + conn.on('data', (chunk) => { + inbuf = Buffer.concat([inbuf, chunk]); + + switch (state) { + case 'settingsHeader': + if (inbuf.length < 9) return; + settingsFrameLength = inbuf.readUIntBE(0, 3); + inbuf = inbuf.slice(9); + state = 'readingSettings'; + // Fallthrough + case 'readingSettings': { + if (inbuf.length < settingsFrameLength) return; + inbuf = inbuf.slice(settingsFrameLength); + state = 'done'; + + // ACK the server SETTINGS. + const ack = Buffer.alloc(9); + ack[3] = 0x04; // type: SETTINGS + ack[4] = 0x01; // flag: ACK + conn.write(ack); + + // Send a HEADERS frame header claiming length 16385, which exceeds + // the default max_frame_size of 16384. nghttp2 checks the length + // before reading any payload, so no body is needed. This triggers + // nghttp2_session_terminate_session(FRAME_SIZE_ERROR) directly in + // nghttp2_session_mem_recv2 — bypassing on_invalid_frame_recv_callback. + const oversized = Buffer.alloc(9); + oversized.writeUIntBE(16385, 0, 3); // length: 16385 (one over max) + oversized[3] = 0x01; // type: HEADERS + oversized[4] = 0x04; // flags: END_HEADERS + oversized.writeUInt32BE(1, 5); // stream id: 1 + conn.write(oversized); + + // No need to write the data - the header alone triggers the check. + } + } + }); + + // The server must close the connection after sending GOAWAY: + conn.on('end', common.mustCall(() => conn.end())); + conn.on('close', common.mustCall()); +})); From 3e417f5075e75f0e9bb45dae12c10b60487cd477 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 3 Jun 2025 11:09:40 +0200 Subject: [PATCH 09/10] http2: remove support for priority signaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matteo Collina Co-authored-by: Antoine du Hamel Refs: https://datatracker.ietf.org/doc/html/rfc9113#section-5.3.1 PR-URL: https://github.com/nodejs/node/pull/58293 Reviewed-By: James M Snell Reviewed-By: Michaël Zasso Reviewed-By: Darshan Sen Reviewed-By: Yagiz Nizipli Reviewed-By: Tim Perry Reviewed-By: Filip Skokan Reviewed-By: Michael Dawson Reviewed-By: Rafael Gonzaga Reviewed-By: Benjamin Gruenbaum (cherry picked from commit a63126409ad4334dd5d838c39806f38c020748b9) --- doc/api/deprecations.md | 8 ++- doc/api/http2.md | 41 +++++-------- lib/internal/http2/core.js | 61 ++++++------------- lib/internal/util.js | 13 ++++ ...st-http2-client-priority-before-connect.js | 5 ++ ...est-http2-client-request-options-errors.js | 1 - .../test-http2-client-set-priority.js | 8 ++- test/parallel/test-http2-priority-cycle-.js | 5 ++ test/parallel/test-http2-priority-event.js | 19 +++--- ...est-http2-server-stream-session-destroy.js | 5 ++ 10 files changed, 82 insertions(+), 84 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 3c4762597e8d49..9a6a6895efc237 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -3863,15 +3863,17 @@ an internal nodejs implementation rather than a public facing API, use `node:str -Type: Documentation-only +Type: End-of-Life -The support for priority signaling has been deprecated in the [RFC 9113][], and -will be removed in future versions of Node.js. +The support for priority signaling has been removed following its deprecation in the [RFC 9113][]. ### DEP0195: Instantiating `node:http` classes without `new` diff --git a/doc/api/http2.md b/doc/api/http2.md index 5ca4f26e38ab43..3157cd0d2652ec 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1071,6 +1071,10 @@ The `'origin'` event is only emitted when using a secure TLS connection. > Stability: 0 - Deprecated: support for priority signaling has been deprecated > in the [RFC 9113][] and is no longer supported in Node.js. -* `options` {Object} - * `exclusive` {boolean} When `true` and `parent` identifies a parent Stream, - this stream is made the sole direct dependency of the parent, with - all other existing dependents made a dependent of this stream. **Default:** - `false`. - * `parent` {number} Specifies the numeric identifier of a stream this stream - is dependent on. - * `weight` {number} Specifies the relative dependency of a stream in relation - to other streams with the same `parent`. The value is a number between `1` - and `256` (inclusive). - * `silent` {boolean} When `true`, changes the priority locally without - sending a `PRIORITY` frame to the connected peer. - -Updates the priority for this `Http2Stream` instance. +Empty method, only there to maintain some backward compatibility. #### `http2stream.rstCode` @@ -1582,6 +1574,10 @@ req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL)); -Type: Documentation-only +Type: Runtime Instantiating classes without the `new` qualifier exported by the `node:repl` module is deprecated. It is recommended to use the `new` qualifier instead. This applies to all REPL classes, including diff --git a/lib/internal/util.js b/lib/internal/util.js index 33507d52927521..03709d883bcb33 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -215,6 +215,14 @@ function deprecate(fn, msg, code, useEmitSync, modifyPrototype = true) { return deprecated; } +function deprecateInstantiation(target, code, ...args) { + assert(typeof code === 'string'); + + getDeprecationWarningEmitter(code, `Instantiating ${target.name} without the 'new' keyword has been deprecated.`, target)(); + + return ReflectConstruct(target, args); +} + function decorateErrorStack(err) { if (!(isError(err) && err.stack) || err[decorated_private_symbol]) return; diff --git a/lib/repl.js b/lib/repl.js index 30a11a167e1288..cfc9ad218e8785 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -111,6 +111,7 @@ const { decorateErrorStack, isError, deprecate, + deprecateInstantiation, SideEffectFreeRegExpPrototypeSymbolReplace, SideEffectFreeRegExpPrototypeSymbolSplit, } = require('internal/util'); @@ -264,12 +265,7 @@ function REPLServer(prompt, ignoreUndefined, replMode) { if (!(this instanceof REPLServer)) { - return new REPLServer(prompt, - stream, - eval_, - useGlobal, - ignoreUndefined, - replMode); + return deprecateInstantiation(REPLServer, 'DEP0185', prompt, stream, eval_, useGlobal, ignoreUndefined, replMode); } let options; diff --git a/test/parallel/test-repl-preview-without-inspector.js b/test/parallel/test-repl-preview-without-inspector.js index 8905d214836c64..67090a928feba4 100644 --- a/test/parallel/test-repl-preview-without-inspector.js +++ b/test/parallel/test-repl-preview-without-inspector.js @@ -65,7 +65,7 @@ function runAndWait(cmds, repl) { return promise; } -const repl = REPLServer({ +const repl = new REPLServer({ prompt: PROMPT, stream: new REPLStream(), ignoreUndefined: true, diff --git a/test/parallel/test-repl-preview.js b/test/parallel/test-repl-preview.js index 7518673ce2e8b4..a324fd41a18a50 100644 --- a/test/parallel/test-repl-preview.js +++ b/test/parallel/test-repl-preview.js @@ -57,7 +57,7 @@ function runAndWait(cmds, repl) { } async function tests(options) { - const repl = REPLServer({ + const repl = new REPLServer({ prompt: PROMPT, stream: new REPLStream(), ignoreUndefined: true, diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 6a02bb6563e293..960e74eee93318 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -1050,3 +1050,17 @@ function event(ee, expected) { })); }); } + +{ + const server = repl.REPLServer(); + common.expectWarning({ + DeprecationWarning: { + DEP0185: 'Instantiating REPLServer without the \'new\' keyword has been deprecated.', + // For the 'url.format' test-case. + DEP0169: + '`url.parse()` behavior is not standardized and prone to errors that have security implications. ' + + 'Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.', + } + }); + server.emit('line', '.exit'); +}