Hide nghttp2_session_callbacks details and provide setter like functions

To make it possible to add new callbacks without bumping so name, we
decided to hide details of nghttp2_session_callbacks.  We provide
setter like functions to set individual callback function.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-08-22 20:59:50 +09:00
parent 9f6bb989e3
commit ab5b81bee1
13 changed files with 776 additions and 242 deletions

View File

@ -310,13 +310,21 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
*/ */
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
{ {
memset(callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
callbacks->send_callback = send_callback;
callbacks->recv_callback = recv_callback; nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
callbacks->on_frame_send_callback = on_frame_send_callback;
callbacks->on_frame_recv_callback = on_frame_recv_callback; nghttp2_session_callbacks_set_on_frame_send_callback
callbacks->on_stream_close_callback = on_stream_close_callback; (callbacks, on_frame_send_callback);
callbacks->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
} }
/* /*
@ -507,7 +515,7 @@ static void request_free(struct Request *req)
*/ */
static void fetch_uri(const struct URI *uri) static void fetch_uri(const struct URI *uri)
{ {
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks *callbacks;
int fd; int fd;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
SSL *ssl; SSL *ssl;
@ -519,8 +527,6 @@ static void fetch_uri(const struct URI *uri)
request_init(&req, uri); request_init(&req, uri);
setup_nghttp2_callbacks(&callbacks);
/* Establish connection and setup SSL */ /* Establish connection and setup SSL */
fd = connect_to(req.host, req.port); fd = connect_to(req.host, req.port);
if(fd == -1) { if(fd == -1) {
@ -551,8 +557,20 @@ static void fetch_uri(const struct URI *uri)
set_tcp_nodelay(fd); set_tcp_nodelay(fd);
printf("[INFO] SSL/TLS handshake completed\n"); printf("[INFO] SSL/TLS handshake completed\n");
rv = nghttp2_session_client_new(&connection.session, &callbacks,
rv = nghttp2_session_callbacks_new(&callbacks);
if(rv != 0) {
diec("nghttp2_session_callbacks_new", rv);
}
setup_nghttp2_callbacks(callbacks);
rv = nghttp2_session_client_new(&connection.session, callbacks,
&connection); &connection);
nghttp2_session_callbacks_del(callbacks);
if(rv != 0) { if(rv != 0) {
diec("nghttp2_session_client_new", rv); diec("nghttp2_session_client_new", rv);
} }

View File

@ -331,17 +331,30 @@ static SSL* create_ssl(SSL_CTX *ssl_ctx)
static void initialize_nghttp2_session(http2_session_data *session_data) static void initialize_nghttp2_session(http2_session_data *session_data)
{ {
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks *callbacks;
memset(&callbacks, 0, sizeof(callbacks)); nghttp2_session_callbacks_new(&callbacks);
callbacks.send_callback = send_callback; nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; nghttp2_session_callbacks_set_on_frame_recv_callback
callbacks.on_stream_close_callback = on_stream_close_callback; (callbacks, on_frame_recv_callback);
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback; nghttp2_session_callbacks_set_on_data_chunk_recv_callback
nghttp2_session_client_new(&session_data->session, &callbacks, session_data); (callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
nghttp2_session_client_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
} }
static void send_client_connection_header(http2_session_data *session_data) static void send_client_connection_header(http2_session_data *session_data)

View File

@ -555,16 +555,27 @@ static int on_stream_close_callback(nghttp2_session *session,
static void initialize_nghttp2_session(http2_session_data *session_data) static void initialize_nghttp2_session(http2_session_data *session_data)
{ {
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks *callbacks;
memset(&callbacks, 0, sizeof(callbacks)); nghttp2_session_callbacks_new(&callbacks);
callbacks.send_callback = send_callback; nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback; nghttp2_session_callbacks_set_on_frame_recv_callback
callbacks.on_header_callback = on_header_callback; (callbacks, on_frame_recv_callback);
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_server_new(&session_data->session, &callbacks, session_data); nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
} }
/* Send HTTP/2 client connection header, which includes 24 bytes /* Send HTTP/2 client connection header, which includes 24 bytes

View File

@ -41,7 +41,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \ nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
nghttp2_version.c \ nghttp2_version.c \
nghttp2_priority_spec.c \ nghttp2_priority_spec.c \
nghttp2_option.c nghttp2_option.c \
nghttp2_callbacks.c
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_frame.h \ nghttp2_frame.h \
@ -52,7 +53,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_net.h \ nghttp2_net.h \
nghttp2_hd.h nghttp2_hd_huffman.h \ nghttp2_hd.h nghttp2_hd_huffman.h \
nghttp2_priority_spec.h \ nghttp2_priority_spec.h \
nghttp2_option.h nghttp2_option.h \
nghttp2_callbacks.h
libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
libnghttp2_la_LDFLAGS = -no-undefined \ libnghttp2_la_LDFLAGS = -no-undefined \

View File

@ -1104,6 +1104,9 @@ typedef union {
* `nghttp2_session_send()` to send data to the remote endpoint. If * `nghttp2_session_send()` to send data to the remote endpoint. If
* the application uses solely `nghttp2_session_mem_send()` instead, * the application uses solely `nghttp2_session_mem_send()` instead,
* this callback function is unnecessary. * 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) typedef ssize_t (*nghttp2_send_callback)
(nghttp2_session *session, (nghttp2_session *session,
@ -1129,6 +1132,9 @@ typedef ssize_t (*nghttp2_send_callback)
* `nghttp2_session_recv()` to receive data from the remote endpoint. * `nghttp2_session_recv()` to receive data from the remote endpoint.
* If the application uses solely `nghttp2_session_mem_recv()` * If the application uses solely `nghttp2_session_mem_recv()`
* instead, this callback function is unnecessary. * 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) typedef ssize_t (*nghttp2_recv_callback)
(nghttp2_session *session, (nghttp2_session *session,
@ -1161,6 +1167,9 @@ typedef ssize_t (*nghttp2_recv_callback)
* If nonzero value is returned, it is treated as fatal error and * If nonzero value is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_frame_recv_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); (nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
@ -1184,6 +1193,9 @@ typedef int (*nghttp2_on_frame_recv_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_invalid_frame_recv_callback)
(nghttp2_session *session, const nghttp2_frame *frame, (nghttp2_session *session, const nghttp2_frame *frame,
@ -1215,6 +1227,9 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_data_chunk_recv_callback)
(nghttp2_session *session, uint8_t flags, int32_t stream_id, (nghttp2_session *session, uint8_t flags, int32_t stream_id,
@ -1232,6 +1247,9 @@ typedef int (*nghttp2_on_data_chunk_recv_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_before_frame_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); (nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
@ -1247,6 +1265,9 @@ typedef int (*nghttp2_before_frame_send_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_frame_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); (nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
@ -1265,6 +1286,9 @@ typedef int (*nghttp2_on_frame_send_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_frame_not_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, (nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
@ -1287,6 +1311,9 @@ typedef int (*nghttp2_on_frame_not_send_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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_stream_close_callback) typedef int (*nghttp2_on_stream_close_callback)
(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code, (nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code,
@ -1309,6 +1336,9 @@ typedef int (*nghttp2_on_stream_close_callback)
* If nonzero is returned, it is treated as fatal error and * If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*
* To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_on_unknown_frame_recv_callback()`.
*/ */
typedef int (*nghttp2_on_unknown_frame_recv_callback) typedef int (*nghttp2_on_unknown_frame_recv_callback)
(nghttp2_session *session, (nghttp2_session *session,
@ -1336,6 +1366,9 @@ typedef int (*nghttp2_on_unknown_frame_recv_callback)
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
* `nghttp2_session_mem_recv()` function will immediately return * `nghttp2_session_mem_recv()` function will immediately return
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * :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) typedef int (*nghttp2_on_begin_headers_callback)
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); (nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
@ -1397,6 +1430,9 @@ typedef int (*nghttp2_on_begin_headers_callback)
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
* `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * 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) typedef int (*nghttp2_on_header_callback)
(nghttp2_session *session, (nghttp2_session *session,
@ -1419,6 +1455,9 @@ typedef int (*nghttp2_on_header_callback)
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make
* `nghttp2_session_send()` function immediately return * `nghttp2_session_send()` function immediately return
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * :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) typedef ssize_t (*nghttp2_select_padding_callback)
(nghttp2_session *session, (nghttp2_session *session,
@ -1426,85 +1465,183 @@ typedef ssize_t (*nghttp2_select_padding_callback)
size_t max_payloadlen, size_t max_payloadlen,
void *user_data); void *user_data);
struct nghttp2_session_callbacks;
/** /**
* @struct * @struct
* *
* Callback functions. * Callback functions for :type:`nghttp2_session`. The details of
* this structure are intentionally hidden from the public API.
*/ */
typedef struct { typedef struct nghttp2_session_callbacks nghttp2_session_callbacks;
/**
* Callback function invoked when the |session| wants to send data /**
* to the remote peer. This callback is not necessary if the * @function
* application uses solely `nghttp2_session_mem_send()` to serialize *
* data to transmit. * Initializes |*callbacks_ptr| with NULL values.
*/ *
nghttp2_send_callback send_callback; * The initialized object can be used when initializing multiple
/** * :type:`nghttp2_session` objects.
* Callback function invoked when the |session| wants to receive *
* data from the remote peer. This callback is not necessary if the * When the application finished using this object, it can use
* application uses solely `nghttp2_session_mem_recv()` to process * `nghttp2_session_callbacks_del()` to free its memory.
* received data. *
*/ * This function returns 0 if it succeeds, or one of the following
nghttp2_recv_callback recv_callback; * negative error codes:
/** *
* Callback function invoked by `nghttp2_session_recv()` when a * :enum:`NGHTTP2_ERR_NOMEM`
* frame is received. * Out of memory.
*/ */
nghttp2_on_frame_recv_callback on_frame_recv_callback; int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr);
/**
* Callback function invoked by `nghttp2_session_recv()` when an /**
* invalid non-DATA frame is received. * @function
*/ *
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback; * Frees any resources allocated for |callbacks|. If |callbacks| is
/** * ``NULL``, this function does nothing.
* Callback function invoked when a chunk of data in DATA frame is */
* received. void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks);
*/
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
/** /**
* Callback function invoked before a non-DATA frame is sent. * @function
*/ *
nghttp2_before_frame_send_callback before_frame_send_callback; * Sets callback function invoked when a session wants to send data to
/** * the remote peer. This callback is not necessary if the application
* Callback function invoked after a frame is sent. * uses solely `nghttp2_session_mem_send()` to serialize data to
*/ * transmit.
nghttp2_on_frame_send_callback on_frame_send_callback; */
/** void nghttp2_session_callbacks_set_send_callback
* The callback function invoked when a non-DATA frame is not sent (nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback);
* because of an error.
*/ /**
nghttp2_on_frame_not_send_callback on_frame_not_send_callback; * @function
/** *
* Callback function invoked when the stream is closed. * Sets callback function invoked when the a session wants to receive
*/ * data from the remote peer. This callback is not necessary if the
nghttp2_on_stream_close_callback on_stream_close_callback; * application uses solely `nghttp2_session_mem_recv()` to process
/** * received data.
* Callback function invoked when the received frame type is */
* unknown. void nghttp2_session_callbacks_set_recv_callback
*/ (nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback);
nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback;
/** /**
* Callback function invoked when the reception of header block in * @function
* HEADERS or PUSH_PROMISE is started. *
*/ * Sets callback function invoked by `nghttp2_session_recv()` when a
nghttp2_on_begin_headers_callback on_begin_headers_callback; * frame is received.
/** */
* Callback function invoked when a header name/value pair is void nghttp2_session_callbacks_set_on_frame_recv_callback
* received. (nghttp2_session_callbacks *cbs,
*/ nghttp2_on_frame_recv_callback on_frame_recv_callback);
nghttp2_on_header_callback on_header_callback;
/** /**
* Callback function invoked when the library asks application how * @function
* many padding bytes are required for the transmission of the given *
* frame. * Sets callback function invoked by `nghttp2_session_recv()` when an
*/ * invalid non-DATA frame is received.
nghttp2_select_padding_callback select_padding_callback; */
/** void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
* The callback function used to determine the |length| allowed (nghttp2_session_callbacks *cbs,
* in `nghttp2_data_source_read_callback()` nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback);
*/
nghttp2_data_source_read_length_callback read_length_callback; /**
} nghttp2_session_callbacks; * @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 received frame type is
* unknown.
*/
void nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_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);
struct nghttp2_option; struct nghttp2_option;
@ -1578,10 +1715,10 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
* does not store |callbacks|. The |user_data| is an arbitrary user * does not store |callbacks|. The |user_data| is an arbitrary user
* supplied data, which will be passed to the callback functions. * supplied data, which will be passed to the callback functions.
* *
* The :member:`nghttp2_session_callbacks.send_callback` must be * The :type:`nghttp2_send_callback` must be specified. If the
* specified. If the application code uses `nghttp2_session_recv()`, * application code uses `nghttp2_session_recv()`, the
* the :member:`nghttp2_session_callbacks.recv_callback` must be * :type:`nghttp2_recv_callback` must be specified. The other members
* specified. The other members of |callbacks| can be ``NULL``. * of |callbacks| can be ``NULL``.
* *
* If this function fails, |*session_ptr| is left untouched. * If this function fails, |*session_ptr| is left untouched.
* *
@ -1603,10 +1740,10 @@ int nghttp2_session_client_new(nghttp2_session **session_ptr,
* does not store |callbacks|. The |user_data| is an arbitrary user * does not store |callbacks|. The |user_data| is an arbitrary user
* supplied data, which will be passed to the callback functions. * supplied data, which will be passed to the callback functions.
* *
* The :member:`nghttp2_session_callbacks.send_callback` must be * The :type:`nghttp2_send_callback` must be specified. If the
* specified. If the application code uses `nghttp2_session_recv()`, * application code uses `nghttp2_session_recv()`, the
* the :member:`nghttp2_session_callbacks.recv_callback` must be * :type:`nghttp2_recv_callback` must be specified. The other members
* specified. The other members of |callbacks| can be ``NULL``. * of |callbacks| can be ``NULL``.
* *
* If this function fails, |*session_ptr| is left untouched. * If this function fails, |*session_ptr| is left untouched.
* *
@ -1688,32 +1825,36 @@ void nghttp2_session_del(nghttp2_session *session);
* This function retrieves the highest prioritized frame from the * This function retrieves the highest prioritized frame from the
* outbound queue and sends it to the remote peer. It does this as * outbound queue and sends it to the remote peer. It does this as
* many as possible until the user callback * 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. * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
* This function calls several callback functions which are passed * This function calls several callback functions which are passed
* when initializing the |session|. Here is the simple time chart * when initializing the |session|. Here is the simple time chart
* which tells when each callback is invoked: * which tells when each callback is invoked:
* *
* 1. Get the next frame to send from outbound queue. * 1. Get the next frame to send from outbound queue.
*
* 2. Prepare transmission of the frame. * 2. Prepare transmission of the frame.
*
* 3. If the control frame cannot be sent because some preconditions * 3. If the control frame cannot be sent because some preconditions
* are not met (e.g., request HEADERS cannot be sent after GOAWAY), * are not met (e.g., request HEADERS cannot be sent after GOAWAY),
* :member:`nghttp2_session_callbacks.on_frame_not_send_callback` * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
* is invoked. Abort the following steps. * the following steps.
*
* 4. If the frame is HEADERS, PUSH_PROMISE or DATA, * 4. If the frame is HEADERS, PUSH_PROMISE or DATA,
* :member:`nghttp2_session_callbacks.select_padding_callback` is * :type:`nghttp2_select_padding_callback` is invoked.
* invoked. *
* 5. If the frame is request HEADERS, the stream is opened here. * 5. If the frame is request HEADERS, the stream is opened here.
* 6. :member:`nghttp2_session_callbacks.before_frame_send_callback` is *
* invoked. * 6. :type:`nghttp2_before_frame_send_callback` is invoked.
* 7. :member:`nghttp2_session_callbacks.send_callback` is invoked one *
* or more times to send the frame. * 7. :type:`nghttp2_send_callback` is invoked one or more times to
* 8. :member:`nghttp2_session_callbacks.on_frame_send_callback` is * send the frame.
* invoked. *
* 8. :type:`nghttp2_on_frame_send_callback` is invoked.
*
* 9. If the transmission of the frame triggers closure of the stream, * 9. If the transmission of the frame triggers closure of the stream,
* the stream is closed and * the stream is closed and
* :member:`nghttp2_session_callbacks.on_stream_close_callback` is * :type:`nghttp2_on_stream_close_callback` is invoked.
* invoked.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@ -1731,11 +1872,10 @@ int nghttp2_session_send(nghttp2_session *session);
* Returns the serialized data to send. * Returns the serialized data to send.
* *
* This function behaves like `nghttp2_session_send()` except that it * This function behaves like `nghttp2_session_send()` except that it
* does not use :member:`nghttp2_session_callbacks.send_callback` to * does not use :type:`nghttp2_send_callback` to transmit data.
* transmit data. Instead, it assigns the pointer to the serialized * Instead, it assigns the pointer to the serialized data to the
* data to the |*data_ptr| and returns its length. The other * |*data_ptr| and returns its length. The other callbacks are called
* callbacks are called in the same way as they are in * in the same way as they are in `nghttp2_session_send()`.
* `nghttp2_session_send()`.
* *
* If no data is available to send, this function returns 0. * If no data is available to send, this function returns 0.
* *
@ -1765,51 +1905,45 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
* Receives frames from the remote peer. * Receives frames from the remote peer.
* *
* This function receives as many frames as possible until the user * 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 * :enum:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several
* callback functions which are passed when initializing the * callback functions which are passed when initializing the
* |session|. Here is the simple time chart which tells when each * |session|. Here is the simple time chart which tells when each
* callback is invoked: * callback is invoked:
* *
* 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked one * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
* or more times to receive frame header. * receive frame header.
*
* 2. If the frame is DATA frame: * 2. If the frame is DATA frame:
* *
* 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked * 1. :type:`nghttp2_recv_callback` is invoked to receive DATA
* to receive DATA payload. For each chunk of data, * payload. For each chunk of data,
* :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback` * :type:`nghttp2_on_data_chunk_recv_callback` is invoked.
* is invoked. *
* 2. If one DATA frame is completely received, * 2. If one DATA frame is completely received,
* :member:`nghttp2_session_callbacks.on_frame_recv_callback` is * :type:`nghttp2_on_frame_recv_callback` is invoked. If the
* invoked. If the reception of the frame triggers the * reception of the frame triggers the closure of the stream,
* closure of the stream, * :type:`nghttp2_on_stream_close_callback` is invoked.
* :member:`nghttp2_session_callbacks.on_stream_close_callback`
* is invoked.
* *
* 3. If the frame is the control frame: * 3. If the frame is the control frame:
* *
* 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
* one or more times to receive whole frame. * receive whole frame.
* *
* 2. If the received frame is valid, then following actions are * 2. If the received frame is valid, then following actions are
* taken. If the frame is either HEADERS or PUSH_PROMISE, * taken. If the frame is either HEADERS or PUSH_PROMISE,
* :member:`nghttp2_session_callbacks.on_begin_headers_callback` * :type:`nghttp2_on_begin_headers_callback` is invoked. Then
* is invoked. Then * :type:`nghttp2_on_header_callback` is invoked for each header
* :member:`nghttp2_session_callbacks.on_header_callback` is * name/value pair. After all name/value pairs are emitted
* invoked for each header name/value pair. After all name/value * successfully, :type:`nghttp2_on_frame_recv_callback` is
* pairs are emitted successfully,
* :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
* invoked. For other frames, * invoked. For other frames,
* :member:`nghttp2_session_callbacks.on_frame_recv_callback` is * :type:`nghttp2_on_frame_recv_callback` is invoked. If the
* invoked. * reception of the frame triggers the closure of the stream,
* If the reception of the frame triggers the closure of the * :type:`nghttp2_on_stream_close_callback` is invoked.
* stream, *
* :member:`nghttp2_session_callbacks.on_stream_close_callback`
* is invoked.
* 3. If the received frame is unpacked but is interpreted as * 3. If the received frame is unpacked but is interpreted as
* invalid, * invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is
* :member:`nghttp2_session_callbacks.on_invalid_frame_recv_callback` * invoked.
* is invoked.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@ -1830,18 +1964,17 @@ int nghttp2_session_recv(nghttp2_session *session);
* |inlen| indicates the number of bytes in the |in|. * |inlen| indicates the number of bytes in the |in|.
* *
* This function behaves like `nghttp2_session_recv()` except that it * This function behaves like `nghttp2_session_recv()` except that it
* does not use :member:`nghttp2_session_callbacks.recv_callback` to * does not use :type:`nghttp2_recv_callback` to receive data; the
* receive data; the |in| is the only data for the invocation of this * |in| is the only data for the invocation of this function. If all
* function. If all bytes are processed, this function returns. The * bytes are processed, this function returns. The other callbacks
* other callbacks are called in the same way as they are in * are called in the same way as they are in `nghttp2_session_recv()`.
* `nghttp2_session_recv()`.
* *
* In the current implementation, this function always tries to * In the current implementation, this function always tries to
* processes all input data unless either an error occurs or * processes all input data unless either an error occurs or
* :enum:`NGHTTP2_ERR_PAUSE` is returned from * :enum:`NGHTTP2_ERR_PAUSE` is returned from
* :member:`nghttp2_session_callbacks.on_header_callback` or * :type:`nghttp2_on_header_callback` or
* :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`. * :type:`nghttp2_on_data_chunk_recv_callback`. If
* If :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the * :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 * number of bytes which was used to produce the data or frame for the
* callback. * callback.
* *
@ -2270,8 +2403,8 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* This function returns assigned stream ID if it succeeds. But * This function returns assigned stream ID if it succeeds. But
* that stream is not opened yet. The application must not submit * that stream is not opened yet. The application must not submit
* frame to that stream ID before * frame to that stream ID before
* :member:`nghttp2_session_callbacks.before_frame_send_callback` is * :type:`nghttp2_before_frame_send_callback` is called for this
* called for this frame. * frame.
* *
*/ */
int32_t nghttp2_submit_request(nghttp2_session *session, int32_t nghttp2_submit_request(nghttp2_session *session,
@ -2396,8 +2529,8 @@ int nghttp2_submit_response(nghttp2_session *session,
* This function returns assigned stream ID if it succeeds and * This function returns assigned stream ID if it succeeds and
* |stream_id| is -1. But that stream is not opened yet. The * |stream_id| is -1. But that stream is not opened yet. The
* application must not submit frame to that stream ID before * application must not submit frame to that stream ID before
* :member:`nghttp2_session_callbacks.before_frame_send_callback` is * :type:`nghttp2_before_frame_send_callback` is called for this
* called for this frame. * frame.
* *
*/ */
int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
@ -2571,8 +2704,8 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
* This function returns assigned promised stream ID if it succeeds. * This function returns assigned promised stream ID if it succeeds.
* But that stream is not opened yet. The application must not * But that stream is not opened yet. The application must not
* submit frame to that stream ID before * submit frame to that stream ID before
* :member:`nghttp2_session_callbacks.before_frame_send_callback` is * :type:`nghttp2_before_frame_send_callback` is called for this
* called for this frame. * frame.
* *
*/ */
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,

139
lib/nghttp2_callbacks.c Normal file
View File

@ -0,0 +1,139 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_callbacks.h"
#include <stdlib.h>
int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr)
{
*callbacks_ptr = calloc(1, sizeof(nghttp2_session_callbacks));
if(*callbacks_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks)
{
free(callbacks);
}
void nghttp2_session_callbacks_set_send_callback
(nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback)
{
cbs->send_callback = send_callback;
}
void nghttp2_session_callbacks_set_recv_callback
(nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback)
{
cbs->recv_callback = recv_callback;
}
void nghttp2_session_callbacks_set_on_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback)
{
cbs->on_frame_recv_callback = on_frame_recv_callback;
}
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)
{
cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
}
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)
{
cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
}
void nghttp2_session_callbacks_set_before_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback)
{
cbs->before_frame_send_callback = before_frame_send_callback;
}
void nghttp2_session_callbacks_set_on_frame_send_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback)
{
cbs->on_frame_send_callback = on_frame_send_callback;
}
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)
{
cbs->on_frame_not_send_callback = on_frame_not_send_callback;
}
void nghttp2_session_callbacks_set_on_stream_close_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback)
{
cbs->on_stream_close_callback = on_stream_close_callback;
}
void nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback)
{
cbs->on_unknown_frame_recv_callback = on_unknown_frame_recv_callback;
}
void nghttp2_session_callbacks_set_on_begin_headers_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback)
{
cbs->on_begin_headers_callback = on_begin_headers_callback;
}
void nghttp2_session_callbacks_set_on_header_callback
(nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback)
{
cbs->on_header_callback = on_header_callback;
}
void nghttp2_session_callbacks_set_select_padding_callback
(nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback)
{
cbs->select_padding_callback = select_padding_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)
{
cbs->read_length_callback = data_source_read_length_callback;
}

112
lib/nghttp2_callbacks.h Normal file
View File

@ -0,0 +1,112 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_CALLBACKS_H
#define NGHTTP2_CALLBACKS_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
/*
* Callback functions.
*/
struct nghttp2_session_callbacks {
/**
* 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;
/**
* The callback function used to determine the length allowed in
* `nghttp2_data_source_read_callback()`
*/
nghttp2_data_source_read_length_callback read_length_callback;
};
#endif /* NGHTTP2_CALLBACKS_H */

View File

@ -38,6 +38,7 @@
#include "nghttp2_outbound_item.h" #include "nghttp2_outbound_item.h"
#include "nghttp2_int.h" #include "nghttp2_int.h"
#include "nghttp2_buf.h" #include "nghttp2_buf.h"
#include "nghttp2_callbacks.h"
/* /*
* Option flags. * Option flags.

View File

@ -213,19 +213,29 @@ void remove_stream_write_timeout(Stream *stream)
} }
} // namespace } // namespace
namespace {
void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config);
} // namespace
class Sessions { class Sessions {
public: public:
Sessions(event_base *evbase, const Config *config, SSL_CTX *ssl_ctx) Sessions(event_base *evbase, const Config *config, SSL_CTX *ssl_ctx)
: evbase_(evbase), : evbase_(evbase),
config_(config), config_(config),
ssl_ctx_(ssl_ctx), ssl_ctx_(ssl_ctx),
callbacks_(nullptr),
next_session_id_(1) next_session_id_(1)
{} {
nghttp2_session_callbacks_new(&callbacks_);
fill_callback(callbacks_, config_);
}
~Sessions() ~Sessions()
{ {
for(auto handler : handlers_) { for(auto handler : handlers_) {
delete handler; delete handler;
} }
nghttp2_session_callbacks_del(callbacks_);
} }
void add_handler(Http2Handler *handler) void add_handler(Http2Handler *handler)
{ {
@ -269,6 +279,10 @@ public:
} }
return session_id; return session_id;
} }
const nghttp2_session_callbacks* get_callbacks() const
{
return callbacks_;
}
void accept_connection(int fd) void accept_connection(int fd)
{ {
int val = 1; int val = 1;
@ -297,6 +311,7 @@ private:
event_base *evbase_; event_base *evbase_;
const Config *config_; const Config *config_;
SSL_CTX *ssl_ctx_; SSL_CTX *ssl_ctx_;
nghttp2_session_callbacks *callbacks_;
int64_t next_session_id_; int64_t next_session_id_;
}; };
@ -311,10 +326,6 @@ void on_session_closed(Http2Handler *hd, int64_t session_id)
} }
} // namespace } // namespace
namespace {
void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config);
} // namespace
Http2Handler::Http2Handler(Sessions *sessions, Http2Handler::Http2Handler(Sessions *sessions,
int fd, SSL *ssl, int64_t session_id) int fd, SSL *ssl, int64_t session_id)
: session_id_(session_id), : session_id_(session_id),
@ -724,9 +735,8 @@ void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
int Http2Handler::on_connect() int Http2Handler::on_connect()
{ {
int r; int r;
nghttp2_session_callbacks callbacks;
fill_callback(callbacks, sessions_->get_config()); r = nghttp2_session_server_new(&session_, sessions_->get_callbacks(), this);
r = nghttp2_session_server_new(&session_, &callbacks, this);
if(r != 0) { if(r != 0) {
return r; return r;
} }
@ -1436,23 +1446,37 @@ int on_stream_close_callback
} // namespace } // namespace
namespace { namespace {
void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config) void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config)
{ {
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_callbacks_set_on_stream_close_callback
callbacks.on_stream_close_callback = on_stream_close_callback; (callbacks, on_stream_close_callback);
callbacks.on_frame_recv_callback = hd_on_frame_recv_callback;
callbacks.on_frame_send_callback = hd_on_frame_send_callback; nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, hd_on_frame_recv_callback);
nghttp2_session_callbacks_set_on_frame_send_callback
(callbacks, hd_on_frame_send_callback);
if(config->verbose) { if(config->verbose) {
callbacks.on_invalid_frame_recv_callback = nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
verbose_on_invalid_frame_recv_callback; (callbacks, verbose_on_invalid_frame_recv_callback);
callbacks.on_unknown_frame_recv_callback =
verbose_on_unknown_frame_recv_callback; nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(callbacks, verbose_on_unknown_frame_recv_callback);
} }
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_header_callback = on_header_callback; nghttp2_session_callbacks_set_on_data_chunk_recv_callback
callbacks.on_begin_headers_callback = on_begin_headers_callback; (callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
if(config->padding) { if(config->padding) {
callbacks.select_padding_callback = select_padding_callback; nghttp2_session_callbacks_set_select_padding_callback
(callbacks, select_padding_callback);
} }
} }
} // namespace } // namespace

View File

@ -102,13 +102,26 @@ void Http2Session::on_connect()
{ {
int rv; int rv;
nghttp2_session_callbacks callbacks = {0}; nghttp2_session_callbacks *callbacks;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
nghttp2_session_client_new(&session_, &callbacks, client_); nghttp2_session_callbacks_new(&callbacks);
util::auto_delete<nghttp2_session_callbacks*> callbacks_deleter
(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_client_new(&session_, callbacks, client_);
nghttp2_settings_entry iv[2]; nghttp2_settings_entry iv[2];
iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;

View File

@ -1829,22 +1829,41 @@ ssize_t file_read_callback
namespace { namespace {
int run(char **uris, int n) int run(char **uris, int n)
{ {
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks *callbacks;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_stream_close_callback = on_stream_close_callback; nghttp2_session_callbacks_new(&callbacks);
callbacks.on_frame_recv_callback = on_frame_recv_callback2; util::auto_delete<nghttp2_session_callbacks*> cbsdel
(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback2);
if(config.verbose) { if(config.verbose) {
callbacks.on_frame_send_callback = verbose_on_frame_send_callback; nghttp2_session_callbacks_set_on_frame_send_callback
callbacks.on_invalid_frame_recv_callback = (callbacks, verbose_on_frame_send_callback);
verbose_on_invalid_frame_recv_callback;
callbacks.on_unknown_frame_recv_callback = nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
verbose_on_unknown_frame_recv_callback; (callbacks, verbose_on_invalid_frame_recv_callback);
nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(callbacks, verbose_on_unknown_frame_recv_callback);
} }
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback; nghttp2_session_callbacks_set_on_data_chunk_recv_callback
callbacks.on_header_callback = on_header_callback; (callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
if(config.padding) { if(config.padding) {
callbacks.select_padding_callback = select_padding_callback; nghttp2_session_callbacks_set_select_padding_callback
(callbacks, select_padding_callback);
} }
std::string prev_scheme; std::string prev_scheme;
@ -1886,7 +1905,7 @@ int run(char **uris, int n)
port != prev_port) { port != prev_port) {
if(!requests.empty()) { if(!requests.empty()) {
if (communicate(prev_scheme, prev_host, prev_port, if (communicate(prev_scheme, prev_host, prev_port,
std::move(requests), &callbacks) != 0) { std::move(requests), callbacks) != 0) {
++failures; ++failures;
} }
requests.clear(); requests.clear();
@ -1901,7 +1920,7 @@ int run(char **uris, int n)
} }
if(!requests.empty()) { if(!requests.empty()) {
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests), if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
&callbacks) != 0) { callbacks) != 0) {
++failures; ++failures;
} }
} }

View File

@ -1390,21 +1390,46 @@ int Http2Session::on_connect()
return -1; return -1;
} }
} }
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks *callbacks;
memset(&callbacks, 0, sizeof(callbacks)); rv = nghttp2_session_callbacks_new(&callbacks);
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; if(rv != 0) {
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; return -1;
callbacks.on_frame_send_callback = on_frame_send_callback;
callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
if(get_config()->padding) {
callbacks.select_padding_callback = http::select_padding_callback;
} }
rv = nghttp2_session_client_new2(&session_, &callbacks, this, util::auto_delete<nghttp2_session_callbacks*> callbacks_deleter
(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_frame_send_callback
(callbacks, on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback
(callbacks, on_frame_not_send_callback);
nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(callbacks, on_unknown_frame_recv_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
if(get_config()->padding) {
nghttp2_session_callbacks_set_select_padding_callback
(callbacks, http::select_padding_callback);
}
rv = nghttp2_session_client_new2(&session_, callbacks, this,
get_config()->http2_option); get_config()->http2_option);
if(rv != 0) { if(rv != 0) {

View File

@ -645,22 +645,46 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
handler->set_upstream_timeouts(&get_config()->http2_upstream_read_timeout, handler->set_upstream_timeouts(&get_config()->http2_upstream_read_timeout,
&get_config()->upstream_write_timeout); &get_config()->upstream_write_timeout);
nghttp2_session_callbacks callbacks; int rv;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.on_stream_close_callback = on_stream_close_callback; nghttp2_session_callbacks *callbacks;
callbacks.on_frame_recv_callback = on_frame_recv_callback; rv = nghttp2_session_callbacks_new(&callbacks);
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_frame_send_callback = on_frame_send_callback; assert(rv == 0);
callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback; util::auto_delete<nghttp2_session_callbacks*> callbacks_deleter
callbacks.on_header_callback = on_header_callback; (callbacks, nghttp2_session_callbacks_del);
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_frame_send_callback
(callbacks, on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback
(callbacks, on_frame_not_send_callback);
nghttp2_session_callbacks_set_on_unknown_frame_recv_callback
(callbacks, on_unknown_frame_recv_callback);
nghttp2_session_callbacks_set_on_header_callback
(callbacks, on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback
(callbacks, on_begin_headers_callback);
if(get_config()->padding) { if(get_config()->padding) {
callbacks.select_padding_callback = http::select_padding_callback; nghttp2_session_callbacks_set_select_padding_callback
(callbacks, http::select_padding_callback);
} }
int rv; rv = nghttp2_session_server_new2(&session_, callbacks, this,
rv = nghttp2_session_server_new2(&session_, &callbacks, this,
get_config()->http2_option); get_config()->http2_option);
assert(rv == 0); assert(rv == 0);