<chapter id="installation">
- <!-- $Id: installation.xml,v 1.8 2005-02-07 09:50:23 adam Exp $ -->
+ <!-- $Id: installation.xml,v 1.9 2006-04-06 01:16:54 adam Exp $ -->
<title>Installation</title>
<para>
You need a C++ compiler to compile and use YAZ proxy.
<varlistentry>
<term><literal>--with-yazpp </literal>directory</term>
<listitem><para>
- Specifies the location of <filename>yaz++-config</filename>.
- The <filename>yaz++-config</filename> program is generated in
+ Specifies the location of <filename>yazpp-config</filename>.
+ The <filename>yazpp-config</filename> program is generated in
the source directory of YAZ++ as well as the binaries
directory when YAZ++ is installed (via make install).
</para>
<para>
If you don't supply this option, <literal>configure</literal> will
- look for <filename>yaz++-config</filename> in directories of the
+ look for <filename>yazpp-config</filename> in directories of the
<envar>PATH</envar> environment - which is nearly always
what you want.
</para></listitem>
<para>
<screen>
<?xml version="1.0"?>
- <proxy xmlns="http://indexdata.dk/yazproxy/schema/0.8/">
+ <proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/">
<target name="server1" default="1">
<!-- description of server1 .. -->
</target>
The proxy records bandwidth/pdu requests during the last 60 seconds
(1 minute). The <literal>limit</literal> may include the
elements <literal>bandwidth</literal>, <literal>pdu</literal>,
- and <literal>retrieve</literal>. The <literal>bandwidth</literal>
+ <literal>retrieve</literal> and <literal>search</literal>.
+ The <literal>bandwidth</literal>
measures the number of bytes transferred within the last minute.
The <literal>pdu</literal> is the number of requests in the last
minute. The <literal>retrieve</literal> holds the maximum records to
- be retrieved in one Present Request.
+ which may be retrieved in one Present Request.
+ The <literal>search</literal> is the maximum number of searches
+ within the last minute.
</para>
<para>
- If a bandwidth/pdu limit is reached the proxy will postpone the
+ If a bandwidth/pdu/search limit is reached the proxy will postpone the
requests to the target and wait one or more seconds. The idea of the
limit is to ensure that clients that downloads hundreds or thousands of
records do not hurt other users.
</screen>
</para>
</section>
+
+ <section id="proxy-max-connect">
+ <title>max-connect</title>
+ <para>
+ The element <literal>max-connect</literal> is a child of element
+ <literal>proxy</literal> and specifies the maximum number
+ of connections to be initiated within the last minute.
+ </para>
+ <para>
+ If the maximum number is reached the proxy will terminate the
+ just initiated session (connection terminated).
+ </para>
+ </section>
+
+ <section id="proxy-limit-connect">
+ <title>limit-connect</title>
+ <para>
+ The element <literal>max-connect</literal> is a child of element
+ <literal>proxy</literal> and specifies the limit of number
+ of connections to be initiated within the last minute.
+ </para>
+ <para>
+ If the maximum number is reached the proxy delay the first operatation
+ in the session (Thus delaying the connection).
+ </para>
+ </section>
+
+ <section id="proxy-docpath">
+ <title>docpath</title>
+ <para>
+ The element <literal>docpath</literal> is a child of element
+ <literal>proxy</literal> and specifies an allowed HTTP path
+ for local file access. Using <literal>docpath</literal> the
+ proxy may return static file content.
+ </para>
+ <para>
+ The value of docpath both serves as a HTTP path prefix
+ <emphasis>and</emphasis> as a local file prefix.
+ If a value of <literal>etc</literal> is used only URLs with the
+ prefix <literal>/etc/</literal> results in a local file access to the
+ directory <literal>etc</literal> within the working directory
+ of yazproxy.
+ </para>
+ <note>
+ <para>
+ Care has been taken to ensure that hostile URLs are rejected - including
+ strings such as <literal>..</literal> and <literal>/</literal> (absolute
+ file system access).
+ </para>
+ </note>
+ </section>
+
</section>
<section id="proxy-usage">
<title>Proxy Manual Pages</title>
<screen><![CDATA[
<?xml version="1.0"?>
<!-- XML Schema for YAZ proxy config file.
- $Id: reference.xml,v 1.14 2006-03-29 18:09:01 adam Exp $
+ $Id: reference.xml,v 1.15 2006-04-06 01:16:54 adam Exp $
-->
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
<?xml version="1.0"?>
-<!-- $Id: config.xml,v 1.16 2006-03-30 10:35:14 adam Exp $ -->
+<!-- $Id: config.xml,v 1.17 2006-04-06 01:16:54 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>
+ <search>3</search>
</limit>
<attribute type="1" value="1-11,13-1016"/>
<attribute type="1" value="*" error="114"/>
<client-timeout>30</client-timeout>
<!-- everything else -->
</target>
- <max-clients>2</max-clients>
- <max-connect>3</max-connect>
+ <max-clients>30</max-clients>
+ <max-connect>10</max-connect>
+ <limit-connect>5</limit-connect>
<log>client-requests server-requests</log>
+ <docpath>doc</docpath>
</proxy>
<?xml version="1.0"?>
-<!-- $Id: voyager.xml,v 1.6 2005-06-10 17:54:10 adam Exp $ -->
+<!-- $Id: voyager.xml,v 1.7 2006-04-06 01:16:54 adam Exp $ -->
<proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://indexdata.dk/yazproxy/schema/0.9/ yazproxy.xsd"
<bandwidth>200000</bandwidth>
<pdu>31</pdu>
<retrieve>50</retrieve>
+ <search>15</search>
</limit>
<!-- use attributes -->
<!-- what we log. Allowed tokens: client-apdu, server-apdu,
client-requests, server-requests -->
<log>client-requests server-requests</log>
- <xlog></xlog>
+ <!-- <xlog></xlog> -->
+ <max-connect>10</max-connect>
+ <limit-connect>5</limit-connect>
</proxy>
-/* $Id: proxy.h,v 1.29 2006-03-30 10:35:15 adam Exp $
+/* $Id: proxy.h,v 1.30 2006-04-06 01:16:55 adam Exp $
Copyright (c) 1998-2006, Index Data.
This file is part of the yazproxy.
timeout_xsl
} m_timeout_mode;
+ int m_initial_reduce;
int m_connect_max;
+ int m_limit_connect;
int m_search_max;
Yaz_bw m_bw_stat;
int m_pdu_max;
Yaz_bw m_pdu_stat;
int m_max_record_retrieve;
+ Yaz_bw m_search_stat;
+
void handle_max_record_retrieve(Z_APDU *apdu);
void display_diagrecs(Z_DiagRec **pp, int num);
Z_Records *create_nonSurrogateDiagnostics(ODR o, int error,
-/* $Id: proxyp.h,v 1.14 2006-03-30 10:35:15 adam Exp $
+/* $Id: proxyp.h,v 1.15 2006-04-06 01:16:55 adam Exp $
Copyright (c) 1998-2006, Index Data.
This file is part of the yazproxy.
const char **default_client_query_charset);
void get_generic_info(int *log_mask, int *max_clients,
- int *max_connect);
+ int *max_connect, int *limit_connect);
+
+ int get_file_access_info(const char *path);
void get_target_info(const char *name, const char **url,
int *limit_bw, int *limit_pdu, int *limit_req,
-/* $Id: yaz-proxy-config.cpp,v 1.26 2006-03-30 10:35:15 adam Exp $
+/* $Id: yaz-proxy-config.cpp,v 1.27 2006-04-06 01:16:55 adam Exp $
Copyright (c) 1998-2006, Index Data.
This file is part of the yazproxy.
return 0;
}
+int Yaz_ProxyConfig::get_file_access_info(const char *path)
+{
+#if HAVE_XSLT
+ xmlNodePtr ptr;
+ if (!m_cp->m_proxyPtr)
+ return 0;
+ for (ptr = m_cp->m_proxyPtr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "docpath"))
+ {
+ const char *docpath = m_cp->get_text(ptr);
+ size_t docpath_len = strlen(docpath);
+ if (docpath_len < strlen(path) && path[docpath_len] == '/'
+ && !memcmp(docpath, path, docpath_len))
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
void Yaz_ProxyConfig::get_generic_info(int *log_mask,
int *max_clients,
- int *max_connect)
+ int *max_connect,
+ int *limit_connect)
{
*max_connect = 0;
+ *limit_connect = 0;
#if HAVE_XSLT
xmlNodePtr ptr;
if (!m_cp->m_proxyPtr)
v = cp;
}
}
- if (ptr->type == XML_ELEMENT_NODE &&
+ else if (ptr->type == XML_ELEMENT_NODE &&
!strcmp((const char *) ptr->name, "max-clients"))
{
const char *t = m_cp->get_text(ptr);
*max_clients = 1;
}
}
- if (ptr->type == XML_ELEMENT_NODE &&
+ else 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);
}
+ else if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "limit-connect"))
+ {
+ const char *t = m_cp->get_text(ptr);
+ if (t)
+ *limit_connect = atoi(t);
+ }
+ else if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "target"))
+ ;
+ else if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "docpath"))
+ ;
+ else if (ptr->type == XML_ELEMENT_NODE)
+ {
+ yaz_log(YLOG_WARN, "0 Unknown element %s in yazproxy config",
+ ptr->name);
+ }
}
#endif
}
-/* $Id: yaz-proxy.cpp,v 1.48 2006-03-30 14:22:06 adam Exp $
+/* $Id: yaz-proxy.cpp,v 1.49 2006-04-06 01:16:55 adam Exp $
Copyright (c) 1998-2006, Index Data.
This file is part of the yazproxy.
ISocketObservable *the_socket_observable,
Yaz_Proxy *parent)
:
- Z_Assoc(the_PDU_Observable), m_bw_stat(60), m_pdu_stat(60)
+ Z_Assoc(the_PDU_Observable),
+ m_bw_stat(60), m_pdu_stat(60), m_search_stat(60)
{
m_PDU_Observable = the_PDU_Observable;
m_socket_observable = the_socket_observable;
m_pdu_max = 0;
m_search_max = 0;
m_connect_max = 0;
+ m_limit_connect = 0;
m_timeout_mode = timeout_normal;
m_timeout_gdu = 0;
m_max_record_retrieve = 0;
m_ref_count = 1;
m_main_ptr_dec = false;
m_peername = 0;
+ m_initial_reduce = 0;
}
void Yaz_Proxy::inc_ref()
int r = m_config->read_xml(config);
if (!r)
m_config->get_generic_info(&m_log_mask, &m_max_clients,
- &m_connect_max);
+ &m_connect_max, &m_limit_connect);
return r;
}
{
m_log_mask = 0;
cfg->get_generic_info(&m_log_mask, &m_max_clients,
- &m_connect_max);
+ &m_connect_max, &m_limit_connect);
}
}
else
Yaz_Proxy *new_proxy = new Yaz_Proxy(the_PDU_Observable,
m_socket_observable, this);
+
+ if (m_limit_connect)
+ new_proxy->m_initial_reduce = connect_total / m_limit_connect;
+
new_proxy->m_config = 0;
new_proxy->m_config_fname = 0;
new_proxy->timeout(m_client_idletime);
void Yaz_Proxy::convert_records_charset(Z_NamePlusRecordList *p,
const char *backend_charset)
{
- yaz_log(YLOG_LOG, "%sconvert_to_marc", m_session_str);
int sel = m_charset_converter->get_client_charset_selected();
const char *client_record_charset =
m_charset_converter->get_client_query_charset();
yaz_iconv_close(cd);
yaz_marc_destroy(mt);
}
- else
- {
- yaz_log(YLOG_LOG, "%sSkipping marc convert", m_session_str);
- }
}
void Yaz_Proxy::convert_to_marcxml(Z_NamePlusRecordList *p,
void Yaz_Proxy::recv_GDU_reduce(GDU *gdu)
{
- int reduce = 0;
+ int reduce = m_initial_reduce; // initial reduce from connect phase..
+ m_initial_reduce = 0; // reset it..
int bw_total = m_bw_stat.get_total();
int pdu_total = m_pdu_stat.get_total();
+ int search_total = m_search_stat.get_total();
assert(m_timeout_mode == timeout_busy);
assert(m_timeout_gdu == 0);
+ if (m_search_max)
+ reduce += search_total / m_search_max;
if (m_bw_max)
- {
- if (bw_total > m_bw_max)
- {
- reduce = (bw_total/m_bw_max);
- }
- }
+ reduce += (bw_total/m_bw_max);
if (m_pdu_max)
{
if (pdu_total > m_pdu_max)
#endif
if (reduce)
{
- yaz_log(YLOG_LOG, "%sdelay=%d bw=%d pdu=%d limit-bw=%d limit-pdu=%d",
- m_session_str, reduce, bw_total, pdu_total,
- m_bw_max, m_pdu_max);
+ yaz_log(YLOG_LOG, "%sdelay=%d bw=%d pdu=%d search=%d limit-bw=%d limit-pdu=%d limit-search=%d",
+ m_session_str, reduce, bw_total, pdu_total, search_total,
+ m_bw_max, m_pdu_max, m_search_max);
m_timeout_mode = timeout_reduce;
m_timeout_gdu = gdu;
if (strcmp(hreq->method, "GET"))
return 0;
if (hreq->path[0] != '/')
- {
- yaz_log(YLOG_WARN, "Bad path: %s", hreq->path);
return 0;
- }
const char *cp = hreq->path;
while (*cp)
{
if (*cp == '/' && strchr("/.", cp[1]))
{
- yaz_log(YLOG_WARN, "Bad path: %s", hreq->path);
+ yaz_log(YLOG_LOG, "%sRejecting path %s", m_session_str,
+ hreq->path);
return 0;
}
cp++;
}
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+
+ if (!cfg->get_file_access_info(hreq->path+1))
+ return 0;
+
const char *fname = hreq->path+1;
if (stat(fname, &sbuf))
{
- yaz_log(YLOG_WARN|YLOG_ERRNO, "%s: stat failed", fname);
+ yaz_log(YLOG_LOG|YLOG_ERRNO, "%sstat failed for %s", m_session_str,
+ fname);
return 0;
}
if ((sbuf.st_mode & S_IFMT) != S_IFREG)
{
- yaz_log(YLOG_WARN, "%s: not a regular file", fname);
+ yaz_log(YLOG_LOG, "%sNot a regular file %s", m_session_str, fname);
return 0;
}
if (sbuf.st_size > (off_t) 1000000)
{
- yaz_log(YLOG_WARN, "%s: too large for transfer", fname);
+ yaz_log(YLOG_WARN, "%sFile %s too large for transfer", m_session_str,
+ fname);
return 0;
}
ODR o = odr_encode();
- Yaz_ProxyConfig *cfg = check_reconfigure();
+
const char *ctype = cfg->check_mime_type(fname);
Z_GDU *gdu = z_get_HTTP_Response(o, 200);
Z_HTTP_Response *hres = gdu->u.HTTP_Response;
if (srw_pdu->which == Z_SRW_searchRetrieve_request)
{
+
Z_SRW_searchRetrieveRequest *srw_req = srw_pdu->u.request;
const char *backend_db = srw_req->database;
apdu = m_initRequest_apdu; // but throw an init to the target
}
+ if (apdu->which == Z_APDU_searchRequest)
+ m_search_stat.add_bytes(1);
+
// Determine our client.
Z_OtherInformation **oi;
get_otherInfoAPDU(apdu, &oi);