certain number of connections has been initiated from a single IP.
<?xml version="1.0"?>
-<!-- $Id: config.xml,v 1.15 2006-03-29 18:09:01 adam Exp $ -->
+<!-- $Id: config.xml,v 1.16 2006-03-30 10:35:14 adam Exp $ -->
<proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<bandwidth>2000000</bandwidth>
<pdu>60</pdu>
<retrieve>100</retrieve>
+ <connect>3</connect>
</limit>
<attribute type="1" value="1-11,13-1016"/>
<attribute type="1" value="*" error="114"/>
<!-- everything else -->
</target>
<max-clients>2</max-clients>
+ <max-connect>3</max-connect>
<log>client-requests server-requests</log>
</proxy>
<?xml version="1.0"?>
<!-- XML Schema for YAZ proxy config file.
- $Id: yazproxy.xsd,v 1.9 2005-05-18 20:15:22 adam Exp $
+ $Id: yazproxy.xsd,v 1.10 2006-03-30 10:35:14 adam Exp $
-->
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
<xs:sequence>
<xs:element ref="target" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="max-clients" minOccurs="0"/>
+ <xs:element ref="max-connect" minOccurs="0"/>
<xs:element ref="log" minOccurs="0"/>
<xs:element ref="module" minOccurs="0"/>
</xs:sequence>
-pkginclude_HEADERS = proxy.h bw.h module.h
+pkginclude_HEADERS = proxy.h bw.h module.h limit-connect.h
-/* $Id: bw.h,v 1.4 2005-06-25 15:58:33 adam Exp $
- Copyright (c) 1998-2004, Index Data.
+/* $Id: bw.h,v 1.5 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
-This file is part of the yaz-proxy.
+This file is part of the yazproxy.
YAZ proxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
02111-1307, USA.
*/
+#ifndef YAZPROXY_YAZ_BW_H
+#define YAZPROXY_YAZ_BW_H
+
+#include <yaz/yconfig.h>
+
class YAZ_EXPORT Yaz_bw {
public:
Yaz_bw(int sz);
int m_ptr;
int m_size;
};
+#endif
/*
* Local variables:
--- /dev/null
+/* $Id: limit-connect.h,v 1.1 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
+
+This file is part of the yazproxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef YAZPROXY_LIMIT_CONNECT_H
+#define YAZPROXY_LIMIT_CONNECT_H
+
+#include <yaz/yconfig.h>
+#include <yazproxy/bw.h>
+
+class LimitConnect {
+public:
+ LimitConnect();
+ ~LimitConnect();
+ void add_connect(const char *peername);
+ int get_total(const char *peername);
+ void cleanup(bool all);
+private:
+ struct Peer;
+
+ int m_period;
+ Peer *m_peers;
+ Peer **lookup(const char *peername);
+};
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
-/* $Id: proxy.h,v 1.28 2006-03-29 13:33:46 adam Exp $
- Copyright (c) 1998-2005, Index Data.
+/* $Id: proxy.h,v 1.29 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
-This file is part of the yaz-proxy.
+This file is part of the yazproxy.
YAZ proxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
#include <yazpp/gdu.h>
#include <yazpp/gduqueue.h>
#include <yazproxy/bw.h>
+#include <yazproxy/limit-connect.h>
class Yaz_Proxy;
Yaz_usemarcon *m_usemarcon;
Yaz_CharsetConverter *m_charset_converter;
yazpp_1::GDUQueue m_in_queue;
+ LimitConnect m_connect;
public:
Yaz_Proxy(yazpp_1::IPDU_Observable *the_PDU_Observable,
yazpp_1::ISocketObservable *the_socket_observable,
-## $Id: Makefile.am,v 1.12 2006-03-25 10:56:28 adam Exp $
+## $Id: Makefile.am,v 1.13 2006-03-30 10:35:15 adam Exp $
AM_CXXFLAGS = $(YAZPPINC) -I$(srcdir)/../include $(XSLT_CFLAGS) $(USEMARCONINC)
libyazproxy_la_SOURCES= yaz-proxy.cpp yaz-proxy-config.cpp yaz-bw.cpp \
proxyp.h yaz-usemarcon.cpp charset-converter.cpp msg-thread.cpp msg-thread.h \
- modules.cpp
+ modules.cpp limit-connect.cpp
bin_PROGRAMS = yazproxy
check_PROGRAMS = cdetails
--- /dev/null
+/* $Id: limit-connect.cpp,v 1.1 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
+
+This file is part of the yazproxy.
+
+YAZ proxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with YAZ proxy; see the file LICENSE. If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+*/
+
+#include <yazproxy/limit-connect.h>
+
+#include <time.h>
+#include <string.h>
+#include <yaz/xmalloc.h>
+
+struct LimitConnect::Peer {
+ friend class LimitConnect;
+
+ Peer(int sz, const char *peername);
+ ~Peer();
+ void add_connect();
+
+ char *m_peername;
+ Yaz_bw m_bw;
+ Peer *m_next;
+};
+
+LimitConnect::LimitConnect()
+{
+ m_period = 60;
+ m_peers = 0;
+}
+
+LimitConnect::~LimitConnect()
+{
+ cleanup(true);
+}
+
+LimitConnect::Peer::Peer(int sz, const char *peername) : m_bw(sz)
+{
+ m_peername = xstrdup(peername);
+ m_next = 0;
+}
+
+LimitConnect::Peer::~Peer()
+{
+ xfree(m_peername);
+}
+
+void LimitConnect::Peer::add_connect()
+{
+ m_bw.add_bytes(1);
+}
+
+LimitConnect::Peer **LimitConnect::lookup(const char *peername)
+{
+ Peer **p = &m_peers;
+ while (*p)
+ {
+ if (!strcmp((*p)->m_peername, peername))
+ break;
+ p = &(*p)->m_next;
+ }
+ return p;
+}
+
+void LimitConnect::add_connect(const char *peername)
+{
+ Peer **p = lookup(peername);
+ if (!*p)
+ *p = new Peer(m_period, peername);
+ (*p)->add_connect();
+}
+
+int LimitConnect::get_total(const char *peername)
+{
+ Peer **p = lookup(peername);
+ if (!*p)
+ return 0;
+ return (*p)->m_bw.get_total();
+}
+
+void LimitConnect::cleanup(bool all)
+{
+ Peer **p = &m_peers;
+ while (*p)
+ {
+ Peer *tp = *p;
+ if (all || (tp->m_bw.get_total() == 0))
+ {
+ *p = tp->m_next;
+ delete tp;
+ }
+ else
+ p = &tp->m_next;
+ }
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
-/* $Id: proxyp.h,v 1.13 2006-03-29 13:33:47 adam Exp $
- Copyright (c) 1998-2005, Index Data.
+/* $Id: proxyp.h,v 1.14 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
-This file is part of the yaz-proxy.
+This file is part of the yazproxy.
YAZ proxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
int *limit_pdu,
int *limit_req,
int *limit_search,
- int *limit_connect,
int *target_idletime,
int *client_idletime,
int *max_clients,
const char **query_charset,
const char **default_client_query_charset);
- void get_generic_info(int *log_mask, int *max_clients);
+ void get_generic_info(int *log_mask, int *max_clients,
+ int *max_connect);
void get_target_info(const char *name, const char **url,
int *limit_bw, int *limit_pdu, int *limit_req,
- int *limit_search, int *limit_connect,
+ int *limit_search,
int *target_idletime, int *client_idletime,
int *max_clients,
int *keepalive_limit_bw, int *keepalive_limit_pdu,
-/* $Id: yaz-proxy-config.cpp,v 1.25 2006-03-25 10:59:14 adam Exp $
- Copyright (c) 1998-2005, Index Data.
+/* $Id: yaz-proxy-config.cpp,v 1.26 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
-This file is part of the yaz-proxy.
+This file is part of the yazproxy.
YAZ proxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
xmlNodePtr m_proxyPtr;
void return_target_info(xmlNodePtr ptr, const char **url,
int *limit_bw, int *limit_pdu, int *limit_req,
- int *limit_search, int *limit_connect,
+ int *limit_search,
int *target_idletime, int *client_idletime,
int *keepalive_limit_bw, int *keepalive_limit_pdu,
int *pre_init, const char **cql2rpn,
const char **default_client_query_charset);
void return_limit(xmlNodePtr ptr,
int *limit_bw, int *limit_pdu, int *limit_req,
- int *limit_search, int *limit_connect);
+ int *limit_search);
int check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
char **addinfo);
xmlNodePtr find_target_node(const char *name, const char *db);
int *limit_bw,
int *limit_pdu,
int *limit_req,
- int *limit_search,
- int *limit_connect)
+ int *limit_search)
{
for (ptr = ptr->children; ptr; ptr = ptr->next)
{
if (t)
*limit_search = atoi(t);
}
- if (ptr->type == XML_ELEMENT_NODE
- && !strcmp((const char *) ptr->name, "connect"))
- {
- const char *t = get_text(ptr);
- if (t)
- *limit_connect = atoi(t);
- }
}
}
#endif
int *limit_pdu,
int *limit_req,
int *limit_search,
- int *limit_connect,
int *target_idletime,
int *client_idletime,
int *keepalive_limit_bw,
*keepalive_limit_bw = 500000;
*keepalive_limit_pdu = 1000;
return_limit(ptr, keepalive_limit_bw, keepalive_limit_pdu,
- &dummy, &dummy, &dummy);
+ &dummy, &dummy);
}
if (ptr->type == XML_ELEMENT_NODE
&& !strcmp((const char *) ptr->name, "limit"))
return_limit(ptr, limit_bw, limit_pdu, limit_req,
- limit_search, limit_connect);
+ limit_search);
if (ptr->type == XML_ELEMENT_NODE
&& !strcmp((const char *) ptr->name, "target-timeout"))
{
int *limit_pdu,
int *limit_req,
int *limit_search,
- int *limit_connect,
int *target_idletime,
int *client_idletime,
int *max_clients,
m_cp->return_target_info(
ptr, url,
limit_bw, limit_pdu, limit_req,
- limit_search, limit_connect,
+ limit_search,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
pre_init, cql2rpn,
}
void Yaz_ProxyConfig::get_generic_info(int *log_mask,
- int *max_clients)
+ int *max_clients,
+ int *max_connect)
{
+ *max_connect = 0;
#if HAVE_XSLT
xmlNodePtr ptr;
if (!m_cp->m_proxyPtr)
*max_clients = 1;
}
}
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "max-connect"))
+ {
+ const char *t = m_cp->get_text(ptr);
+ if (t)
+ *max_connect = atoi(t);
+ }
}
#endif
}
int *limit_pdu,
int *limit_req,
int *limit_search,
- int *limit_connect,
int *target_idletime,
int *client_idletime,
int *max_clients,
url[1] = 0;
}
m_cp->return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
- limit_search, limit_connect,
+ limit_search,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
pre_init, cql2rpn,
-/* $Id: yaz-proxy.cpp,v 1.44 2006-03-25 10:59:14 adam Exp $
- Copyright (c) 1998-2005, Index Data.
+/* $Id: yaz-proxy.cpp,v 1.45 2006-03-30 10:35:15 adam Exp $
+ Copyright (c) 1998-2006, Index Data.
-This file is part of the yaz-proxy.
+This file is part of the yazproxy.
YAZ proxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
IMsg_Thread *Auth_Msg::handle()
{
- yaz_log(YLOG_LOG, "Auth_Msg:handle begin");
ODR decode = odr_createmem(ODR_DECODE);
Z_APDU *apdu;
{
m_ret = m_proxy->handle_authentication(apdu);
}
- yaz_log(YLOG_LOG, "Auth_Msg:handle end");
odr_destroy(decode);
return this;
}
void Auth_Msg::result()
{
- yaz_log(YLOG_LOG, "Auth_Msg:result proxy ok buf=%p len=%d",
- m_apdu_buf, m_apdu_len);
if (m_proxy->dec_ref(false))
+ {
yaz_log(YLOG_LOG, "Auth_Msg::proxy deleted meanwhile");
+ }
else
{
- yaz_log(YLOG_LOG, "Auth_Msg::proxy still alive");
odr_setbuf(m_proxy->odr_decode(), m_apdu_buf, m_apdu_len, 0);
Z_APDU *apdu = 0;
int r = z_APDU(m_proxy->odr_decode(), &apdu, 0, 0);
- if (r)
- yaz_log(YLOG_LOG, "Auth_Msg::result z_APDU OK");
- else
+ if (!r)
yaz_log(YLOG_LOG, "Auth_Msg::result z_APDU failed");
m_proxy->result_authentication(apdu, m_ret);
}
m_config_fname = xstrdup(config);
int r = m_config->read_xml(config);
if (!r)
- m_config->get_generic_info(&m_log_mask, &m_max_clients);
+ m_config->get_generic_info(&m_log_mask, &m_max_clients,
+ &m_connect_max);
return r;
}
else
{
m_log_mask = 0;
- cfg->get_generic_info(&m_log_mask, &m_max_clients);
+ cfg->get_generic_info(&m_log_mask, &m_max_clients,
+ &m_connect_max);
}
}
else
int pre_init = 0;
cfg->get_target_info(proxy_host, url, &m_bw_max,
&m_pdu_max, &m_max_record_retrieve,
- &m_search_max, &m_connect_max,
+ &m_search_max,
&m_target_idletime, &client_idletime,
&parent->m_max_clients,
&m_keepalive_limit_bw,
void Yaz_Proxy::recv_GDU_reduce(GDU *gdu)
{
+ int reduce = 0;
+
+ if (1)
+ {
+ m_parent->m_connect.add_connect(m_peername);
+ int connect_total = m_parent->m_connect.get_total(m_peername);
+ int connect_max = m_parent->m_connect_max;
+
+ if (connect_max && connect_total > connect_max)
+ {
+ yaz_log(YLOG_LOG, "%sconnect delay total=%d max=%d",
+ m_session_str, connect_total, connect_max);
+ reduce = connect_total / connect_max;
+ }
+ else
+ yaz_log(YLOG_LOG, "%sconnect OK total=%d", m_session_str,
+ connect_total);
+ m_parent->m_connect.cleanup(false);
+ }
+
+
int bw_total = m_bw_stat.get_total();
int pdu_total = m_pdu_stat.get_total();
- int reduce = 0;
assert(m_timeout_mode == timeout_busy);
assert(m_timeout_gdu == 0);
{
if (apdu->which == Z_APDU_initRequest)
{
- yaz_log(YLOG_LOG, "%shandle_charset_lang_negotiation",
- m_session_str);
if (m_initRequest_options &&
!ODR_MASK_GET(m_initRequest_options, Z_Options_negotiationModel) &&
(m_proxy_negotiation_charset || m_proxy_negotiation_lang))
m_client->m_init_flag = 1;
#if USE_AUTH_MSG
- yaz_log(YLOG_LOG, "%suse_auth_msg", m_session_str);
Auth_Msg *m = new Auth_Msg;
m->m_proxy = this;
z_APDU(odr_encode(), &apdu, 0, "encode");
bool Yaz_Proxy::dec_ref(bool main_ptr)
{
- yaz_log(YLOG_LOG, "%sdec_ref count=%d", m_session_str, m_ref_count);
-
assert(m_ref_count > 0);
if (main_ptr)
{
void Yaz_Proxy::send_response_fail_client(const char *addr)
{
- yaz_log(YLOG_LOG, "%ssend_close_response", get_session_str());
if (m_http_version)
{
Z_SRW_diagnostic *diagnostic = 0;
int i;
const char *name = 0;
const char *zurl_in_use[MAX_ZURL_PLEX];
- int limit_bw, limit_pdu, limit_req, limit_search, limit_connect;
+ int limit_bw, limit_pdu, limit_req, limit_search;
int target_idletime, client_idletime;
int max_clients;
int keepalive_limit_bw, keepalive_limit_pdu;
for (i = 0; cfg && cfg->get_target_no(i, &name, zurl_in_use,
&limit_bw, &limit_pdu, &limit_req,
- &limit_search, &limit_connect,
+ &limit_search,
&target_idletime, &client_idletime,
&max_clients,
&keepalive_limit_bw,