From 4a46c6ad125dde75e1e35a09f8388f43eab5bb39 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 17 Nov 2015 11:31:27 +0100 Subject: [PATCH] http-req-max per IP MP-632 --- etc/config-shared1.xml | 2 +- include/metaproxy/util.hpp | 2 ++ src/filter_frontend_net.cpp | 37 ++++++++++++++++++++++++++---------- src/filter_frontend_net.hpp | 1 + src/util.cpp | 22 +++++++++++++++++++++ xml/schema/filter_frontend_net.rnc | 5 ++++- 6 files changed, 57 insertions(+), 12 deletions(-) diff --git a/etc/config-shared1.xml b/etc/config-shared1.xml index cc96110..ea40579 100644 --- a/etc/config-shared1.xml +++ b/etc/config-shared1.xml @@ -5,7 +5,7 @@ @:9000 10 - 50 + 2 diff --git a/include/metaproxy/util.hpp b/include/metaproxy/util.hpp index 2377f5f..08c1f41 100644 --- a/include/metaproxy/util.hpp +++ b/include/metaproxy/util.hpp @@ -130,6 +130,8 @@ namespace metaproxy_1 { Odr_int &number_to_present, const char **element_set_name); + bool match_ip(const std::string &pattern, const std::string &value); + std::string uri_encode(std::string s); std::string uri_decode(std::string s); }; diff --git a/src/filter_frontend_net.cpp b/src/filter_frontend_net.cpp index 3fe5367..02638d6 100644 --- a/src/filter_frontend_net.cpp +++ b/src/filter_frontend_net.cpp @@ -54,6 +54,12 @@ namespace metaproxy_1 { std::string cert_fname; int max_recv_bytes; }; + class FrontendNet::IP_Pattern { + friend class Rep; + friend class FrontendNet; + std::string pattern; + int value; + }; class FrontendNet::Rep { friend class FrontendNet; @@ -64,7 +70,7 @@ namespace metaproxy_1 { int m_listen_duration; int m_session_timeout; int m_connect_max; - int m_http_req_max; + std::list http_req_max; std::string m_msg_config; std::string m_stat_req; yazpp_1::SocketManager mySocketManager; @@ -401,14 +407,19 @@ void yf::FrontendNet::ZAssocChild::recv_GDU(Z_GDU *z_pdu, int len) m_limit_connect.add_connect(peername.c_str()); m_limit_connect.cleanup(false); int con_sz = m_limit_connect.get_total(peername.c_str()); - - if (m_p->m_http_req_max && con_sz >= m_p->m_http_req_max) + std::list::const_iterator it = m_p->http_req_max.begin(); + for (; it != m_p->http_req_max.end(); it++) { - mp::odr o; - Z_GDU *gdu_res = o.create_HTTP_Response(m_session, hreq, 500); - int len; - send_GDU(gdu_res, &len); - return; + if (mp::util::match_ip(it->pattern, peername)) + { + if (con_sz < it->value) + break; + mp::odr o; + Z_GDU *gdu_res = o.create_HTTP_Response(m_session, hreq, 500); + int len; + send_GDU(gdu_res, &len); + return; + } } } @@ -534,7 +545,6 @@ yf::FrontendNet::Rep::Rep() m_listen_duration = 0; m_session_timeout = 300; // 5 minutes m_connect_max = 0; - m_http_req_max = 0; az = 0; size_t i; for (i = 0; i < 22; i++) @@ -755,7 +765,14 @@ void yf::FrontendNet::configure(const xmlNode * ptr, bool test_only, } else if (!strcmp((const char *) ptr->name, "http-req-max")) { - m_p->m_http_req_max = mp::xml::get_int(ptr, 0); + const char *names[2] = {"ip", 0}; + std::string values[1]; + + mp::xml::parse_attr(ptr, names, values); + IP_Pattern m; + m.value = mp::xml::get_int(ptr, 0); + m.pattern = values[0]; + m_p->http_req_max.push_back(m); } else if (!strcmp((const char *) ptr->name, "message")) { diff --git a/src/filter_frontend_net.hpp b/src/filter_frontend_net.hpp index 5af4d7c..20cfff5 100644 --- a/src/filter_frontend_net.hpp +++ b/src/filter_frontend_net.hpp @@ -31,6 +31,7 @@ namespace metaproxy_1 { class FrontendNet : public Base { class Rep; class Port; + class IP_Pattern; class ZAssocServer; class ZAssocChild; class ThreadPoolPackage; diff --git a/src/util.cpp b/src/util.cpp index f23c00c..c18895d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -26,6 +26,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include + +#include #include @@ -737,6 +740,25 @@ const char *mp::wrbuf::c_str_null() return wrbuf_cstr_null(m_wrbuf); } +bool mp::util::match_ip(const std::string &pattern, const std::string &value) +{ + std::vector globitems; + boost::split(globitems, pattern, boost::is_any_of(" ")); + std::vector::const_iterator it = globitems.begin(); + bool ret_value = true; // for now (if only empty values) + for (; it != globitems.end(); it++) + { + const char *c_str = (*it).c_str(); + if (*c_str) + { + ret_value = false; // at least one non-empty value + if (yaz_match_glob(c_str, value.c_str())) + return true; + } + } + return ret_value; +} + /* * Local variables: * c-basic-offset: 4 diff --git a/xml/schema/filter_frontend_net.rnc b/xml/schema/filter_frontend_net.rnc index 4e32ccd..365c556 100644 --- a/xml/schema/filter_frontend_net.rnc +++ b/xml/schema/filter_frontend_net.rnc @@ -18,7 +18,10 @@ filter_frontend_net = }+, element mp:timeout { xsd:integer }?, element mp:connect-max { xsd:integer }?, - element mp:http-req-max { xsd:integer }?, + element mp:http-req-max { + attribute ip { xsd:string }?, + xsd:integer + }*, element mp:message { xsd:string }?, element mp:stat-req { xsd:string }? -- 1.7.10.4