From ab5b81bee114f44d499ec8ccee35121eee93c844 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 22 Aug 2014 20:59:50 +0900 Subject: [PATCH] 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. --- examples/client.c | 40 +++- examples/libevent-client.c | 31 ++- examples/libevent-server.c | 27 ++- lib/Makefile.am | 6 +- lib/includes/nghttp2/nghttp2.h | 421 ++++++++++++++++++++++----------- lib/nghttp2_callbacks.c | 139 +++++++++++ lib/nghttp2_callbacks.h | 112 +++++++++ lib/nghttp2_session.h | 1 + src/HttpServer.cc | 66 ++++-- src/h2load_http2_session.cc | 25 +- src/nghttp.cc | 49 ++-- src/shrpx_http2_session.cc | 51 +++- src/shrpx_http2_upstream.cc | 50 +++- 13 files changed, 776 insertions(+), 242 deletions(-) create mode 100644 lib/nghttp2_callbacks.c create mode 100644 lib/nghttp2_callbacks.h diff --git a/examples/client.c b/examples/client.c index 57a9cc96..a08d943a 100644 --- a/examples/client.c +++ b/examples/client.c @@ -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) { - memset(callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks->send_callback = send_callback; - callbacks->recv_callback = recv_callback; - callbacks->on_frame_send_callback = on_frame_send_callback; - callbacks->on_frame_recv_callback = on_frame_recv_callback; - callbacks->on_stream_close_callback = on_stream_close_callback; - callbacks->on_data_chunk_recv_callback = on_data_chunk_recv_callback; + nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); + + nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback); + + nghttp2_session_callbacks_set_on_frame_send_callback + (callbacks, on_frame_send_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) { - nghttp2_session_callbacks callbacks; + nghttp2_session_callbacks *callbacks; int fd; SSL_CTX *ssl_ctx; SSL *ssl; @@ -519,8 +527,6 @@ static void fetch_uri(const struct URI *uri) request_init(&req, uri); - setup_nghttp2_callbacks(&callbacks); - /* Establish connection and setup SSL */ fd = connect_to(req.host, req.port); if(fd == -1) { @@ -551,8 +557,20 @@ static void fetch_uri(const struct URI *uri) set_tcp_nodelay(fd); 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); + + nghttp2_session_callbacks_del(callbacks); + if(rv != 0) { diec("nghttp2_session_client_new", rv); } diff --git a/examples/libevent-client.c b/examples/libevent-client.c index fbc34626..ef2dde8a 100644 --- a/examples/libevent-client.c +++ b/examples/libevent-client.c @@ -331,17 +331,30 @@ static SSL* create_ssl(SSL_CTX *ssl_ctx) 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; - 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; - callbacks.on_begin_headers_callback = on_begin_headers_callback; - nghttp2_session_client_new(&session_data->session, &callbacks, session_data); + nghttp2_session_callbacks_set_send_callback(callbacks, send_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_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) diff --git a/examples/libevent-server.c b/examples/libevent-server.c index d380aff8..6a5a3c1c 100644 --- a/examples/libevent-server.c +++ b/examples/libevent-server.c @@ -555,16 +555,27 @@ static int on_stream_close_callback(nghttp2_session *session, 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; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_stream_close_callback = on_stream_close_callback; - callbacks.on_header_callback = on_header_callback; - callbacks.on_begin_headers_callback = on_begin_headers_callback; - nghttp2_session_server_new(&session_data->session, &callbacks, session_data); + nghttp2_session_callbacks_set_send_callback(callbacks, send_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_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 diff --git a/lib/Makefile.am b/lib/Makefile.am index 74182585..b24fa7b8 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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_version.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 \ nghttp2_frame.h \ @@ -52,7 +53,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ nghttp2_net.h \ nghttp2_hd.h nghttp2_hd_huffman.h \ nghttp2_priority_spec.h \ - nghttp2_option.h + nghttp2_option.h \ + nghttp2_callbacks.h libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) libnghttp2_la_LDFLAGS = -no-undefined \ diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 421b58d9..dc1aa301 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -1104,6 +1104,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, @@ -1129,6 +1132,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, @@ -1161,6 +1167,9 @@ typedef ssize_t (*nghttp2_recv_callback) * 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); @@ -1184,6 +1193,9 @@ 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, @@ -1215,6 +1227,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, @@ -1232,6 +1247,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); @@ -1247,6 +1265,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); @@ -1265,6 +1286,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, @@ -1287,6 +1311,9 @@ 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`. + * + * 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) (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 * `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_unknown_frame_recv_callback()`. */ typedef int (*nghttp2_on_unknown_frame_recv_callback) (nghttp2_session *session, @@ -1336,6 +1366,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); @@ -1397,6 +1430,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, @@ -1419,6 +1455,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, @@ -1426,85 +1465,183 @@ typedef ssize_t (*nghttp2_select_padding_callback) size_t max_payloadlen, 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; - /** - * The callback function used to determine the |length| allowed - * in `nghttp2_data_source_read_callback()` - */ - nghttp2_data_source_read_length_callback read_length_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 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; @@ -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 * 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. * @@ -1603,10 +1740,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. * @@ -1688,32 +1825,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: @@ -1731,11 +1872,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. * @@ -1765,51 +1905,45 @@ 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. + * 1. :type:`nghttp2_recv_callback` is invoked one or more times to + * receive frame header. + * * 2. If the frame is DATA frame: * - * 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. + * 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. + * * 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: * - * 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: @@ -1830,18 +1964,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. * @@ -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 * 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, @@ -2396,8 +2529,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, @@ -2571,8 +2704,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, diff --git a/lib/nghttp2_callbacks.c b/lib/nghttp2_callbacks.c new file mode 100644 index 00000000..9af35503 --- /dev/null +++ b/lib/nghttp2_callbacks.c @@ -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 + +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; +} diff --git a/lib/nghttp2_callbacks.h b/lib/nghttp2_callbacks.h new file mode 100644 index 00000000..2057cd10 --- /dev/null +++ b/lib/nghttp2_callbacks.h @@ -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 +#endif /* HAVE_CONFIG_H */ + +#include + +/* + * 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 */ diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 6da373b9..8c8a13c6 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -38,6 +38,7 @@ #include "nghttp2_outbound_item.h" #include "nghttp2_int.h" #include "nghttp2_buf.h" +#include "nghttp2_callbacks.h" /* * Option flags. diff --git a/src/HttpServer.cc b/src/HttpServer.cc index d1909222..f5c16179 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -213,19 +213,29 @@ void remove_stream_write_timeout(Stream *stream) } } // namespace +namespace { +void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config); +} // namespace + class Sessions { public: Sessions(event_base *evbase, const Config *config, SSL_CTX *ssl_ctx) : evbase_(evbase), config_(config), ssl_ctx_(ssl_ctx), + callbacks_(nullptr), next_session_id_(1) - {} + { + nghttp2_session_callbacks_new(&callbacks_); + + fill_callback(callbacks_, config_); + } ~Sessions() { for(auto handler : handlers_) { delete handler; } + nghttp2_session_callbacks_del(callbacks_); } void add_handler(Http2Handler *handler) { @@ -269,6 +279,10 @@ public: } return session_id; } + const nghttp2_session_callbacks* get_callbacks() const + { + return callbacks_; + } void accept_connection(int fd) { int val = 1; @@ -297,6 +311,7 @@ private: event_base *evbase_; const Config *config_; SSL_CTX *ssl_ctx_; + nghttp2_session_callbacks *callbacks_; int64_t next_session_id_; }; @@ -311,10 +326,6 @@ void on_session_closed(Http2Handler *hd, int64_t session_id) } } // namespace -namespace { -void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config); -} // namespace - Http2Handler::Http2Handler(Sessions *sessions, int fd, SSL *ssl, int64_t 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 r; - nghttp2_session_callbacks callbacks; - fill_callback(callbacks, sessions_->get_config()); - r = nghttp2_session_server_new(&session_, &callbacks, this); + + r = nghttp2_session_server_new(&session_, sessions_->get_callbacks(), this); if(r != 0) { return r; } @@ -1436,23 +1446,37 @@ int on_stream_close_callback } // 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)); - callbacks.on_stream_close_callback = 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_stream_close_callback + (callbacks, on_stream_close_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) { - callbacks.on_invalid_frame_recv_callback = - verbose_on_invalid_frame_recv_callback; - callbacks.on_unknown_frame_recv_callback = - verbose_on_unknown_frame_recv_callback; + nghttp2_session_callbacks_set_on_invalid_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_header_callback = on_header_callback; - callbacks.on_begin_headers_callback = on_begin_headers_callback; + + nghttp2_session_callbacks_set_on_data_chunk_recv_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) { - callbacks.select_padding_callback = select_padding_callback; + nghttp2_session_callbacks_set_select_padding_callback + (callbacks, select_padding_callback); } } } // namespace diff --git a/src/h2load_http2_session.cc b/src/h2load_http2_session.cc index 45b0c174..5acdb82a 100644 --- a/src/h2load_http2_session.cc +++ b/src/h2load_http2_session.cc @@ -102,13 +102,26 @@ void Http2Session::on_connect() { int rv; - nghttp2_session_callbacks callbacks = {0}; - 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_callbacks *callbacks; - nghttp2_session_client_new(&session_, &callbacks, client_); + nghttp2_session_callbacks_new(&callbacks); + + util::auto_delete 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]; iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; diff --git a/src/nghttp.cc b/src/nghttp.cc index 0658e060..06335ce3 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -1829,22 +1829,41 @@ ssize_t file_read_callback namespace { int run(char **uris, int n) { - nghttp2_session_callbacks callbacks; - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.on_stream_close_callback = on_stream_close_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback2; + nghttp2_session_callbacks *callbacks; + + nghttp2_session_callbacks_new(&callbacks); + util::auto_delete 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) { - callbacks.on_frame_send_callback = verbose_on_frame_send_callback; - callbacks.on_invalid_frame_recv_callback = - verbose_on_invalid_frame_recv_callback; - callbacks.on_unknown_frame_recv_callback = - verbose_on_unknown_frame_recv_callback; + nghttp2_session_callbacks_set_on_frame_send_callback + (callbacks, verbose_on_frame_send_callback); + + nghttp2_session_callbacks_set_on_invalid_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; - callbacks.on_header_callback = on_header_callback; + + nghttp2_session_callbacks_set_on_data_chunk_recv_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) { - callbacks.select_padding_callback = select_padding_callback; + nghttp2_session_callbacks_set_select_padding_callback + (callbacks, select_padding_callback); } std::string prev_scheme; @@ -1886,7 +1905,7 @@ int run(char **uris, int n) port != prev_port) { if(!requests.empty()) { if (communicate(prev_scheme, prev_host, prev_port, - std::move(requests), &callbacks) != 0) { + std::move(requests), callbacks) != 0) { ++failures; } requests.clear(); @@ -1901,7 +1920,7 @@ int run(char **uris, int n) } if(!requests.empty()) { if (communicate(prev_scheme, prev_host, prev_port, std::move(requests), - &callbacks) != 0) { + callbacks) != 0) { ++failures; } } diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 7286e8dc..ff5034d1 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -1390,21 +1390,46 @@ int Http2Session::on_connect() return -1; } } - nghttp2_session_callbacks callbacks; - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.on_stream_close_callback = on_stream_close_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; - 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; + nghttp2_session_callbacks *callbacks; + rv = nghttp2_session_callbacks_new(&callbacks); + + if(rv != 0) { + return -1; } - rv = nghttp2_session_client_new2(&session_, &callbacks, this, + util::auto_delete 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); if(rv != 0) { diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 2a499e2d..1af40c8c 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -645,22 +645,46 @@ Http2Upstream::Http2Upstream(ClientHandler *handler) handler->set_upstream_timeouts(&get_config()->http2_upstream_read_timeout, &get_config()->upstream_write_timeout); - nghttp2_session_callbacks callbacks; - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.on_stream_close_callback = on_stream_close_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; - 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; + int rv; + + nghttp2_session_callbacks *callbacks; + rv = nghttp2_session_callbacks_new(&callbacks); + + assert(rv == 0); + + util::auto_delete 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) { - 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); assert(rv == 0);