diff options
author | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2014-10-19 15:35:47 +0200 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2014-10-22 02:55:03 +0000 |
commit | fc75085cd0f98d2e64c6c85086e6d694d2345f43 (patch) | |
tree | f4c4711a23198fe5e7b2fb8acfe9770c70ff151e /epan/nghttp2 | |
parent | 9ddbc8de77287e0b531f366bda1ffae27975a9a3 (diff) | |
download | wireshark-fc75085cd0f98d2e64c6c85086e6d694d2345f43.tar.gz |
libnghttp2: Update to 0.6.4
Change-Id: Ic8878f818a89ebc1056777a5b0838e8a5b1215d5
Reviewed-on: https://code.wireshark.org/review/4834
Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/nghttp2')
-rw-r--r-- | epan/nghttp2/README.nghttp2 | 2 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2.h | 713 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_buf.c | 43 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_buf.h | 16 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_hd.c | 307 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_hd.h | 12 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_helper.c | 73 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2ver.h | 4 |
8 files changed, 815 insertions, 355 deletions
diff --git a/epan/nghttp2/README.nghttp2 b/epan/nghttp2/README.nghttp2 index 79edd3debf..bc8a9be7c1 100644 --- a/epan/nghttp2/README.nghttp2 +++ b/epan/nghttp2/README.nghttp2 @@ -20,7 +20,7 @@ find . -name "nghttp2*" -type f -exec sed -i 's/<nghttp2\/nghttp2.h>/<nghttp2.h> Change path to nghttp2ver.h find . -name "nghttp2*" -type f -exec sed -i 's/<nghttp2\/nghttp2ver.h>/"nghttp2ver.h"/g' {} \; -Fix c++-compat error +Fix c++-compat error and unused-parameter error in nghttp2/nghttp2_helper.h remove check for CONFIG.H diff --git a/epan/nghttp2/nghttp2.h b/epan/nghttp2/nghttp2.h index 0334fcfcac..9b17a1fe86 100644 --- a/epan/nghttp2/nghttp2.h +++ b/epan/nghttp2/nghttp2.h @@ -343,7 +343,12 @@ typedef enum { /** * The user callback function failed. This is a fatal error. */ - NGHTTP2_ERR_CALLBACK_FAILURE = -902 + NGHTTP2_ERR_CALLBACK_FAILURE = -902, + /** + * Invalid connection preface was received and further processing is + * not possible. + */ + NGHTTP2_ERR_BAD_PREFACE = -903 } nghttp2_error; /** @@ -600,13 +605,18 @@ typedef struct { */ int32_t stream_id; /** - * The type of this frame. See `nghttp2_frame`. + * The type of this frame. See `nghttp2_frame_type`. */ uint8_t type; /** * The flags. */ uint8_t flags; + /** + * Reserved bit in frame header. Currently, this is always set to 0 + * and application should not expect something useful in here. + */ + uint8_t reserved; } nghttp2_frame_hd; @@ -662,9 +672,12 @@ typedef enum { * to outgoing queue, call `nghttp2_session_resume_data()`. In case * of error, there are 2 choices. Returning * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream - * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. - * Returning :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the - * entire session failure. + * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. If a + * different error code is desirable, use + * `nghttp2_submit_rst_stream()` with a desired error code and then + * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Returning + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session + * failure. */ typedef ssize_t (*nghttp2_data_source_read_callback) (nghttp2_session *session, int32_t stream_id, @@ -820,7 +833,7 @@ typedef struct { /** * The error code. See :type:`nghttp2_error_code`. */ - nghttp2_error_code error_code; + uint32_t error_code; } nghttp2_rst_stream; /** @@ -886,6 +899,11 @@ typedef struct { * The promised stream ID */ int32_t promised_stream_id; + /** + * Reserved bit. Currently this is always set to 0 and application + * should not expect something useful in here. + */ + uint8_t reserved; } nghttp2_push_promise; /** @@ -921,7 +939,7 @@ typedef struct { /** * The error code. See :type:`nghttp2_error_code`. */ - nghttp2_error_code error_code; + uint32_t error_code; /** * The additional debug data */ @@ -930,6 +948,11 @@ typedef struct { * The length of |opaque_data| member. */ size_t opaque_data_len; + /** + * Reserved bit. Currently this is always set to 0 and application + * should not expect something useful in here. + */ + uint8_t reserved; } nghttp2_goaway; /** @@ -946,6 +969,11 @@ typedef struct { * The window size increment. */ int32_t window_size_increment; + /** + * Reserved bit. Currently this is always set to 0 and application + * should not expect something useful in here. + */ + uint8_t reserved; } nghttp2_window_update; /** @@ -1079,6 +1107,9 @@ typedef union { * `nghttp2_session_send()` to send data to the remote endpoint. If * the application uses solely `nghttp2_session_mem_send()` instead, * this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_send_callback()`. */ typedef ssize_t (*nghttp2_send_callback) (nghttp2_session *session, @@ -1104,6 +1135,9 @@ typedef ssize_t (*nghttp2_send_callback) * `nghttp2_session_recv()` to receive data from the remote endpoint. * If the application uses solely `nghttp2_session_mem_recv()` * instead, this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_recv_callback()`. */ typedef ssize_t (*nghttp2_recv_callback) (nghttp2_session *session, @@ -1132,10 +1166,16 @@ typedef ssize_t (*nghttp2_recv_callback) * If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the * |frame| is the last frame from the remote peer in this stream. * + * This callback won't be called for CONTINUATION frames. + * HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame. + * * The implementation of this function must return 0 if it succeeds. * If nonzero value is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_frame_recv_callback()`. */ typedef int (*nghttp2_on_frame_recv_callback) (nghttp2_session *session, const nghttp2_frame *frame, void *user_data); @@ -1144,12 +1184,13 @@ typedef int (*nghttp2_on_frame_recv_callback) * @functypedef * * Callback function invoked by `nghttp2_session_recv()` when an - * invalid non-DATA frame is received. The |error_code| is one of the - * :enum:`nghttp2_error_code` and indicates the error. When this - * callback function is invoked, the library automatically submits - * either RST_STREAM or GOAWAY frame. The |user_data| pointer is the - * third argument passed in to the call to - * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * invalid non-DATA frame is received. The |error_code| indicates the + * error. It is usually one of the :enum:`nghttp2_error_code` but + * that is not guaranteed. When this callback function is invoked, + * the library automatically submits either RST_STREAM or GOAWAY + * frame. The |user_data| pointer is the third argument passed in to + * the call to `nghttp2_session_client_new()` or + * `nghttp2_session_server_new()`. * * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` * member of their data structure are always ``NULL`` and 0 @@ -1159,10 +1200,13 @@ typedef int (*nghttp2_on_frame_recv_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`. */ typedef int (*nghttp2_on_invalid_frame_recv_callback) (nghttp2_session *session, const nghttp2_frame *frame, - nghttp2_error_code error_code, void *user_data); + uint32_t error_code, void *user_data); /** * @functypedef @@ -1190,6 +1234,9 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_data_chunk_recv_callback()`. */ typedef int (*nghttp2_on_data_chunk_recv_callback) (nghttp2_session *session, uint8_t flags, int32_t stream_id, @@ -1207,6 +1254,9 @@ typedef int (*nghttp2_on_data_chunk_recv_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_before_frame_send_callback()`. */ typedef int (*nghttp2_before_frame_send_callback) (nghttp2_session *session, const nghttp2_frame *frame, void *user_data); @@ -1222,6 +1272,9 @@ typedef int (*nghttp2_before_frame_send_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_frame_send_callback()`. */ typedef int (*nghttp2_on_frame_send_callback) (nghttp2_session *session, const nghttp2_frame *frame, void *user_data); @@ -1240,6 +1293,9 @@ typedef int (*nghttp2_on_frame_send_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_frame_not_send_callback()`. */ typedef int (*nghttp2_on_frame_not_send_callback) (nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, @@ -1250,10 +1306,11 @@ typedef int (*nghttp2_on_frame_not_send_callback) * * Callback function invoked when the stream |stream_id| is closed. * The reason of closure is indicated by the |error_code|. The - * stream_user_data, which was specified in `nghttp2_submit_request()` - * or `nghttp2_submit_headers()`, is still available in this function. - * The |user_data| pointer is the third argument passed in to the call - * to `nghttp2_session_client_new()` or + * |error_code| is usually one of :enum:`nghttp2_error_code`, but that + * is not guaranteed. The stream_user_data, which was specified in + * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still + * available in this function. The |user_data| pointer is the third + * argument passed in to the call to `nghttp2_session_client_new()` or * `nghttp2_session_server_new()`. * * This function is also called for a stream in reserved state. @@ -1262,33 +1319,12 @@ typedef int (*nghttp2_on_frame_not_send_callback) * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. - */ -typedef int (*nghttp2_on_stream_close_callback) -(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code, - void *user_data); - -/** - * @functypedef - * - * Callback function invoked when the received frame type is unknown. - * The |head| is the pointer to the header of the received frame. The - * |headlen| is the length of the |head|. According to the spec, the - * |headlen| is always 8. In other words, the |head| is the first 8 - * bytes of the received frame. The |payload| is the pointer to the - * data portion of the received frame. The |payloadlen| is the length - * of the |payload|. This is the data after the length field. The - * |user_data| pointer is the third argument passed in to the call to - * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. * - * The implementation of this function must return 0 if it succeeds. - * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_send()` functions - * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_stream_close_callback()`. */ -typedef int (*nghttp2_on_unknown_frame_recv_callback) -(nghttp2_session *session, - const uint8_t *head, size_t headlen, - const uint8_t *payload, size_t payloadlen, +typedef int (*nghttp2_on_stream_close_callback) +(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data); /** @@ -1311,6 +1347,9 @@ typedef int (*nghttp2_on_unknown_frame_recv_callback) * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, * `nghttp2_session_mem_recv()` function will immediately return * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_begin_headers_callback()`. */ typedef int (*nghttp2_on_begin_headers_callback) (nghttp2_session *session, const nghttp2_frame *frame, void *user_data); @@ -1346,12 +1385,6 @@ typedef int (*nghttp2_on_begin_headers_callback) * `nghttp2_check_header_value()` provide simple validation against * HTTP2 header field construction rule. * - * One more thing to note is that the |value| may contain ``NULL`` - * (``0x00``) characters. It is used to concatenate header values - * which share the same header field name. The application should - * split these values if it wants to get individual value. This - * concatenation is used in order to keep the ordering of headers. - * * If the application uses `nghttp2_session_mem_recv()`, it can return * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` * return without processing further input bytes. The memory pointed @@ -1364,7 +1397,10 @@ typedef int (*nghttp2_on_begin_headers_callback) * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close * the stream by issuing RST_STREAM with * :enum:`NGHTTP2_INTERNAL_ERROR`. In this case, - * :type:`nghttp2_on_frame_recv_callback` will not be invoked. + * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a + * different error code is desirable, use + * `nghttp2_submit_rst_stream()` with a desired error code and then + * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. * * The implementation of this function must return 0 if it succeeds. * It may return :enum:`NGHTTP2_ERR_PAUSE` or @@ -1375,6 +1411,9 @@ typedef int (*nghttp2_on_begin_headers_callback) * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_header_callback()`. */ typedef int (*nghttp2_on_header_callback) (nghttp2_session *session, @@ -1397,6 +1436,9 @@ typedef int (*nghttp2_on_header_callback) * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make * `nghttp2_session_send()` function immediately return * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_select_padding_callback()`. */ typedef ssize_t (*nghttp2_select_padding_callback) (nghttp2_session *session, @@ -1405,79 +1447,237 @@ typedef ssize_t (*nghttp2_select_padding_callback) void *user_data); /** + * @functypedef + * + * Callback function invoked when library wants to get max length of + * data to send data to the remote peer. The implementation of this + * function should return a value in the following range. [1, + * min(|session_remote_window_size|, |stream_remote_window_size|, + * |remote_max_frame_size|)]. If a value greater than this range is + * returned than the max allow value will be used. Returning a value + * smaller than this range is treated as + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The |frame_type| is provided + * for future extensibility and identifies the type of frame (see + * :type:`nghttp2_frame_type`) for which to get the length for. + * Currently supported frame types are: :enum:`NGHTTP2_DATA`. + * + * This callback can be used to control the length in bytes for which + * :type:`nghttp2_data_source_read_callback` is allowed to send to the + * remote endpoint. This callback is optional. Returning + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session + * failure. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_data_source_read_length_callback()`. + */ +typedef ssize_t (*nghttp2_data_source_read_length_callback) +(nghttp2_session *session, uint8_t frame_type, int32_t stream_id, + int32_t session_remote_window_size, + int32_t stream_remote_window_size, + uint32_t remote_max_frame_size, + void *user_data); + +/** + * @functypedef + * + * Callback function invoked when a frame header is received. The + * |hd| points to received frame header. + * + * Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will + * also be called when frame header of CONTINUATION frame is received. + * + * If both :type:`nghttp2_on_begin_frame_callback` and + * :type:`nghttp2_on_begin_headers_callback` are set and HEADERS or + * PUSH_PROMISE is received, :type:`nghttp2_on_begin_frame_callback` + * will be called first. + * + * The implementation of this function must return 0 if it succeeds. + * If nonzero value is returned, it is treated as fatal error and + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions + * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_on_begin_frame_callback()`. + */ +typedef int (*nghttp2_on_begin_frame_callback) +(nghttp2_session *session, const nghttp2_frame_hd *hd, void *user_data); + +struct nghttp2_session_callbacks; + +/** * @struct * - * Callback functions. + * Callback functions for :type:`nghttp2_session`. The details of + * this structure are intentionally hidden from the public API. */ -typedef struct { - /** - * Callback function invoked when the |session| wants to send data - * to the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_send()` to serialize - * data to transmit. - */ - nghttp2_send_callback send_callback; - /** - * Callback function invoked when the |session| wants to receive - * data from the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_recv()` to process - * received data. - */ - nghttp2_recv_callback recv_callback; - /** - * Callback function invoked by `nghttp2_session_recv()` when a - * frame is received. - */ - nghttp2_on_frame_recv_callback on_frame_recv_callback; - /** - * Callback function invoked by `nghttp2_session_recv()` when an - * invalid non-DATA frame is received. - */ - nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback; - /** - * Callback function invoked when a chunk of data in DATA frame is - * received. - */ - nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback; - /** - * Callback function invoked before a non-DATA frame is sent. - */ - nghttp2_before_frame_send_callback before_frame_send_callback; - /** - * Callback function invoked after a frame is sent. - */ - nghttp2_on_frame_send_callback on_frame_send_callback; - /** - * The callback function invoked when a non-DATA frame is not sent - * because of an error. - */ - nghttp2_on_frame_not_send_callback on_frame_not_send_callback; - /** - * Callback function invoked when the stream is closed. - */ - nghttp2_on_stream_close_callback on_stream_close_callback; - /** - * Callback function invoked when the received frame type is - * unknown. - */ - nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback; - /** - * Callback function invoked when the reception of header block in - * HEADERS or PUSH_PROMISE is started. - */ - nghttp2_on_begin_headers_callback on_begin_headers_callback; - /** - * Callback function invoked when a header name/value pair is - * received. - */ - nghttp2_on_header_callback on_header_callback; - /** - * Callback function invoked when the library asks application how - * many padding bytes are required for the transmission of the given - * frame. - */ - nghttp2_select_padding_callback select_padding_callback; -} nghttp2_session_callbacks; +typedef struct nghttp2_session_callbacks nghttp2_session_callbacks; + +/** + * @function + * + * Initializes |*callbacks_ptr| with NULL values. + * + * The initialized object can be used when initializing multiple + * :type:`nghttp2_session` objects. + * + * When the application finished using this object, it can use + * `nghttp2_session_callbacks_del()` to free its memory. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`NGHTTP2_ERR_NOMEM` + * Out of memory. + */ +int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr); + +/** + * @function + * + * Frees any resources allocated for |callbacks|. If |callbacks| is + * ``NULL``, this function does nothing. + */ +void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); + + +/** + * @function + * + * Sets callback function invoked when a session wants to send data to + * the remote peer. This callback is not necessary if the application + * uses solely `nghttp2_session_mem_send()` to serialize data to + * transmit. + */ +void nghttp2_session_callbacks_set_send_callback +(nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback); + +/** + * @function + * + * Sets callback function invoked when the a session wants to receive + * data from the remote peer. This callback is not necessary if the + * application uses solely `nghttp2_session_mem_recv()` to process + * received data. + */ +void nghttp2_session_callbacks_set_recv_callback +(nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback); + +/** + * @function + * + * Sets callback function invoked by `nghttp2_session_recv()` when a + * frame is received. + */ +void nghttp2_session_callbacks_set_on_frame_recv_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_frame_recv_callback on_frame_recv_callback); + +/** + * @function + * + * Sets callback function invoked by `nghttp2_session_recv()` when an + * invalid non-DATA frame is received. + */ +void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback); + +/** + * @function + * + * Sets callback function invoked when a chunk of data in DATA frame + * is received. + */ +void nghttp2_session_callbacks_set_on_data_chunk_recv_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback); + +/** + * @function + * + * Sets callback function invoked before a non-DATA frame is sent. + */ +void nghttp2_session_callbacks_set_before_frame_send_callback +(nghttp2_session_callbacks *cbs, + nghttp2_before_frame_send_callback before_frame_send_callback); + +/** + * @function + * + * Sets callback function invoked after a frame is sent. + */ +void nghttp2_session_callbacks_set_on_frame_send_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_frame_send_callback on_frame_send_callback); + +/** + * @function + * + * Sets callback function invoked when a non-DATA frame is not sent + * because of an error. + */ +void nghttp2_session_callbacks_set_on_frame_not_send_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_frame_not_send_callback on_frame_not_send_callback); + +/** + * @function + * + * Sets callback function invoked when the stream is closed. + */ +void nghttp2_session_callbacks_set_on_stream_close_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_stream_close_callback on_stream_close_callback); + +/** + * @function + * + * Sets callback function invoked when the reception of header block + * in HEADERS or PUSH_PROMISE is started. + */ +void nghttp2_session_callbacks_set_on_begin_headers_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_begin_headers_callback on_begin_headers_callback); + +/** + * @function + * + * Sets callback function invoked when a header name/value pair is + * received. + */ +void nghttp2_session_callbacks_set_on_header_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_header_callback on_header_callback); + +/** + * @function + * + * Sets callback function invoked when the library asks application + * how many padding bytes are required for the transmission of the + * given frame. + */ +void nghttp2_session_callbacks_set_select_padding_callback +(nghttp2_session_callbacks *cbs, + nghttp2_select_padding_callback select_padding_callback); + +/** + * @function + * + * Sets callback function determine the length allowed in + * :type:`nghttp2_data_source_read_callback`. + */ +void nghttp2_session_callbacks_set_data_source_read_length_callback +(nghttp2_session_callbacks *cbs, + nghttp2_data_source_read_length_callback data_source_read_length_callback); + +/** + * @function + * + * Sets callback function invoked when a frame header is received. + */ +void nghttp2_session_callbacks_set_on_begin_frame_callback +(nghttp2_session_callbacks *cbs, + nghttp2_on_begin_frame_callback on_begin_frame_callback); struct nghttp2_option; @@ -1546,15 +1746,33 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, /** * @function * + * By default, nghttp2 library only handles HTTP/2 frames and does not + * recognize first 24 bytes of client connection preface. This design + * choice is done due to the fact that server may want to detect the + * application protocol based on first few bytes on clear text + * communication. But for simple servers which only speak HTTP/2, it + * is easier for developers if nghttp2 library takes care of client + * connection preface. + * + * If this option is used with nonzero |val|, nghttp2 library checks + * first 24 bytes client connection preface. If it is not a valid + * one, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` will + * return error :enum:`NGHTTP2_ERR_BAD_PREFACE`, which is fatal error. + */ +void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val); + +/** + * @function + * * Initializes |*session_ptr| for client use. The all members of * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr| * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :member:`nghttp2_session_callbacks.send_callback` must be - * specified. If the application code uses `nghttp2_session_recv()`, - * the :member:`nghttp2_session_callbacks.recv_callback` must be - * specified. The other members of |callbacks| can be ``NULL``. + * The :type:`nghttp2_send_callback` must be specified. If the + * application code uses `nghttp2_session_recv()`, the + * :type:`nghttp2_recv_callback` must be specified. The other members + * of |callbacks| can be ``NULL``. * * If this function fails, |*session_ptr| is left untouched. * @@ -1576,10 +1794,10 @@ int nghttp2_session_client_new(nghttp2_session **session_ptr, * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :member:`nghttp2_session_callbacks.send_callback` must be - * specified. If the application code uses `nghttp2_session_recv()`, - * the :member:`nghttp2_session_callbacks.recv_callback` must be - * specified. The other members of |callbacks| can be ``NULL``. + * The :type:`nghttp2_send_callback` must be specified. If the + * application code uses `nghttp2_session_recv()`, the + * :type:`nghttp2_recv_callback` must be specified. The other members + * of |callbacks| can be ``NULL``. * * If this function fails, |*session_ptr| is left untouched. * @@ -1661,32 +1879,36 @@ void nghttp2_session_del(nghttp2_session *session); * This function retrieves the highest prioritized frame from the * outbound queue and sends it to the remote peer. It does this as * many as possible until the user callback - * :member:`nghttp2_session_callbacks.send_callback` returns + * :type:`nghttp2_send_callback` returns * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty. * This function calls several callback functions which are passed * when initializing the |session|. Here is the simple time chart * which tells when each callback is invoked: * * 1. Get the next frame to send from outbound queue. + * * 2. Prepare transmission of the frame. + * * 3. If the control frame cannot be sent because some preconditions * are not met (e.g., request HEADERS cannot be sent after GOAWAY), - * :member:`nghttp2_session_callbacks.on_frame_not_send_callback` - * is invoked. Abort the following steps. + * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort + * the following steps. + * * 4. If the frame is HEADERS, PUSH_PROMISE or DATA, - * :member:`nghttp2_session_callbacks.select_padding_callback` is - * invoked. + * :type:`nghttp2_select_padding_callback` is invoked. + * * 5. If the frame is request HEADERS, the stream is opened here. - * 6. :member:`nghttp2_session_callbacks.before_frame_send_callback` is - * invoked. - * 7. :member:`nghttp2_session_callbacks.send_callback` is invoked one - * or more times to send the frame. - * 8. :member:`nghttp2_session_callbacks.on_frame_send_callback` is - * invoked. + * + * 6. :type:`nghttp2_before_frame_send_callback` is invoked. + * + * 7. :type:`nghttp2_send_callback` is invoked one or more times to + * send the frame. + * + * 8. :type:`nghttp2_on_frame_send_callback` is invoked. + * * 9. If the transmission of the frame triggers closure of the stream, * the stream is closed and - * :member:`nghttp2_session_callbacks.on_stream_close_callback` is - * invoked. + * :type:`nghttp2_on_stream_close_callback` is invoked. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1704,11 +1926,10 @@ int nghttp2_session_send(nghttp2_session *session); * Returns the serialized data to send. * * This function behaves like `nghttp2_session_send()` except that it - * does not use :member:`nghttp2_session_callbacks.send_callback` to - * transmit data. Instead, it assigns the pointer to the serialized - * data to the |*data_ptr| and returns its length. The other - * callbacks are called in the same way as they are in - * `nghttp2_session_send()`. + * does not use :type:`nghttp2_send_callback` to transmit data. + * Instead, it assigns the pointer to the serialized data to the + * |*data_ptr| and returns its length. The other callbacks are called + * in the same way as they are in `nghttp2_session_send()`. * * If no data is available to send, this function returns 0. * @@ -1738,51 +1959,48 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, * Receives frames from the remote peer. * * This function receives as many frames as possible until the user - * callback :member:`nghttp2_session_callbacks.recv_callback` returns + * callback :type:`nghttp2_recv_callback` returns * :enum:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several * callback functions which are passed when initializing the * |session|. Here is the simple time chart which tells when each * callback is invoked: * - * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked one - * or more times to receive frame header. - * 2. If the frame is DATA frame: + * 1. :type:`nghttp2_recv_callback` is invoked one or more times to + * receive frame header. + * + * 2. When frame header is received, + * :type:`nghttp2_on_begin_frame_callback` is invoked. + * + * 3. If the frame is DATA frame: + * + * 1. :type:`nghttp2_recv_callback` is invoked to receive DATA + * payload. For each chunk of data, + * :type:`nghttp2_on_data_chunk_recv_callback` is invoked. * - * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked - * to receive DATA payload. For each chunk of data, - * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback` - * is invoked. * 2. If one DATA frame is completely received, - * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is - * invoked. If the reception of the frame triggers the - * closure of the stream, - * :member:`nghttp2_session_callbacks.on_stream_close_callback` - * is invoked. + * :type:`nghttp2_on_frame_recv_callback` is invoked. If the + * reception of the frame triggers the closure of the stream, + * :type:`nghttp2_on_stream_close_callback` is invoked. * - * 3. If the frame is the control frame: + * 4. If the frame is the control frame: * - * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked - * one or more times to receive whole frame. + * 1. :type:`nghttp2_recv_callback` is invoked one or more times to + * receive whole frame. * * 2. If the received frame is valid, then following actions are * taken. If the frame is either HEADERS or PUSH_PROMISE, - * :member:`nghttp2_session_callbacks.on_begin_headers_callback` - * is invoked. Then - * :member:`nghttp2_session_callbacks.on_header_callback` is - * invoked for each header name/value pair. After all name/value - * pairs are emitted successfully, - * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is + * :type:`nghttp2_on_begin_headers_callback` is invoked. Then + * :type:`nghttp2_on_header_callback` is invoked for each header + * name/value pair. After all name/value pairs are emitted + * successfully, :type:`nghttp2_on_frame_recv_callback` is * invoked. For other frames, - * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is - * invoked. - * If the reception of the frame triggers the closure of the - * stream, - * :member:`nghttp2_session_callbacks.on_stream_close_callback` - * is invoked. + * :type:`nghttp2_on_frame_recv_callback` is invoked. If the + * reception of the frame triggers the closure of the stream, + * :type:`nghttp2_on_stream_close_callback` is invoked. + * * 3. If the received frame is unpacked but is interpreted as - * invalid, - * :member:`nghttp2_session_callbacks.on_invalid_frame_recv_callback` - * is invoked. + * invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is + * invoked. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -1793,6 +2011,10 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. + * :enum:`NGHTTP2_ERR_BAD_PREFACE` + * Invalid client preface was detected. This error only returns + * when |session| was configured as server and + * `nghttp2_option_set_recv_client_preface()` is used. */ int nghttp2_session_recv(nghttp2_session *session); @@ -1803,18 +2025,17 @@ int nghttp2_session_recv(nghttp2_session *session); * |inlen| indicates the number of bytes in the |in|. * * This function behaves like `nghttp2_session_recv()` except that it - * does not use :member:`nghttp2_session_callbacks.recv_callback` to - * receive data; the |in| is the only data for the invocation of this - * function. If all bytes are processed, this function returns. The - * other callbacks are called in the same way as they are in - * `nghttp2_session_recv()`. + * does not use :type:`nghttp2_recv_callback` to receive data; the + * |in| is the only data for the invocation of this function. If all + * bytes are processed, this function returns. The other callbacks + * are called in the same way as they are in `nghttp2_session_recv()`. * * In the current implementation, this function always tries to * processes all input data unless either an error occurs or * :enum:`NGHTTP2_ERR_PAUSE` is returned from - * :member:`nghttp2_session_callbacks.on_header_callback` or - * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`. - * If :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the + * :type:`nghttp2_on_header_callback` or + * :type:`nghttp2_on_data_chunk_recv_callback`. If + * :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the * number of bytes which was used to produce the data or frame for the * callback. * @@ -1825,6 +2046,10 @@ int nghttp2_session_recv(nghttp2_session *session); * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. + * :enum:`NGHTTP2_ERR_BAD_PREFACE` + * Invalid client preface was detected. This error only returns + * when |session| was configured as server and + * `nghttp2_option_set_recv_client_preface()` is used. */ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen); @@ -1839,8 +2064,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, * negative error codes: * * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The stream does not exist; or no deferred data exist; or data - * was deferred by flow control. + * The stream does not exist; or no deferred data exist. * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ @@ -1979,14 +2203,27 @@ int32_t nghttp2_session_get_effective_local_window_size * @function * * Returns the remote window size for a given stream |stream_id|. + * * This is the amount of flow-controlled payload (e.g., DATA) that the - * local endpoint can send without WINDOW_UPDATE. + * local endpoint can send without stream level WINDOW_UPDATE. There + * is also connection level flow control, so the effective size of + * payload that the local endpoint can actually send is + * min(`nghttp2_session_get_stream_remote_window_size()`, + * `nghttp2_session_get_remote_window_size()`). * * This function returns -1 if it fails. */ int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session* session, int32_t stream_id); +/** + * @function + * + * Returns the remote window size for a connection. + * + * This function always succeeds. + */ +int32_t nghttp2_session_get_remote_window_size(nghttp2_session* session); /** * @function @@ -2014,7 +2251,8 @@ int nghttp2_session_get_stream_remote_close(nghttp2_session* session, * The last stream ID is the ID of a stream for which * :type:`nghttp2_on_frame_recv_callback` was called most recently. * - * The |error_code| is the error code of this GOAWAY frame. + * The |error_code| is the error code of this GOAWAY frame. The + * pre-defined error code is one of :enum:`nghttp2_error_code`. * * After the transmission, both `nghttp2_session_want_read()` and * `nghttp2_session_want_write()` return 0. @@ -2030,7 +2268,7 @@ int nghttp2_session_get_stream_remote_close(nghttp2_session* session, * Out of memory. */ int nghttp2_session_terminate_session(nghttp2_session *session, - nghttp2_error_code error_code); + uint32_t error_code); /** * @function @@ -2049,7 +2287,7 @@ int nghttp2_session_terminate_session(nghttp2_session *session, */ int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, - nghttp2_error_code error_code); + uint32_t error_code); /** * @function @@ -2206,18 +2444,18 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`. * * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The value is opaque sequence of bytes and - * therefore can contain NULL byte (0x0). If the application requires - * that the ordering of values for a single header field name - * appearing in different header fields, it has to concatenate them - * using NULL byte (0x0) before passing them to this function. + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. * * HTTP/2 specification has requirement about header fields in the * request HEADERS. See the specification for more details. * - * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. - * * If |data_prd| is not ``NULL``, it provides data which will be sent * in subsequent DATA frames. In this case, a method that allows * request message bodies @@ -2244,8 +2482,8 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); * This function returns assigned stream ID if it succeeds. But * that stream is not opened yet. The application must not submit * frame to that stream ID before - * :member:`nghttp2_session_callbacks.before_frame_send_callback` is - * called for this frame. + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. * */ int32_t nghttp2_submit_request(nghttp2_session *session, @@ -2261,18 +2499,18 @@ int32_t nghttp2_submit_request(nghttp2_session *session, * frames against the stream |stream_id|. * * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The value is opaque sequence of bytes and - * therefore can contain NULL byte (0x0). If the application requires - * that the ordering of values for a single header field name - * appearing in different header fields, it has to concatenate them - * using NULL byte (0x0) before passing them to this function. + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. * * HTTP/2 specification has requirement about header fields in the * response HEADERS. See the specification for more details. * - * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. - * * If |data_prd| is not ``NULL``, it provides data which will be sent * in subsequent DATA frames. This function does not take ownership * of the |data_prd|. The function copies the members of the @@ -2285,6 +2523,10 @@ int32_t nghttp2_submit_request(nghttp2_session *session, * the target stream denoted by the |stream_id| must be reserved using * `nghttp2_submit_push_promise()`. * + * To send non-final response headers (e.g., HTTP status 101), don't + * use this function because this function half-closes the outbound + * stream. Instead, use `nghttp2_submit_headers()` for this purpose. + * * This function returns 0 if it succeeds, or one of the following * negative error codes: * @@ -2331,14 +2573,14 @@ int nghttp2_submit_response(nghttp2_session *session, * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`. * * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The value is opaque sequence of bytes and - * therefore can contain NULL byte (0x0). If the application requires - * that the ordering of values for a single header field name - * appearing in different header fields, it has to concatenate them - * using NULL byte (0x0) before passing them to this function. + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. * * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. * * The |stream_user_data| is a pointer to an arbitrary data which is * associated to the stream this frame will open. Therefore it is @@ -2366,8 +2608,8 @@ int nghttp2_submit_response(nghttp2_session *session, * This function returns assigned stream ID if it succeeds and * |stream_id| is -1. But that stream is not opened yet. The * application must not submit frame to that stream ID before - * :member:`nghttp2_session_callbacks.before_frame_send_callback` is - * called for this frame. + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. * */ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, @@ -2396,6 +2638,19 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, * DATA has been already submitted and not fully processed yet. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0. + * :enum:`NGHTTP2_ERR_STREAM_CLOSED` + * The stream was alreay closed; or the |stream_id| is invalid. + * + * .. note:: + * + * Currently, only one data is allowed for a stream at a time. + * Submitting data more than once before first data is finished + * results in :enum:`NGHTTP2_ERR_DATA_EXIST` error code. The + * earliest callback which tells that previous data is done is + * :type:`nghttp2_on_frame_send_callback`. In side that callback, + * new data can be submitted using `nghttp2_submit_data()`. Of + * course, all data except for last one must not have + * :enum:`NGHTTP2_FLAG_END_STREAM` flag set in |flags|. */ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, int32_t stream_id, @@ -2440,6 +2695,8 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, * Submits RST_STREAM frame to cancel/reject the stream |stream_id| * with the error code |error_code|. * + * The pre-defined error code is one of :enum:`nghttp2_error_code`. + * * The |flags| is currently ignored and should be * :enum:`NGHTTP2_FLAG_NONE`. * @@ -2453,7 +2710,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, */ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, int32_t stream_id, - nghttp2_error_code error_code); + uint32_t error_code); /** * @function @@ -2504,14 +2761,14 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, * The |stream_id| must be client initiated stream ID. * * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The value is opaque sequence of bytes and - * therefore can contain NULL byte (0x0). If the application requires - * that the ordering of values for a single header field name - * appearing in different header fields, it has to concatenate them - * using NULL byte (0x0) before passing them to this function. + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. * * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. * * The |promised_stream_user_data| is a pointer to an arbitrary data * which is associated to the promised stream this frame will open and @@ -2541,8 +2798,8 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, * This function returns assigned promised stream ID if it succeeds. * But that stream is not opened yet. The application must not * submit frame to that stream ID before - * :member:`nghttp2_session_callbacks.before_frame_send_callback` is - * called for this frame. + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. * */ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, @@ -2580,6 +2837,8 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, * Submits GOAWAY frame with the last stream ID |last_stream_id| and * the error code |error_code|. * + * The pre-defined error code is one of :enum:`nghttp2_error_code`. + * * The |flags| is currently ignored and should be * :enum:`NGHTTP2_FLAG_NONE`. * @@ -2606,7 +2865,7 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, */ int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags, int32_t last_stream_id, - nghttp2_error_code error_code, + uint32_t error_code, const uint8_t *opaque_data, size_t opaque_data_len); /** diff --git a/epan/nghttp2/nghttp2_buf.c b/epan/nghttp2/nghttp2_buf.c index ad75519f8c..ebedcd66c2 100644 --- a/epan/nghttp2/nghttp2_buf.c +++ b/epan/nghttp2/nghttp2_buf.c @@ -45,7 +45,12 @@ int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial) void nghttp2_buf_free(nghttp2_buf *buf) { + if(buf == NULL) { + return; + } + free(buf->begin); + buf->begin = NULL; } int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap) @@ -164,10 +169,41 @@ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, return 0; } +int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) +{ + int rv; + nghttp2_buf_chain *chain; + + if(chunk_length < bufs->offset) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + rv = buf_chain_new(&chain, chunk_length); + if(rv != 0) { + return rv; + } + + nghttp2_bufs_free(bufs); + + bufs->head = chain; + bufs->cur = bufs->head; + + nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset); + + bufs->chunk_length = chunk_length; + bufs->chunk_used = 1; + + return 0; +} + void nghttp2_bufs_free(nghttp2_bufs *bufs) { nghttp2_buf_chain *chain, *next_chain; + if(bufs == NULL) { + return; + } + for(chain = bufs->head; chain;) { next_chain = chain->next; @@ -175,6 +211,8 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs) chain = next_chain; } + + bufs->head = NULL; } int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len) @@ -205,7 +243,12 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len) void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) { + if(bufs == NULL) { + return; + } + free(bufs->head); + bufs->head = NULL; } void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) diff --git a/epan/nghttp2/nghttp2_buf.h b/epan/nghttp2/nghttp2_buf.h index 1097ae6a99..e3cb9ec836 100644 --- a/epan/nghttp2/nghttp2_buf.h +++ b/epan/nghttp2/nghttp2_buf.h @@ -229,6 +229,22 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len); void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs); /* + * Reallocates internal buffer using |chunk_length|. The max_chunk, + * chunk_keep and offset do not change. After successful allocation + * of new buffer, previous buffers are deallocated without copying + * anything into new buffers. chunk_used is reset to 1. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_INVALID_ARGUMENT + * chunk_length < offset + */ +int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length); + +/* * Appends the |data| of length |len| to the |bufs|. The write starts * at bufs->cur->buf.last. A new buffers will be allocated to store * all data. diff --git a/epan/nghttp2/nghttp2_hd.c b/epan/nghttp2/nghttp2_hd.c index 0c2a9ecdef..effff208f6 100644 --- a/epan/nghttp2/nghttp2_hd.c +++ b/epan/nghttp2/nghttp2_hd.c @@ -31,73 +31,84 @@ #include "nghttp2_helper.h" #include "nghttp2_int.h" +#define STATIC_TABLE_LENGTH 61 + /* Make scalar initialization form of nghttp2_nv */ -#define MAKE_ENT(N, V, NH, VH) \ - { { (uint8_t*)N, (uint8_t*)V, sizeof(N) - 1, sizeof(V) - 1, 0}, \ - NH, VH, 1, NGHTTP2_HD_FLAG_NONE } - -static nghttp2_hd_entry static_table[] = { - MAKE_ENT(":authority", "", 2962729033u, 0u), - MAKE_ENT(":method", "GET", 3153018267u, 70454u), - MAKE_ENT(":method", "POST", 3153018267u, 2461856u), - MAKE_ENT(":path", "/", 56997727u, 47u), - MAKE_ENT(":path", "/index.html", 56997727u, 2144181430u), - MAKE_ENT(":scheme", "http", 3322585695u, 3213448u), - MAKE_ENT(":scheme", "https", 3322585695u, 99617003u), - MAKE_ENT(":status", "200", 3338091692u, 49586u), - MAKE_ENT(":status", "204", 3338091692u, 49590u), - MAKE_ENT(":status", "206", 3338091692u, 49592u), - MAKE_ENT(":status", "304", 3338091692u, 50551u), - MAKE_ENT(":status", "400", 3338091692u, 51508u), - MAKE_ENT(":status", "404", 3338091692u, 51512u), - MAKE_ENT(":status", "500", 3338091692u, 52469u), - MAKE_ENT("accept-charset", "", 124285319u, 0u), - MAKE_ENT("accept-encoding", "gzip, deflate", 4127597688u, 1733326877u), - MAKE_ENT("accept-language", "", 802785917u, 0u), - MAKE_ENT("accept-ranges", "", 1397189435u, 0u), - MAKE_ENT("accept", "", 2871506184u, 0u), - MAKE_ENT("access-control-allow-origin", "", 3297999203u, 0u), - MAKE_ENT("age", "", 96511u, 0u), - MAKE_ENT("allow", "", 92906313u, 0u), - MAKE_ENT("authorization", "", 2909397113u, 0u), - MAKE_ENT("cache-control", "", 4086191634u, 0u), - MAKE_ENT("content-disposition", "", 3027699811u, 0u), - MAKE_ENT("content-encoding", "", 2095084583u, 0u), - MAKE_ENT("content-language", "", 3065240108u, 0u), - MAKE_ENT("content-length", "", 3162187450u, 0u), - MAKE_ENT("content-location", "", 2284906121u, 0u), - MAKE_ENT("content-range", "", 2878374633u, 0u), - MAKE_ENT("content-type", "", 785670158u, 0u), - MAKE_ENT("cookie", "", 2940209764u, 0u), - MAKE_ENT("date", "", 3076014u, 0u), - MAKE_ENT("etag", "", 3123477u, 0u), - MAKE_ENT("expect", "", 3005803609u, 0u), - MAKE_ENT("expires", "", 2985731892u, 0u), - MAKE_ENT("from", "", 3151786u, 0u), - MAKE_ENT("host", "", 3208616u, 0u), - MAKE_ENT("if-match", "", 34533653u, 0u), - MAKE_ENT("if-modified-since", "", 2302095846u, 0u), - MAKE_ENT("if-none-match", "", 646073760u, 0u), - MAKE_ENT("if-range", "", 39145613u, 0u), - MAKE_ENT("if-unmodified-since", "", 1454068927u, 0u), - MAKE_ENT("last-modified", "", 150043680u, 0u), - MAKE_ENT("link", "", 3321850u, 0u), - MAKE_ENT("location", "", 1901043637u, 0u), - MAKE_ENT("max-forwards", "", 1619948695u, 0u), - MAKE_ENT("proxy-authenticate", "", 3993199572u, 0u), - MAKE_ENT("proxy-authorization", "", 329532250u, 0u), - MAKE_ENT("range", "", 108280125u, 0u), - MAKE_ENT("referer", "", 1085069613u, 0u), - MAKE_ENT("refresh", "", 1085444827u, 0u), - MAKE_ENT("retry-after", "", 1933352567u, 0u), - MAKE_ENT("server", "", 3389140803u, 0u), - MAKE_ENT("set-cookie", "", 1237214767u, 0u), - MAKE_ENT("strict-transport-security", "", 1153852136u, 0u), - MAKE_ENT("transfer-encoding", "", 1274458357u, 0u), - MAKE_ENT("user-agent", "", 486342275u, 0u), - MAKE_ENT("vary", "", 3612210u, 0u), - MAKE_ENT("via", "", 116750u, 0u), - MAKE_ENT("www-authenticate", "", 4051929931u, 0u), +#define MAKE_STATIC_ENT(I, N, V, NH, VH) \ + { { { (uint8_t*)N, (uint8_t*)V, sizeof(N) - 1, sizeof(V) - 1, 0 }, \ + NH, VH, 1, NGHTTP2_HD_FLAG_NONE }, I } + +/* Sorted by hash(name) and its table index */ +static nghttp2_hd_static_entry static_table[] = { + MAKE_STATIC_ENT(20, "age", "", 96511u, 0u), + MAKE_STATIC_ENT(59, "via", "", 116750u, 0u), + MAKE_STATIC_ENT(32, "date", "", 3076014u, 0u), + MAKE_STATIC_ENT(33, "etag", "", 3123477u, 0u), + MAKE_STATIC_ENT(36, "from", "", 3151786u, 0u), + MAKE_STATIC_ENT(37, "host", "", 3208616u, 0u), + MAKE_STATIC_ENT(44, "link", "", 3321850u, 0u), + MAKE_STATIC_ENT(58, "vary", "", 3612210u, 0u), + MAKE_STATIC_ENT(38, "if-match", "", 34533653u, 0u), + MAKE_STATIC_ENT(41, "if-range", "", 39145613u, 0u), + MAKE_STATIC_ENT(3, ":path", "/", 56997727u, 47u), + MAKE_STATIC_ENT(4, ":path", "/index.html", 56997727u, 2144181430u), + MAKE_STATIC_ENT(21, "allow", "", 92906313u, 0u), + MAKE_STATIC_ENT(49, "range", "", 108280125u, 0u), + MAKE_STATIC_ENT(14, "accept-charset", "", 124285319u, 0u), + MAKE_STATIC_ENT(43, "last-modified", "", 150043680u, 0u), + MAKE_STATIC_ENT(48, "proxy-authorization", "", 329532250u, 0u), + MAKE_STATIC_ENT(57, "user-agent", "", 486342275u, 0u), + MAKE_STATIC_ENT(40, "if-none-match", "", 646073760u, 0u), + MAKE_STATIC_ENT(30, "content-type", "", 785670158u, 0u), + MAKE_STATIC_ENT(16, "accept-language", "", 802785917u, 0u), + MAKE_STATIC_ENT(50, "referer", "", 1085069613u, 0u), + MAKE_STATIC_ENT(51, "refresh", "", 1085444827u, 0u), + MAKE_STATIC_ENT(55, "strict-transport-security", "", 1153852136u, 0u), + MAKE_STATIC_ENT(54, "set-cookie", "", 1237214767u, 0u), + MAKE_STATIC_ENT(56, "transfer-encoding", "", 1274458357u, 0u), + MAKE_STATIC_ENT(17, "accept-ranges", "", 1397189435u, 0u), + MAKE_STATIC_ENT(42, "if-unmodified-since", "", 1454068927u, 0u), + MAKE_STATIC_ENT(46, "max-forwards", "", 1619948695u, 0u), + MAKE_STATIC_ENT(45, "location", "", 1901043637u, 0u), + MAKE_STATIC_ENT(52, "retry-after", "", 1933352567u, 0u), + MAKE_STATIC_ENT(25, "content-encoding", "", 2095084583u, 0u), + MAKE_STATIC_ENT(28, "content-location", "", 2284906121u, 0u), + MAKE_STATIC_ENT(39, "if-modified-since", "", 2302095846u, 0u), + MAKE_STATIC_ENT(18, "accept", "", 2871506184u, 0u), + MAKE_STATIC_ENT(29, "content-range", "", 2878374633u, 0u), + MAKE_STATIC_ENT(22, "authorization", "", 2909397113u, 0u), + MAKE_STATIC_ENT(31, "cookie", "", 2940209764u, 0u), + MAKE_STATIC_ENT(0, ":authority", "", 2962729033u, 0u), + MAKE_STATIC_ENT(35, "expires", "", 2985731892u, 0u), + MAKE_STATIC_ENT(34, "expect", "", 3005803609u, 0u), + MAKE_STATIC_ENT(24, "content-disposition", "", 3027699811u, 0u), + MAKE_STATIC_ENT(26, "content-language", "", 3065240108u, 0u), + MAKE_STATIC_ENT(1, ":method", "GET", 3153018267u, 70454u), + MAKE_STATIC_ENT(2, ":method", "POST", 3153018267u, 2461856u), + MAKE_STATIC_ENT(27, "content-length", "", 3162187450u, 0u), + MAKE_STATIC_ENT(19, "access-control-allow-origin", "", 3297999203u, 0u), + MAKE_STATIC_ENT(5, ":scheme", "http", 3322585695u, 3213448u), + MAKE_STATIC_ENT(6, ":scheme", "https", 3322585695u, 99617003u), + MAKE_STATIC_ENT(7, ":status", "200", 3338091692u, 49586u), + MAKE_STATIC_ENT(8, ":status", "204", 3338091692u, 49590u), + MAKE_STATIC_ENT(9, ":status", "206", 3338091692u, 49592u), + MAKE_STATIC_ENT(10, ":status", "304", 3338091692u, 50551u), + MAKE_STATIC_ENT(11, ":status", "400", 3338091692u, 51508u), + MAKE_STATIC_ENT(12, ":status", "404", 3338091692u, 51512u), + MAKE_STATIC_ENT(13, ":status", "500", 3338091692u, 52469u), + MAKE_STATIC_ENT(53, "server", "", 3389140803u, 0u), + MAKE_STATIC_ENT(47, "proxy-authenticate", "", 3993199572u, 0u), + MAKE_STATIC_ENT(60, "www-authenticate", "", 4051929931u, 0u), + MAKE_STATIC_ENT(23, "cache-control", "", 4086191634u, 0u), + MAKE_STATIC_ENT(15, "accept-encoding", "gzip, deflate", 4127597688u, 1733326877u), +}; + +/* Index to the position in static_table */ +const size_t static_table_index[] = { + 38, 43, 44, 10, 11, 47, 48, 49, 50, 51, 52, 53, 54, 55, 14, 60, + 20, 26, 34, 46, 0 , 12, 36, 59, 41, 31, 42, 45, 32, 35, 19, 37, + 2 , 3 , 40, 39, 4 , 5 , 8 , 33, 18, 9 , 27, 15, 6 , 29, 28, 57, + 16, 13, 21, 22, 30, 56, 24, 23, 25, 17, 7 , 1 , 58 }; const size_t NGHTTP2_STATIC_TABLE_LENGTH = @@ -126,7 +137,8 @@ static uint32_t hash(const uint8_t *s, size_t n) int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, size_t namelen, - uint8_t *value, size_t valuelen) + uint8_t *value, size_t valuelen, + uint32_t name_hash, uint32_t value_hash) { int rv = 0; @@ -167,16 +179,10 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, ent->nv.valuelen = valuelen; ent->ref = 1; ent->flags = flags; - if(ent->nv.name) { - ent->name_hash = hash(ent->nv.name, ent->nv.namelen); - } else { - ent->name_hash = 0; - } - if(ent->nv.value) { - ent->value_hash = hash(ent->nv.value, ent->nv.valuelen); - } else { - ent->value_hash = 0; - } + + ent->name_hash = name_hash; + ent->value_hash = value_hash; + return 0; fail2: @@ -753,6 +759,8 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv, static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv, + uint32_t name_hash, + uint32_t value_hash, uint8_t entry_flags) { int rv; @@ -787,7 +795,8 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context, } rv = nghttp2_hd_entry_init(new_ent, entry_flags, - nv->name, nv->namelen, nv->value, nv->valuelen); + nv->name, nv->namelen, nv->value, nv->valuelen, + name_hash, value_hash); if(rv != 0) { free(new_ent); return NULL; @@ -837,44 +846,58 @@ typedef struct { } search_result; static search_result search_hd_table(nghttp2_hd_context *context, - const nghttp2_nv *nv) + const nghttp2_nv *nv, + uint32_t name_hash, uint32_t value_hash) { + ssize_t left = -1, right = (ssize_t)STATIC_TABLE_LENGTH; search_result res = { -1, 0 }; size_t i; - uint32_t name_hash = hash(nv->name, nv->namelen); - uint32_t value_hash = hash(nv->value, nv->valuelen); int use_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) == 0; - for(i = 0; i < NGHTTP2_STATIC_TABLE_LENGTH; ++i) { - nghttp2_hd_entry *ent = &static_table[i]; - if(ent->name_hash != name_hash || !name_eq(&ent->nv, nv)) { - continue; - } + /* Search dynamic table first, so that we can find recently used + entry first */ + if(use_index) { + for(i = 0; i < context->hd_table.len; ++i) { + nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i); + if(ent->name_hash != name_hash || !name_eq(&ent->nv, nv)) { + continue; + } - if(res.index == -1) { - res.index = (ssize_t)i; - } + if(res.index == -1) { + res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + } - if(use_index && - ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { - res.index = (ssize_t)i; - res.name_value_match = 1; - return res; + if(ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { + res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + res.name_value_match = 1; + return res; + } } } - if(!use_index) { - return res; + while(right - left > 1) { + ssize_t mid = (left + right) / 2; + nghttp2_hd_entry *ent = &static_table[mid].ent; + if(ent->name_hash < name_hash) { + left = mid; + } else { + right = mid; + } } - for(i = 0; i < context->hd_table.len; ++i) { - nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i); - if(ent->name_hash == name_hash && name_eq(&ent->nv, nv)) { + for(i = right; i < STATIC_TABLE_LENGTH; ++i) { + nghttp2_hd_entry *ent = &static_table[i].ent; + if(ent->name_hash != name_hash) { + break; + } + + if(name_eq(&ent->nv, nv)) { if(res.index == -1) { - res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + res.index = (ssize_t)(static_table[i].index); } - if(ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { - res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + if(use_index && + ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { + res.index = (ssize_t)(static_table[i].index); res.name_value_match = 1; return res; } @@ -940,7 +963,7 @@ nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context, if(idx >= NGHTTP2_STATIC_TABLE_LENGTH) { return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH); } else { - return &static_table[idx]; + return &static_table[static_table_index[idx]].ent; } } @@ -959,11 +982,14 @@ static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater, return !name_match(nv, NGHTTP2_XHD); #else /* !NGHTTP2_XHD */ return - !name_match(nv, "set-cookie") && + !name_match(nv, ":path") && !name_match(nv, "content-length") && - !name_match(nv, "location") && + !name_match(nv, "set-cookie") && !name_match(nv, "etag") && - !name_match(nv, ":path"); + !name_match(nv, "if-modified-since") && + !name_match(nv, "if-none-match") && + !name_match(nv, "location") && + !name_match(nv, "age"); #endif /* !NGHTTP2_XHD */ } @@ -974,6 +1000,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, search_result res; ssize_t idx = -1; int incidx = 0; + uint32_t name_hash = hash(nv->name, nv->namelen); + uint32_t value_hash = hash(nv->value, nv->valuelen); DEBUGF(fprintf(stderr, "deflatehd: deflating ")); DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr)); @@ -981,7 +1009,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr)); DEBUGF(fprintf(stderr, "\n")); - res = search_hd_table(&deflater->ctx, nv); + + res = search_hd_table(&deflater->ctx, nv, name_hash, value_hash); idx = res.index; @@ -1009,9 +1038,11 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nv_indname = *nv; nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, idx)->nv.name; new_ent = add_hd_table_incremental(&deflater->ctx, &nv_indname, + name_hash, value_hash, NGHTTP2_HD_FLAG_VALUE_ALLOC); } else { new_ent = add_hd_table_incremental(&deflater->ctx, nv, + name_hash, value_hash, NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC); } @@ -1119,12 +1150,11 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, return (ssize_t)buflen; } -size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, +size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_, const nghttp2_nv *nva, size_t nvlen) { size_t n = 0; size_t i; - (void)deflater; /* Possible Maximum Header Table Size Change. Encoding (1u << 31) - 1 using 4 bit prefix requires 6 bytes. We may emit this at most @@ -1321,25 +1351,52 @@ static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, ssize_t rv; size_t buflen; uint8_t *buf; + nghttp2_buf *pbuf; - rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf); + if(inflater->index_required || + inflater->nvbufs.head != inflater->nvbufs.cur) { - if(rv < 0) { - return NGHTTP2_ERR_NOMEM; + rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf); + + if(rv < 0) { + return NGHTTP2_ERR_NOMEM; + } + + buflen = rv; + + if(value_only) { + nv->name = NULL; + nv->namelen = 0; + } else { + nv->name = buf; + nv->namelen = inflater->newnamelen; + } + + nv->value = buf + nv->namelen; + nv->valuelen = buflen - nv->namelen; + + return 0; } - buflen = rv; + /* If we are not going to store header in header table and + name/value are in first chunk, we just refer them from nv, + instead of mallocing another memory. */ + + pbuf = &inflater->nvbufs.head->buf; if(value_only) { nv->name = NULL; nv->namelen = 0; } else { - nv->name = buf; + nv->name = pbuf->pos; nv->namelen = inflater->newnamelen; } - nv->value = buf + nv->namelen; - nv->valuelen = buflen - nv->namelen; + nv->value = pbuf->pos + nv->namelen; + nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen; + + /* Resetting does not change the content of first buffer */ + nghttp2_bufs_reset(&inflater->nvbufs); return 0; } @@ -1381,7 +1438,10 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, management. */ ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT; - new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_flags); + new_ent = add_hd_table_incremental(&inflater->ctx, &nv, + hash(nv.name, nv.namelen), + hash(nv.value, nv.valuelen), + ent_flags); if(new_ent) { emit_indexed_header(nv_out, new_ent); @@ -1397,7 +1457,9 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, emit_literal_header(nv_out, &nv); - inflater->nv_keep = nv.name; + if(nv.name != inflater->nvbufs.head->buf.pos) { + inflater->nv_keep = nv.name; + } return 0; } @@ -1451,7 +1513,10 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, ++ent_name->ref; } - new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_flags); + new_ent = add_hd_table_incremental(&inflater->ctx, &nv, + ent_name->name_hash, + hash(nv.value, nv.valuelen), + ent_flags); if(!static_name && --ent_name->ref == 0) { nghttp2_hd_entry_free(ent_name); @@ -1473,7 +1538,9 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, emit_literal_header(nv_out, &nv); - inflater->nv_keep = nv.value; + if(nv.value != inflater->nvbufs.head->buf.pos) { + inflater->nv_keep = nv.value; + } return 0; } diff --git a/epan/nghttp2/nghttp2_hd.h b/epan/nghttp2/nghttp2_hd.h index 51bc0a0283..2b96b579a5 100644 --- a/epan/nghttp2/nghttp2_hd.h +++ b/epan/nghttp2/nghttp2_hd.h @@ -74,6 +74,11 @@ typedef struct { } nghttp2_hd_entry; typedef struct { + nghttp2_hd_entry ent; + size_t index; +} nghttp2_hd_static_entry; + +typedef struct { nghttp2_hd_entry **buffer; size_t mask; size_t first; @@ -168,7 +173,9 @@ struct nghttp2_hd_inflater { * set in the |flags|, the content pointed by the |name| with length * |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit * set in the |flags|, the content pointed by the |value| with length - * |valuelen| is copied. + * |valuelen| is copied. The |name_hash| and |value_hash| are hash + * value for |name| and |value| respectively. The hash function is + * defined in nghttp2_hd.c. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -178,7 +185,8 @@ struct nghttp2_hd_inflater { */ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, size_t namelen, - uint8_t *value, size_t valuelen); + uint8_t *value, size_t valuelen, + uint32_t name_hash, uint32_t value_hash); void nghttp2_hd_entry_free(nghttp2_hd_entry *ent); diff --git a/epan/nghttp2/nghttp2_helper.c b/epan/nghttp2/nghttp2_helper.c index a0fcaf35ef..51f8ad7444 100644 --- a/epan/nghttp2/nghttp2_helper.c +++ b/epan/nghttp2/nghttp2_helper.c @@ -88,13 +88,78 @@ void* nghttp2_memdup(const void* src, size_t n) return dest; } +static const int DOWNCASE_TBL[] = { + 0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */, + 4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */, + 8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */, + 12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */, + 16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */, + 20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */, + 24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */, + 28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */, + 32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */, + 36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */, + 40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */, + 44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */, + 48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */, + 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */, + 56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */, + 60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */, + 64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */, + 100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */, + 104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */, + 108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */, + 112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */, + 116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */, + 120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */, + 92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */, + 96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */, + 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */, + 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */, + 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */, + 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */, + 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */, + 120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */, + 124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */, + 128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */, + 132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */, + 136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */, + 140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */, + 144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */, + 148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */, + 152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */, + 156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */, + 160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */, + 164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */, + 168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */, + 172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */, + 176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */, + 180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */, + 184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */, + 188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */, + 192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */, + 196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */, + 200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */, + 204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */, + 208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */, + 212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */, + 216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */, + 220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */, + 224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */, + 228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */, + 232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */, + 236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */, + 240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */, + 244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */, + 248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */, + 252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */, +}; + void nghttp2_downcase(uint8_t *s, size_t len) { size_t i; for(i = 0; i < len; ++i) { - if('A' <= s[i] && s[i] <= 'Z') { - s[i] += 'a'-'A'; - } + s[i] = DOWNCASE_TBL[s[i]]; } } @@ -225,6 +290,8 @@ const char* nghttp2_strerror(int error_code) return "Out of memory"; case NGHTTP2_ERR_CALLBACK_FAILURE: return "The user callback function failed"; + case NGHTTP2_ERR_BAD_PREFACE: + return "Received bad connection preface"; default: return "Unknown error code"; } diff --git a/epan/nghttp2/nghttp2ver.h b/epan/nghttp2/nghttp2ver.h index cb360bd541..6c2ec0c884 100644 --- a/epan/nghttp2/nghttp2ver.h +++ b/epan/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "0.5.2-DEV" +#define NGHTTP2_VERSION "0.6.4" /** * @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 0x000502 +#define NGHTTP2_VERSION_NUM 0x000604 #endif /* NGHTTP2VER_H */ |