http-req-max per IP MP-632
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 17 Nov 2015 10:31:27 +0000 (11:31 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 17 Nov 2015 10:31:27 +0000 (11:31 +0100)
etc/config-shared1.xml
include/metaproxy/util.hpp
src/filter_frontend_net.cpp
src/filter_frontend_net.hpp
src/util.cpp
xml/schema/filter_frontend_net.rnc

index cc96110..ea40579 100644 (file)
@@ -5,7 +5,7 @@
     <filter id="frontend" type="frontend_net">
       <port>@:9000</port>
       <connect-max>10</connect-max>
-      <http-req-max>50</http-req-max>
+      <http-req-max ip="::1">2</http-req-max>
     </filter>
     <filter id="backend" type="z3950_client">
     </filter>
index 2377f5f..08c1f41 100644 (file)
@@ -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);
     };
index 3fe5367..02638d6 100644 (file)
@@ -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<IP_Pattern> 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<IP_Pattern>::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"))
         {
index 5af4d7c..20cfff5 100644 (file)
@@ -31,6 +31,7 @@ namespace metaproxy_1 {
         class FrontendNet : public Base {
             class Rep;
             class Port;
+            class IP_Pattern;
             class ZAssocServer;
             class ZAssocChild;
             class ThreadPoolPackage;
index f23c00c..c18895d 100644 (file)
@@ -26,6 +26,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <yaz/querytowrbuf.h>
 #include <yaz/oid_db.h>
 #include <yaz/srw.h>
+#include <yaz/match_glob.h>
+
+#include <boost/algorithm/string.hpp>
 
 #include <iostream>
 
@@ -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<std::string> globitems;
+    boost::split(globitems, pattern, boost::is_any_of(" "));
+    std::vector<std::string>::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
index 4e32ccd..365c556 100644 (file)
@@ -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 }?