diff --git a/src/asio_http2_handler.cc b/src/asio_http2_handler.cc index 8a5ba5a0..c08345b5 100644 --- a/src/asio_http2_handler.cc +++ b/src/asio_http2_handler.cc @@ -525,7 +525,7 @@ int http2_handler::start() { return -1; } - auto cb_del = util::defer(callbacks, nghttp2_session_callbacks_del); + auto cb_del = defer(nghttp2_session_callbacks_del, callbacks); nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); @@ -548,7 +548,7 @@ int http2_handler::start() { return -1; } - auto opt_del = util::defer(option, nghttp2_option_del); + auto opt_del = defer(nghttp2_option_del, option); nghttp2_option_set_recv_client_preface(option, 1); diff --git a/src/asio_http2_impl.cc b/src/asio_http2_impl.cc index d793befe..051e4da8 100644 --- a/src/asio_http2_impl.cc +++ b/src/asio_http2_impl.cc @@ -135,10 +135,10 @@ void http2_impl::backlog(int backlog) { backlog_ = backlog; } } // namespace server -template -std::shared_ptr> defer_shared(T &&t, F f) { - return std::make_shared>(std::forward(t), - std::forward(f)); +template +std::shared_ptr> defer_shared(F &&f, T &&... t) { + return std::make_shared>(std::forward(f), + std::forward(t)...); } read_cb file_reader(const std::string &path) { @@ -151,7 +151,7 @@ read_cb file_reader(const std::string &path) { } read_cb file_reader_from_fd(int fd) { - auto d = defer_shared(static_cast(fd), close); + auto d = defer_shared(close, fd); return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type { int rv; diff --git a/src/h2load.cc b/src/h2load.cc index d066fa3c..9539dcdf 100644 --- a/src/h2load.cc +++ b/src/h2load.cc @@ -280,7 +280,7 @@ void print_server_tmp_key(SSL *ssl) { return; } - auto key_del = util::defer(key, EVP_PKEY_free); + auto key_del = defer(EVP_PKEY_free, key); std::cout << "Server Temp Key: "; @@ -293,7 +293,7 @@ void print_server_tmp_key(SSL *ssl) { break; case EVP_PKEY_EC: { auto ec = EVP_PKEY_get1_EC_KEY(key); - auto ec_del = util::defer(ec, EC_KEY_free); + auto ec_del = defer(EC_KEY_free, ec); auto nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); auto cname = EC_curve_nid2nist(nid); if (!cname) { diff --git a/src/h2load_http2_session.cc b/src/h2load_http2_session.cc index 8c202369..f5a382bd 100644 --- a/src/h2load_http2_session.cc +++ b/src/h2load_http2_session.cc @@ -28,6 +28,7 @@ #include "h2load.h" #include "util.h" +#include "template.h" using namespace nghttp2; @@ -126,8 +127,7 @@ void Http2Session::on_connect() { nghttp2_session_callbacks_new(&callbacks); - auto callbacks_deleter = - util::defer(callbacks, nghttp2_session_callbacks_del); + auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks); nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, on_frame_recv_callback); diff --git a/src/nghttp.cc b/src/nghttp.cc index 6bed5e9d..6285484e 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -2136,7 +2136,7 @@ int run(char **uris, int n) { nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks_new(&callbacks); - auto cbsdel = util::defer(callbacks, nghttp2_session_callbacks_del); + auto cbsdel = defer(nghttp2_session_callbacks_del, callbacks); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index ae50683e..c66c57d4 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -1174,8 +1174,7 @@ int Http2Session::on_connect() { return -1; } - auto callbacks_deleter = - util::defer(callbacks, nghttp2_session_callbacks_del); + auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index b5f38d71..88828285 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -666,8 +666,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler) assert(rv == 0); - auto callbacks_deleter = - util::defer(callbacks, nghttp2_session_callbacks_del); + auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index 5a7babe8..886b63ca 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -639,7 +639,7 @@ void get_altnames(X509 *cert, std::vector &dns_names, GENERAL_NAMES *altnames = static_cast( X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); if (altnames) { - auto altnames_deleter = util::defer(altnames, GENERAL_NAMES_free); + auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); size_t n = sk_GENERAL_NAME_num(altnames); for (size_t i = 0; i < n; ++i) { const GENERAL_NAME *altname = sk_GENERAL_NAME_value(altnames, i); @@ -699,7 +699,7 @@ int check_cert(SSL *ssl) { LOG(ERROR) << "No certificate found"; return -1; } - auto cert_deleter = util::defer(cert, X509_free); + auto cert_deleter = defer(X509_free, cert); long verify_res = SSL_get_verify_result(ssl); if (verify_res != X509_V_OK) { LOG(ERROR) << "Certificate verification failed: " @@ -877,7 +877,7 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, LOG(ERROR) << "BIO_new failed"; return -1; } - auto bio_deleter = util::defer(bio, BIO_vfree); + auto bio_deleter = defer(BIO_vfree, bio); if (!BIO_read_filename(bio, certfile)) { LOG(ERROR) << "Could not read certificate file '" << certfile << "'"; return -1; @@ -888,7 +888,7 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, << "'"; return -1; } - auto cert_deleter = util::defer(cert, X509_free); + auto cert_deleter = defer(X509_free, cert); std::string common_name; std::vector dns_names; std::vector ip_addrs; diff --git a/src/template.h b/src/template.h index ff1a281f..77a230ca 100644 --- a/src/template.h +++ b/src/template.h @@ -54,6 +54,23 @@ template constexpr size_t array_size(T (&)[N]) { return N; } +// inspired by , but our +// template can take functions returning other than void. +template struct Defer { + Defer(F &&f, T &&... t) + : f(std::bind(std::forward(f), std::forward(t)...)) {} + Defer(Defer &&o) : f(std::move(o.f)) {} + ~Defer() { f(); } + + using ResultType = typename std::result_of< + typename std::decay::type(typename std::decay::type...)>::type; + std::function f; +}; + +template Defer defer(F &&f, T &&... t) { + return Defer(std::forward(f), std::forward(t)...); +} + } // namespace nghttp2 #endif // TEMPLATE_H diff --git a/src/util.h b/src/util.h index a18993fa..0d66c931 100644 --- a/src/util.h +++ b/src/util.h @@ -54,19 +54,6 @@ namespace nghttp2 { namespace util { -template struct Defer { - Defer(T t, F f) : t(t), f(std::move(f)) {} - - ~Defer() { f(t); } - - T t; - F f; -}; - -template Defer defer(T &&t, F f) { - return Defer(std::forward(t), std::forward(f)); -} - extern const char DEFAULT_STRIP_CHARSET[]; template