aboutsummaryrefslogtreecommitdiffstats
path: root/epan/nghttp2
diff options
context:
space:
mode:
authorAlexis La Goutte <alexis.lagoutte@gmail.com>2014-10-19 15:35:47 +0200
committerMichael Mann <mmann78@netscape.net>2014-10-22 02:55:03 +0000
commitfc75085cd0f98d2e64c6c85086e6d694d2345f43 (patch)
treef4c4711a23198fe5e7b2fb8acfe9770c70ff151e /epan/nghttp2
parent9ddbc8de77287e0b531f366bda1ffae27975a9a3 (diff)
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.nghttp22
-rw-r--r--epan/nghttp2/nghttp2.h713
-rw-r--r--epan/nghttp2/nghttp2_buf.c43
-rw-r--r--epan/nghttp2/nghttp2_buf.h16
-rw-r--r--epan/nghttp2/nghttp2_hd.c307
-rw-r--r--epan/nghttp2/nghttp2_hd.h12
-rw-r--r--epan/nghttp2/nghttp2_helper.c73
-rw-r--r--epan/nghttp2/nghttp2ver.h4
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 */