commit 6d8989b915cc477d8030e1cfa98069ec9da07eed Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 10:55:58 2019 -0400 Package init diff --git a/0103-http-add-callback-to-allow-server-to-decline-and-the.patch b/0103-http-add-callback-to-allow-server-to-decline-and-the.patch new file mode 100644 index 0000000..49ca2d9 --- /dev/null +++ b/0103-http-add-callback-to-allow-server-to-decline-and-the.patch @@ -0,0 +1,255 @@ +From 727bcea130eb4beea9b1ea53604b9807f6819a9a Mon Sep 17 00:00:00 2001 +From: John Fremlin +Date: Fri, 1 Dec 2017 01:29:32 +0000 +Subject: [PATCH 103/319] http: add callback to allow server to decline (and + thereby close) incoming connections. + +This is important, as otherwise clients can easily exhaust the file +descriptors available on a libevent HTTP server, which can cause +problems in other code which does not handle EMFILE well: for example, +see https://github.com/bitcoin/bitcoin/issues/11368 + +Closes: #578 (patch cherry picked) +--- + http-internal.h | 2 + + http.c | 25 +++++++--- + include/event2/http.h | 18 ++++++++ + test/regress_http.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 163 insertions(+), 7 deletions(-) + +diff --git a/http-internal.h b/http-internal.h +index b7d21ef..9e5b0f9 100644 +--- a/http-internal.h ++++ b/http-internal.h +@@ -170,6 +170,8 @@ struct evhttp { + void *gencbarg; + struct bufferevent* (*bevcb)(struct event_base *, void *); + void *bevcbarg; ++ int (*newreqcb)(struct evhttp_request *req, void *); ++ void *newreqcbarg; + + struct event_base *base; + }; +diff --git a/http.c b/http.c +index b3087b5..f2e4971 100644 +--- a/http.c ++++ b/http.c +@@ -3929,6 +3929,14 @@ evhttp_set_bevcb(struct evhttp *http, + http->bevcbarg = cbarg; + } + ++void ++evhttp_set_newreqcb(struct evhttp *http, ++ int (*cb)(struct evhttp_request *, void *), void *cbarg) ++{ ++ http->newreqcb = cb; ++ http->newreqcbarg = cbarg; ++} ++ + /* + * Request related functions + */ +@@ -4239,17 +4247,20 @@ evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon) + req->evcon = evcon; /* the request ends up owning the connection */ + req->flags |= EVHTTP_REQ_OWN_CONNECTION; + +- /* We did not present the request to the user user yet, so treat it as +- * if the user was done with the request. This allows us to free the +- * request on a persistent connection if the client drops it without +- * sending a request. ++ /* We did not present the request to the user yet, so treat it ++ * as if the user was done with the request. This allows us ++ * to free the request on a persistent connection if the ++ * client drops it without sending a request. + */ + req->userdone = 1; +- +- TAILQ_INSERT_TAIL(&evcon->requests, req, next); +- + req->kind = EVHTTP_REQUEST; + ++ if (http->newreqcb && http->newreqcb(req, http->newreqcbarg) == -1) { ++ evhttp_request_free(req); ++ return (-1); ++ } ++ ++ TAILQ_INSERT_TAIL(&evcon->requests, req, next); + + evhttp_start_read_(evcon); + +diff --git a/include/event2/http.h b/include/event2/http.h +index 2a41303..ed9acf4 100644 +--- a/include/event2/http.h ++++ b/include/event2/http.h +@@ -298,6 +298,24 @@ EVENT2_EXPORT_SYMBOL + void evhttp_set_bevcb(struct evhttp *http, + struct bufferevent *(*cb)(struct event_base *, void *), void *arg); + ++ ++/** ++ Set a callback which allows the user to note or throttle incoming requests. ++ ++ The requests are not populated with HTTP level information. They ++ are just associated to a connection. ++ ++ If the callback returns -1, the associated connection is terminated ++ and the request is closed. ++ ++ @param http the evhttp server object for which to set the callback ++ @param cb the callback to invoke for incoming connections ++ @param arg an context argument for the callback ++ */ ++EVENT2_EXPORT_SYMBOL ++void evhttp_set_newreqcb(struct evhttp *http, ++ int (*cb)(struct evhttp_request*, void *), void *arg); ++ + /** + Adds a virtual host to the http server. + +diff --git a/test/regress_http.c b/test/regress_http.c +index b761df0..c459910 100644 +--- a/test/regress_http.c ++++ b/test/regress_http.c +@@ -4604,6 +4604,129 @@ http_request_extra_body_test(void *arg) + evbuffer_free(body); + } + ++struct http_newreqcb_test_state ++{ ++ int connections_started; ++ int connections_noticed; ++ int connections_throttled; ++ int connections_good; ++ int connections_error; ++ int connections_done; ++}; ++ ++static void ++http_newreqcb_test_state_check(struct http_newreqcb_test_state* state) ++{ ++ tt_int_op(state->connections_started, >=, 0); ++ tt_int_op(state->connections_started, >=, state->connections_noticed); ++ tt_int_op(state->connections_throttled, >=, state->connections_error); ++ ++ tt_int_op(state->connections_done, <=, state->connections_started); ++ if (state->connections_good + state->connections_error == state->connections_started) { ++ tt_int_op(state->connections_throttled, ==, state->connections_error); ++ tt_int_op(state->connections_good + state->connections_error, ==, state->connections_done); ++ event_base_loopexit(exit_base, NULL); ++ } ++ ++ return; ++end: ++ tt_fail(); ++ exit(17); ++} ++ ++static void ++http_request_done_newreqcb(struct evhttp_request *req, void *arg) ++{ ++ struct http_newreqcb_test_state* state = arg; ++ if (req && evhttp_request_get_response_code(req) == HTTP_OK) { ++ ++state->connections_good; ++ evhttp_request_set_error_cb(req, NULL); ++ } ++ ++state->connections_done; ++ ++ http_newreqcb_test_state_check(state); ++} ++ ++static void ++http_request_error_newreqcb(enum evhttp_request_error err, void *arg) ++{ ++ struct http_newreqcb_test_state* state = arg; ++ ++state->connections_error; ++ ++ http_newreqcb_test_state_check(state); ++} ++ ++static int ++http_newreqcb(struct evhttp_request* req, void *arg) ++{ ++ struct http_newreqcb_test_state* state = arg; ++ ++state->connections_noticed; ++ http_newreqcb_test_state_check(state); ++ if (1 == state->connections_noticed % 7) { ++ state->connections_throttled++; ++ return -1; ++ } ++ return 0; ++} ++ ++ ++static void ++http_newreqcb_test(void *arg) ++{ ++ struct basic_test_data *data = arg; ++ ev_uint16_t port = 0; ++ struct evhttp *http = http_setup(&port, data->base, 0); ++ struct evhttp_connection *evcons[100]; ++ struct http_newreqcb_test_state newreqcb_test_state; ++ unsigned n; ++ ++ exit_base = data->base; ++ test_ok = 0; ++ ++ memset(&newreqcb_test_state, 0, sizeof(newreqcb_test_state)); ++ memset(evcons, 0, sizeof(evcons)); ++ ++ evhttp_set_newreqcb(http, http_newreqcb, &newreqcb_test_state); ++ ++ for (n = 0; n < sizeof(evcons)/sizeof(evcons[0]); ++n) { ++ struct evhttp_connection* evcon = NULL; ++ struct evhttp_request *req = NULL; ++ evcons[n] = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); ++ evcon = evcons[n]; ++ evhttp_connection_set_retries(evcon, 0); ++ ++ tt_assert(evcon); ++ ++ req = evhttp_request_new(http_request_done_newreqcb, &newreqcb_test_state); ++ evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close"); ++ evhttp_request_set_error_cb(req, http_request_error_newreqcb); ++ ++ /* We give ownership of the request to the connection */ ++ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { ++ tt_abort_msg("Couldn't make request"); ++ } ++ ++ ++newreqcb_test_state.connections_started; ++ http_newreqcb_test_state_check(&newreqcb_test_state); ++ } ++ ++ event_base_dispatch(data->base); ++ ++ http_newreqcb_test_state_check(&newreqcb_test_state); ++ tt_int_op(newreqcb_test_state.connections_throttled, >, 0); ++ ++ end: ++ evhttp_free(http); ++ ++ for (n = 0; n < sizeof(evcons)/sizeof(evcons[0]); ++n) { ++ if (evcons[n]) ++ evhttp_connection_free(evcons[n]); ++ ++ } ++ ++} ++ ++ + #define HTTP_LEGACY(name) \ + { #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \ + http_##name##_test } +@@ -4725,6 +4848,8 @@ struct testcase_t http_testcases[] = { + + HTTP(request_extra_body), + ++ HTTP(newreqcb), ++ + #ifdef EVENT__HAVE_OPENSSL + HTTPS(basic), + HTTPS(filter_basic), +-- +1.8.3.1 + + diff --git a/libevent-2.1.11-stable.tar.gz b/libevent-2.1.11-stable.tar.gz new file mode 100644 index 0000000..8ca374c Binary files /dev/null and b/libevent-2.1.11-stable.tar.gz differ diff --git a/libevent-nonettests.patch b/libevent-nonettests.patch new file mode 100644 index 0000000..f62df5b --- /dev/null +++ b/libevent-nonettests.patch @@ -0,0 +1,11 @@ +diff -up libevent-2.0.21-stable/test/regress_main.c.orig libevent-2.0.21-stable/test/regress_main.c +--- libevent-2.0.21-stable/test/regress_main.c.orig 2012-11-02 11:57:00.000000000 -0400 ++++ libevent-2.0.21-stable/test/regress_main.c 2013-08-21 10:16:26.714288000 -0400 +@@ -370,7 +370,6 @@ struct testgroup_t testgroups[] = { + { "util/", util_testcases }, + { "bufferevent/", bufferevent_testcases }, + { "http/", http_testcases }, +- { "dns/", dns_testcases }, + { "evtag/", evtag_testcases }, + { "rpc/", rpc_testcases }, + { "thread/", thread_testcases }, diff --git a/libevent.spec b/libevent.spec new file mode 100644 index 0000000..bf476ec --- /dev/null +++ b/libevent.spec @@ -0,0 +1,74 @@ +Name: libevent +Version: 2.1.11 +Release: 1 +Summary: An event notification library + +License: BSD +URL: http://libevent.org/ +Source0: https://github.com/libevent/libevent/releases/download/release-%{version}-stable/libevent-%{version}-stable.tar.gz + +BuildRequires: gcc doxygen openssl-devel libevent + +Patch01: libevent-nonettests.patch +Patch02: 0103-http-add-callback-to-allow-server-to-decline-and-the.patch + +%description +Libevent additionally provides a sophisticated framework for buffered network IO, with support for sockets, +filters, rate-limiting, SSL, zero-copy file transmission, and IOCP. +Libevent includes support for several useful protocols, including DNS, HTTP, and a minimal RPC framewor. + +%package devel +Summary: Development files for %{name} +Requires: %{name} = %{version}-%{release} + +%description devel +This package contains the header files and libraries for developing +with %{name}. + +%prep +%autosetup -n libevent-%{version}-stable -p1 + +%build +%configure --disable-dependency-tracking --disable-static +%make_build + +%install +%make_install +cp -a %{_libdir}/libevent* %{buildroot}%{_libdir} +rm -f %{buildroot}%{_libdir}/*.la + + +%check +make check + +%ldconfig_scriptlets + +%files +%doc ChangeLog +%license LICENSE +%{_libdir}/libevent-2.1.so.* +%{_libdir}/libevent_core-2.1.so.* +%{_libdir}/libevent_extra-2.1.so.* +%{_libdir}/libevent_openssl-2.1.so.* +%{_libdir}/libevent_pthreads-2.1.so.* + +%files devel +%{_includedir}/*.h +%dir %{_includedir}/event2 +%{_includedir}/event2/*.h +%{_libdir}/libevent.so +%{_libdir}/libevent_core.so +%{_libdir}/libevent_extra.so +%{_libdir}/libevent_openssl.so +%{_libdir}/libevent_pthreads.so +%{_libdir}/pkgconfig/libevent.pc +%{_libdir}/pkgconfig/libevent_core.pc +%{_libdir}/pkgconfig/libevent_extra.pc +%{_libdir}/pkgconfig/libevent_openssl.pc +%{_libdir}/pkgconfig/libevent_pthreads.pc +%{_bindir}/event_rpcgen.* + + +%changelog +* Tue Aug 27 2019 openEuler Buildteam - 2.1.11-1 +- Package init