YAZ_INIT(threads)
dnl
+dnl ----- libXML2
+AC_SUBST(XML2_LIBS)
+AC_SUBST(XML2_CFLAGS)
+xml2dir=yes
+AC_ARG_WITH(xml2, [ --with-xml2[=PREFIX] use libxml2 in PREFIX],[xml2dir=$withval])
+if test "$xml2dir" = "yes"; then
+ for d in /usr /usr/local; do
+ if test -x $d/bin/xml2-config; then
+ xml2dir=$d
+ fi
+ done
+fi
+if test "$xml2dir" != "no"; then
+ AC_MSG_CHECKING(for libXML2)
+ if test -x $xml2dir/bin/xml2-config; then
+ XML2_LIBS=`$xml2dir/bin/xml2-config --libs`
+ LIBS="$XML2_LIBS $LIBS"
+ XML2_CFLAGS=`$xml2dir/bin/xml2-config --cflags`
+ XML2_VER=`$xml2dir/bin/xml2-config --version`
+ AC_MSG_RESULT($XML2_VER)
+ AC_DEFINE(HAVE_XML2)
+ else
+ AC_MSG_RESULT(Not found)
+ fi
+fi
+
+dnl
dnl ----- DOCBOOK DTD
AC_SUBST(DTD_DIR)
AC_ARG_WITH(dtd, [ --with-dtd[=DIR] Use docbookx.dtd in DIR],
* Copyright (c) 1998-2000, Index Data.
* See the file LICENSE for details.
*
- * $Id: ir-assoc.h,v 1.1 2002-10-09 12:50:26 adam Exp $
+ * $Id: ir-assoc.h,v 1.2 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz++/z-assoc.h>
/// Destroy assocation and close PDU Observer
virtual ~Yaz_IR_Assoc();
/// Receive Z39.50 PDU
- void recv_Z_PDU(Z_APDU *apdu);
+ void recv_Z_PDU(Z_APDU *apdu, int len);
/// Set Database Names
void set_databaseNames (int num, const char **list);
void set_databaseNames(const char *dblist, const char *sep);
/*
- * Copyright (c) 1998-2000, Index Data.
+ * Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: pdu-assoc.h,v 1.1 2002-10-09 12:50:26 adam Exp $
+ * $Id: pdu-assoc.h,v 1.2 2003-10-01 13:13:51 adam Exp $
*/
#ifndef YAZ_PDU_ASSOC_INCLUDED
void idleTime (int timeout);
/// Child start...
virtual void childNotify(COMSTACK cs);
+ const char *getpeername();
};
class YAZ_EXPORT Yaz_PDU_AssocThread : public Yaz_PDU_Assoc {
* Copyright (c) 1998-2000, Index Data.
* See the file LICENSE for details.
*
- * $Id: pdu-observer.h,v 1.1 2002-10-09 12:50:26 adam Exp $
+ * $Id: pdu-observer.h,v 1.2 2003-10-01 13:13:51 adam Exp $
*/
#ifndef YAZ_PDU_OBSERVER_H
virtual void destroy() = 0;
/// Set Idle Time
virtual void idleTime (int timeout) = 0;
+ /// Get peername
+ virtual const char *getpeername() = 0;
};
/** Protocol Data Unit Observer.
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: proxy.h,v 1.7 2003-09-04 20:11:03 adam Exp $
+ * $Id: proxy.h,v 1.8 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz++/z-assoc.h>
#include <yaz++/z-query.h>
#include <yaz++/z-databases.h>
+#if HAVE_XML2
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
class Yaz_Proxy;
struct Yaz_RecordCache_Entry;
+class YAZ_EXPORT Yaz_ProxyConfig {
+public:
+ Yaz_ProxyConfig();
+ ~Yaz_ProxyConfig();
+ int read_xml(const char *fname);
+ void get_target_info(const char *name, const char **url, int *keepalive,
+ int *limit_bw, int *limit_pdu, int *limit_req);
+ void operator=(const Yaz_ProxyConfig &conf);
+private:
+#if HAVE_XML2
+ xmlDocPtr m_docPtr;
+ xmlNodePtr m_proxyPtr;
+ void return_target_info(xmlNodePtr ptr, const char **url, int *keepalive,
+ int *limit_bw, int *limit_pdu, int *limit_req);
+ void return_limit(xmlNodePtr ptr,
+ int *limit_bw, int *limit_pdu, int *limit_req);
+ const char *get_text(xmlNodePtr ptr);
+#endif
+ int m_copy;
+};
+
class YAZ_EXPORT Yaz_RecordCache {
public:
Yaz_RecordCache ();
Z_RecordComposition *comp);
};
+class YAZ_EXPORT Yaz_bw {
+ public:
+ Yaz_bw(int sz);
+ ~Yaz_bw();
+ void add_bytes(int m);
+ int get_total();
+ private:
+ long m_sec; // time of most recent bucket
+ int *m_bucket;
+ int m_ptr;
+ int m_size;
+};
+
/// Private class
class YAZ_EXPORT Yaz_ProxyClient : public Yaz_Z_Assoc {
friend class Yaz_Proxy;
Yaz_ProxyClient(IYaz_PDU_Observable *the_PDU_Observable);
~Yaz_ProxyClient();
- void recv_Z_PDU(Z_APDU *apdu);
+ void recv_Z_PDU(Z_APDU *apdu, int len);
IYaz_PDU_Observer* sessionNotify
(IYaz_PDU_Observable *the_PDU_Observable, int fd);
void shutdown();
void failNotify();
void timeoutNotify();
void connectNotify();
+ int send_to_target(Z_APDU *apdu);
+ const char *get_session_str();
char *m_cookie;
Yaz_ProxyClient *m_next;
Yaz_ProxyClient **m_prev;
int m_seqno;
int m_waiting;
int m_resultSetStartPoint;
+ int m_bytes_sent;
+ int m_bytes_recv;
ODR m_init_odr;
Z_APDU *m_initResponse;
Yaz_RecordCache m_cache;
int m_seqno;
int m_max_clients;
int m_keepalive;
- int m_idletime;
+ int m_client_idletime;
+ int m_target_idletime;
char *m_proxyTarget;
+ char *m_default_target;
char *m_proxy_authentication;
long m_seed;
char *m_optimize;
+ int m_session_no; // sequence for each client session
+ char m_session_str[20]; // session string (time:session_no)
+ Yaz_ProxyConfig m_config;
+ int m_bytes_sent;
+ int m_bytes_recv;
+ int m_bw_max;
+ Yaz_bw m_bw_stat;
+ int m_pdu_max;
+ Yaz_bw m_pdu_stat;
+ Z_APDU *m_bw_hold_PDU;
+ int m_max_record_retrieve;
+ void handle_max_record_retrieve(Z_APDU *apdu);
+ void display_diagrecs(Z_DiagRec **pp, int num);
public:
Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable);
~Yaz_Proxy();
- void recv_Z_PDU(Z_APDU *apdu);
+ void recv_Z_PDU(Z_APDU *apdu, int len);
+ void recv_Z_PDU_0(Z_APDU *apdu);
IYaz_PDU_Observer* sessionNotify
(IYaz_PDU_Observable *the_PDU_Observable, int fd);
void failNotify();
void timeoutNotify();
void connectNotify();
const char *option(const char *name, const char *value);
- void set_proxy_target(const char *target);
+ void set_default_target(const char *target);
void set_proxy_authentication (const char *auth);
char *get_proxy_target() { return m_proxyTarget; };
+ char *get_session_str() { return m_session_str; };
void set_max_clients(int m) { m_max_clients = m; };
- void set_idletime (int t) { m_idletime = (t > 1) ? t : 600; };
+ void set_client_idletime (int t) { m_client_idletime = (t > 1) ? t : 600; };
+ void set_target_idletime (int t) { m_target_idletime = (t > 1) ? t : 600; };
+ int get_target_idletime () { return m_target_idletime; }
+ int set_config(const char *name);
+ int send_to_client(Z_APDU *apdu);
};
* Copyright (c) 1998-2000, Index Data.
* See the file LICENSE for details.
*
- * $Id: z-assoc.h,v 1.1 2002-10-09 12:50:26 adam Exp $
+ * $Id: z-assoc.h,v 1.2 2003-10-01 13:13:51 adam Exp $
*/
#ifndef YAZ_Z_ASSOC_INCLUDED
/// Encode Z39.50 PDU.
int encode_Z_PDU(Z_APDU *apdu, char **buf, int *len);
/// Send Z39.50 PDU
- int send_Z_PDU(Z_APDU *apdu);
+ int send_Z_PDU(Z_APDU *apdu, int *len);
/// Receive Z39.50 PDU
- virtual void recv_Z_PDU(Z_APDU *apdu) = 0;
+ virtual void recv_Z_PDU(Z_APDU *apdu, int len) = 0;
/// Create Z39.50 PDU with reasonable defaults
Z_APDU *create_Z_PDU(int type);
/// Request Alloc
* Copyright (c) 1998-2000, Index Data.
* See the file LICENSE for details.
*
- * $Id: z-query.h,v 1.1 2002-10-09 12:50:26 adam Exp $
+ * $Id: z-query.h,v 1.2 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/proto.h>
ODR odr_decode;
ODR odr_encode;
ODR odr_print;
+ void oid2str(Odr_oid *o, WRBUF buf);
+ int rpn2pquery(Z_RPNStructure *s, WRBUF buf);
+ WRBUF zquery2pquery(Z_Query *q);
+ void pr_term(WRBUF wbuf, char *buf, int len);
};
* Copyright (c) 2000-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: z-server.h,v 1.2 2002-10-28 12:16:09 adam Exp $
+ * $Id: z-server.h,v 1.3 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz++/z-assoc.h>
public:
Yaz_Z_Server(IYaz_PDU_Observable *the_PDU_Observable);
virtual ~Yaz_Z_Server();
- virtual void recv_Z_PDU(Z_APDU *apdu);
+ virtual void recv_Z_PDU(Z_APDU *apdu, int len);
void facility_add(IYaz_Server_Facility *facility, const char *name);
void facility_reset ();
-## $Id: Makefile.am,v 1.14 2003-07-18 13:27:20 adam Exp $
+## $Id: Makefile.am,v 1.15 2003-10-01 13:13:51 adam Exp $
-AM_CXXFLAGS = $(YAZINC) -I$(srcdir)/../include
+AM_CXXFLAGS = $(YAZINC) -I$(srcdir)/../include $(XML2_CFLAGS)
noinst_LTLIBRARIES = libyazcpp.la
yaz-z-assoc.cpp yaz-proxy.cpp yaz-z-query.cpp yaz-ir-assoc.cpp \
yaz-z-server.cpp yaz-pdu-assoc-thread.cpp yaz-z-server-sr.cpp \
yaz-z-server-ill.cpp yaz-z-server-update.cpp yaz-z-databases.cpp \
- yaz-z-cache.cpp
+ yaz-z-cache.cpp yaz-proxy-config.cpp yaz-bw.cpp
bin_PROGRAMS = yaz-proxy
noinst_PROGRAMS = yaz-my-server yaz-my-client
--- /dev/null
+/*
+ * Copyright (c) 2000-2003, Index Data.
+ * See the file LICENSE for details.
+ *
+ * $Id: yaz-bw.cpp,v 1.1 2003-10-01 13:13:51 adam Exp $
+ */
+
+#include <time.h>
+#include <yaz/log.h>
+#include <yaz++/proxy.h>
+
+
+Yaz_bw::Yaz_bw(int sz)
+{
+ m_sec = 0;
+ m_size = sz;
+ m_bucket = new int[m_size];
+ m_ptr = 0;
+}
+
+Yaz_bw::~Yaz_bw()
+{
+ delete [] m_bucket;
+}
+
+int Yaz_bw::get_total()
+{
+ add_bytes(0);
+ int bw = 0;
+ int i;
+ for (i = 0; i<m_size; i++)
+ bw += m_bucket[i];
+ return bw;
+}
+
+void Yaz_bw::add_bytes(int b)
+{
+ long now = time(0);
+
+ int d = now - m_sec;
+ if (d > m_size)
+ d = m_size;
+ while (--d >= 0)
+ {
+ if (++m_ptr == m_size)
+ m_ptr = 0;
+ m_bucket[m_ptr] = 0;
+ }
+ m_bucket[m_ptr] += b;
+ m_sec = now;
+}
+
/*
- * Copyright (c) 1998-2000, Index Data.
+ * Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-ir-assoc.cpp,v 1.18 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-ir-assoc.cpp,v 1.19 2003-10-01 13:13:51 adam Exp $
*/
#include <assert.h>
*elementSetName = m_elementSetNames->u.generic;
}
-void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu)
+void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu, int len)
{
- yaz_log (m_log, "recv_Z_PDU");
+ yaz_log (m_log, "recv_Z_PDU %d bytes", len);
m_lastReceived = apdu->which;
switch (apdu->which)
{
req->resultSetName = pResultSetId;
}
- return send_Z_PDU(apdu);
+ return send_Z_PDU(apdu, 0);
}
int Yaz_IR_Assoc::send_presentRequest(int start,
req->resultSetId = pResultSetId;
}
- return send_Z_PDU(apdu);
+ return send_Z_PDU(apdu, 0);
}
void Yaz_IR_Assoc::set_proxy(const char *str)
void Yaz_IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
{
Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
- send_Z_PDU(apdu);
+ send_Z_PDU(apdu, 0);
}
void Yaz_IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
{
Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
- send_Z_PDU(apdu);
+ send_Z_PDU(apdu, 0);
}
void Yaz_IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
{
Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
- send_Z_PDU(apdu);
+ send_Z_PDU(apdu, 0);
}
void Yaz_IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
if (m_cookie)
set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
- return send_Z_PDU(apdu);
+ return send_Z_PDU(apdu, 0);
}
int Yaz_IR_Assoc::send_deleteResultSetRequest(char* pResultSetId, char* pRefId)
if (m_cookie)
set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
-
- return send_Z_PDU(apdu);
+ return send_Z_PDU(apdu, 0);
}
/*
- * Copyright (c) 1998-2001, Index Data.
+ * Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-my-client.cpp,v 1.12 2002-10-28 12:16:09 adam Exp $
+ * $Id: yaz-my-client.cpp,v 1.13 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
* Copyright (c) 1998-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-pdu-assoc.cpp,v 1.29 2003-07-25 19:27:36 adam Exp $
+ * $Id: yaz-pdu-assoc.cpp,v 1.30 2003-10-01 13:13:51 adam Exp $
*/
#include <assert.h>
res);
m_socketObservable->addObserver(cs_fileno(m_cs), this);
- if (res >= 0)
- { // Connect pending or complete
+ if (res == 0)
+ { // Connect complete
+ m_state = Connecting;
+ unsigned mask = YAZ_SOCKET_OBSERVE_EXCEPT;
+ mask |= YAZ_SOCKET_OBSERVE_WRITE;
+ mask |= YAZ_SOCKET_OBSERVE_READ;
+ yaz_log(m_log, "maskObserver 11");
+ m_socketObservable->maskObserver(this, mask);
+ }
+ else if (res > 0)
+ { // Connect pending
m_state = Connecting;
unsigned mask = YAZ_SOCKET_OBSERVE_EXCEPT;
if (m_cs->io_pending & CS_WANT_WRITE)
new_observable->m_PDU_Observer = m_PDU_Observer->sessionNotify
(new_observable, cs_fileno(cs));
}
+
+const char*Yaz_PDU_Assoc::getpeername()
+{
+ return cs_addrstr(m_cs);
+}
--- /dev/null
+/*
+ * Copyright (c) 1998-2003, Index Data.
+ * See the file LICENSE for details.
+ *
+ * $Id: yaz-proxy-config.cpp,v 1.1 2003-10-01 13:13:51 adam Exp $
+ */
+
+#include <yaz/log.h>
+#include <yaz++/proxy.h>
+
+Yaz_ProxyConfig::Yaz_ProxyConfig()
+{
+ m_copy = 0;
+#if HAVE_XML2
+ m_docPtr = 0;
+ m_proxyPtr = 0;
+#endif
+}
+
+Yaz_ProxyConfig::~Yaz_ProxyConfig()
+{
+#if HAVE_XML2
+ if (!m_copy && m_docPtr)
+ xmlFreeDoc(m_docPtr);
+#endif
+}
+
+void Yaz_ProxyConfig::operator=(const Yaz_ProxyConfig &conf)
+{
+#if HAVE_XML2
+ m_docPtr = conf.m_docPtr;
+ m_proxyPtr = conf.m_proxyPtr;
+#endif
+ m_copy = 1;
+}
+
+int Yaz_ProxyConfig::read_xml(const char *fname)
+{
+#if HAVE_XML2
+ xmlDocPtr ndoc = xmlParseFile(fname);
+
+ if (!ndoc)
+ {
+ yaz_log(LOG_WARN, "Config file %s not found or parse error", fname);
+ return -1; // no good
+ }
+ xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
+ if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
+ strcmp((const char *) proxyPtr->name, "proxy"))
+ {
+ yaz_log(LOG_WARN, "No proxy element in %s", fname);
+ xmlFreeDoc(ndoc);
+ return -1;
+ }
+ m_proxyPtr = proxyPtr;
+
+ // OK: release previous and make it the current one.
+ if (m_docPtr)
+ xmlFreeDoc(m_docPtr);
+ m_docPtr = ndoc;
+ return 0;
+#else
+ return -2;
+#endif
+}
+
+#if HAVE_XML2
+const char *Yaz_ProxyConfig::get_text(xmlNodePtr ptr)
+{
+ for(ptr = ptr->children; ptr; ptr = ptr->next)
+ if (ptr->type == XML_TEXT_NODE)
+ {
+ xmlChar *t = ptr->content;
+ if (t)
+ {
+ while (*t == ' ')
+ t++;
+ return (const char *) t;
+ }
+ }
+ return 0;
+}
+#endif
+
+#if HAVE_XML2
+void Yaz_ProxyConfig::return_limit(xmlNodePtr ptr,
+ int *limit_bw,
+ int *limit_pdu,
+ int *limit_req)
+{
+ for (ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "bandwidth"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ *limit_bw = atoi(t);
+ }
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "retrieve"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ *limit_req = atoi(t);
+ }
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "pdu"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ *limit_pdu = atoi(t);
+ }
+ }
+}
+#endif
+
+#if HAVE_XML2
+void Yaz_ProxyConfig::return_target_info(xmlNodePtr ptr,
+ const char **url,
+ int *keepalive,
+ int *limit_bw,
+ int *limit_pdu,
+ int *limit_req)
+{
+ ptr = ptr->children;
+ for (; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "url"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ *url = t;
+ }
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "keepalive"))
+ {
+ const char *t = get_text(ptr);
+ if (!t || *t == '1')
+ *keepalive = 1;
+ else
+ *keepalive = 0;
+ }
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "limit"))
+ return_limit(ptr, limit_bw, limit_pdu, limit_req);
+ }
+}
+#endif
+
+void Yaz_ProxyConfig::get_target_info(const char *name,
+ const char **url,
+ int *keepalive,
+ int *limit_bw,
+ int *limit_pdu,
+ int *limit_req)
+{
+#if HAVE_XML2
+ xmlNodePtr ptr;
+ if (!m_proxyPtr)
+ {
+ *url = name;
+ return;
+ }
+ for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "target"))
+ {
+ // default one ?
+ if (!name)
+ {
+ // <target default="1"> ?
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ if (!strcmp((const char *) attr->name, "default") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ {
+ xmlChar *t = attr->children->content;
+ if (!t || *t == '1')
+ {
+ return_target_info(ptr, url, keepalive,
+ limit_bw, limit_pdu, limit_req);
+ return;
+ }
+ }
+ }
+ else
+ {
+ // <target name="name"> ?
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ if (!strcmp((const char *) attr->name, "name"))
+ {
+ if (attr->children
+ && attr->children->type==XML_TEXT_NODE
+ && attr->children->content
+ && (!strcmp((const char *) attr->children->content,
+ name)
+ || !strcmp((const char *) attr->children->content,
+ "*")))
+ {
+ *url = name;
+ return_target_info(ptr, url, keepalive,
+ limit_bw, limit_pdu, limit_req);
+ return;
+ }
+ }
+ }
+ }
+ }
+#else
+ *url = name;
+ return;
+#endif
+}
+
+
* Copyright (c) 1998-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy-main.cpp,v 1.18 2002-10-23 10:15:18 adam Exp $
+ * $Id: yaz-proxy-main.cpp,v 1.19 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
void usage(char *prog)
{
- fprintf (stderr, "%s: [-a log] [-c num] [-v level] [-t target] [-i sec] "
+ fprintf (stderr, "%s: [-c config] [-a log] [-m num] [-v level] [-t target] [-i sec] "
"[-u auth] [-o optlevel] @:port\n", prog);
exit (1);
}
char *prog = argv[0];
int ret;
- while ((ret = options("o:a:t:v:c:u:i:", argv, argc, &arg)) != -2)
+ while ((ret = options("o:a:t:v:c:u:i:m:l:T:", argv, argc, &arg)) != -2)
{
+ int err;
switch (ret)
{
case 0:
}
addr = arg;
break;
+ case 'c':
+ err = proxy->set_config(arg);
+ if (err == -2)
+ {
+ fprintf(stderr, "Config file support not enabled (proxy not compiled with libxml2 support)\n");
+ exit(1);
+ }
+ else if (err == -1)
+ {
+ fprintf(stderr, "Bad or missing file %s\n", arg);
+ exit(1);
+ }
+ break;
case 'a':
proxy->set_APDU_log(arg);
break;
case 't':
- proxy->set_proxy_target(arg);
+ proxy->set_default_target(arg);
break;
case 'u':
proxy->set_proxy_authentication(arg);
case 'v':
yaz_log_init_level (yaz_log_mask_str(arg));
break;
- case 'c':
+ case 'l':
+ yaz_log_init_file (arg);
+ break;
+ case 'm':
proxy->set_max_clients(atoi(arg));
break;
case 'i':
- proxy->set_idletime(atoi(arg));
+ proxy->set_client_idletime(atoi(arg));
+ break;
+ case 'T':
+ proxy->set_target_idletime(atoi(arg));
break;
default:
usage(prog);
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy.cpp,v 1.47 2003-09-03 11:30:26 adam Exp $
+ * $Id: yaz-proxy.cpp,v 1.48 2003-10-01 13:13:51 adam Exp $
*/
#include <assert.h>
#include <time.h>
#include <yaz/log.h>
+#include <yaz/diagbib1.h>
#include <yaz++/proxy.h>
+static const char *apdu_name(Z_APDU *apdu)
+{
+ switch (apdu->which)
+ {
+ case Z_APDU_initRequest:
+ return "initRequest";
+ case Z_APDU_initResponse:
+ return "initResponse";
+ case Z_APDU_searchRequest:
+ return "searchRequest";
+ case Z_APDU_searchResponse:
+ return "searchResponse";
+ case Z_APDU_presentRequest:
+ return "presentRequest";
+ case Z_APDU_presentResponse:
+ return "presentResponse";
+ case Z_APDU_deleteResultSetRequest:
+ return "deleteResultSetRequest";
+ case Z_APDU_deleteResultSetResponse:
+ return "deleteResultSetResponse";
+ case Z_APDU_scanRequest:
+ return "scanRequest";
+ case Z_APDU_scanResponse:
+ return "scanResponse";
+ case Z_APDU_sortRequest:
+ return "sortRequest";
+ case Z_APDU_sortResponse:
+ return "sortResponse";
+ case Z_APDU_extendedServicesRequest:
+ return "extendedServicesRequest";
+ case Z_APDU_extendedServicesResponse:
+ return "extendedServicesResponse";
+ case Z_APDU_close:
+ return "close";
+ }
+ return "other";
+}
+
+
Yaz_Proxy::Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable) :
- Yaz_Z_Assoc(the_PDU_Observable)
+ Yaz_Z_Assoc(the_PDU_Observable), m_bw_stat(60), m_pdu_stat(60)
{
m_PDU_Observable = the_PDU_Observable;
m_client = 0;
m_parent = 0;
m_clientPool = 0;
m_seqno = 1;
- m_keepalive = 1;
+ m_keepalive = 0;
m_proxyTarget = 0;
+ m_default_target = 0;
m_proxy_authentication = 0;
m_max_clients = 150;
m_seed = time(0);
- m_idletime = 600;
+ m_client_idletime = 600;
+ m_target_idletime = 600;
m_optimize = xstrdup ("1");
+ strcpy(m_session_str, "x");
+ m_session_no=0;
+ m_bytes_sent = m_bytes_recv = 0;
+ m_bw_hold_PDU = 0;
+ m_bw_max = 0;
+ m_pdu_max = 0;
+ m_max_record_retrieve = 0;
}
Yaz_Proxy::~Yaz_Proxy()
{
+ yaz_log(LOG_LOG, "%s Closed %d/%d sent/recv bytes total", m_session_str,
+ m_bytes_sent, m_bytes_recv);
xfree (m_proxyTarget);
+ xfree (m_default_target);
xfree (m_proxy_authentication);
xfree (m_optimize);
}
-void Yaz_Proxy::set_proxy_target(const char *target)
+int Yaz_Proxy::set_config(const char *config)
{
- xfree (m_proxyTarget);
- m_proxyTarget = 0;
+ int r = m_config.read_xml(config);
+ return r;
+}
+
+void Yaz_Proxy::set_default_target(const char *target)
+{
+ xfree (m_default_target);
+ m_default_target = 0;
if (target)
- m_proxyTarget = (char *) xstrdup (target);
+ m_default_target = (char *) xstrdup (target);
}
void Yaz_Proxy::set_proxy_authentication (const char *auth)
{
Yaz_Proxy *new_proxy = new Yaz_Proxy(the_PDU_Observable);
new_proxy->m_parent = this;
- new_proxy->timeout(m_idletime);
- new_proxy->set_proxy_target(m_proxyTarget);
+ new_proxy->m_config = m_config;
+ new_proxy->timeout(m_client_idletime);
+ new_proxy->m_target_idletime = m_target_idletime;
+ new_proxy->set_default_target(m_default_target);
new_proxy->set_APDU_log(get_APDU_log());
new_proxy->set_proxy_authentication(m_proxy_authentication);
- yaz_log (LOG_LOG, "New session p=%p", new_proxy);
+ sprintf(new_proxy->m_session_str, "%ld:%d", (long) time(0), m_session_no);
+ m_session_no++;
+ yaz_log (LOG_LOG, "%s New session %s", new_proxy->m_session_str,
+ the_PDU_Observable->getpeername());
return new_proxy;
}
get_otherInfoAPDU(apdu, &oi);
char *cookie = get_cookie(oi);
- const char *proxy_host = get_proxy(oi);
- if (proxy_host)
- set_proxy_target(proxy_host);
-
- // no target specified at all?
if (!m_proxyTarget)
- return 0;
-
- if (!strcmp(m_proxyTarget, "stop"))
- exit (0);
+ {
+ const char *proxy_host = get_proxy(oi);
+ if (!proxy_host)
+ proxy_host = m_default_target;
+
+ const char *url = 0;
+ m_config.get_target_info(proxy_host, &url, &m_keepalive, &m_bw_max,
+ &m_pdu_max, &m_max_record_retrieve);
+
+ if (!url)
+ {
+ yaz_log(LOG_LOG, "%s No default target", m_session_str);
+ return 0;
+ }
+ m_proxyTarget = (char*) xstrdup(url);
+ }
if (cookie && *cookie)
{
Yaz_ProxyClient *cc = 0;
// we have an initRequest we can safely do re-open
if (c->m_waiting && apdu->which == Z_APDU_initRequest)
{
- yaz_log (LOG_LOG, "reopen target=%s", c->get_hostname());
+ yaz_log (LOG_LOG, "%s REOPEN target=%s", m_session_str,
+ c->get_hostname());
c->close();
c->client(m_proxyTarget);
c->m_init_flag = 0;
c->m_sr_transform = 0;
c->m_waiting = 0;
c->m_resultSetStartPoint = 0;
- c->timeout(m_idletime);
+ c->timeout(m_target_idletime);
}
c->m_seqno = parent->m_seqno;
if (c->m_server && c->m_server != this)
// found it in cache
c = cc;
- yaz_log (LOG_LOG, "Reuse session %d to %d %s",
+ yaz_log (LOG_LOG, "%s REUSE %d %d %s",
+ m_session_str,
c->m_seqno, parent->m_seqno, c->get_hostname());
c->m_seqno = parent->m_seqno;
c = c_min;
if (c->m_waiting || strcmp(m_proxyTarget, c->get_hostname()))
{
- yaz_log (LOG_LOG, "Replace session %d",
- c->m_seqno);
+ yaz_log (LOG_LOG, "%s MAXCLIENTS Destroy %d",
+ m_session_str, c->m_seqno);
if (c->m_server && c->m_server != this)
delete c->m_server;
c->m_server = 0;
}
else
{
- yaz_log (LOG_LOG, "Move session %d to %d %s",
- c->m_seqno, parent->m_seqno, c->get_hostname());
+ yaz_log (LOG_LOG, "%s MAXCLIENTS Reuse %d %d %s",
+ m_session_str,
+ c->m_seqno, parent->m_seqno, c->get_hostname());
xfree (c->m_cookie);
c->m_cookie = 0;
if (cookie)
delete c->m_server;
}
(parent->m_seqno)++;
- yaz_log (LOG_DEBUG, "get_client 2 %p %p", this, c);
return c;
}
}
else
{
- yaz_log (LOG_LOG, "Making session %d %s", parent->m_seqno,
- m_proxyTarget);
+ yaz_log (LOG_LOG, "%s NEW %d %s",
+ m_session_str, parent->m_seqno, m_proxyTarget);
c = new Yaz_ProxyClient(m_PDU_Observable->clone());
c->m_next = parent->m_clientPool;
if (c->m_next)
if (cookie)
c->m_cookie = xstrdup(cookie);
- yaz_log (LOG_LOG, "Connecting to %s", m_proxyTarget);
c->m_seqno = parent->m_seqno;
c->client(m_proxyTarget);
c->m_init_flag = 0;
c->m_sr_transform = 0;
c->m_waiting = 0;
c->m_resultSetStartPoint = 0;
- c->timeout(20);
+ c->timeout(30);
(parent->m_seqno)++;
}
return c;
}
+void Yaz_Proxy::display_diagrecs(Z_DiagRec **pp, int num)
+{
+ int i;
+ for (i = 0; i<num; i++)
+ {
+ oident *ent;
+ Z_DefaultDiagFormat *r;
+ Z_DiagRec *p = pp[i];
+ if (p->which != Z_DiagRec_defaultFormat)
+ {
+ yaz_log(LOG_LOG, "%s Error no diagnostics", m_session_str);
+ return;
+ }
+ else
+ r = p->u.defaultFormat;
+ if (!(ent = oid_getentbyoid(r->diagnosticSetId)) ||
+ ent->oclass != CLASS_DIAGSET || ent->value != VAL_BIB1)
+ yaz_log(LOG_LOG, "%s Error unknown diagnostic set", m_session_str);
+ switch (r->which)
+ {
+ case Z_DefaultDiagFormat_v2Addinfo:
+ yaz_log(LOG_LOG, "%s Error %d %s:%s",
+ m_session_str,
+ *r->condition, diagbib1_str(*r->condition),
+ r->u.v2Addinfo);
+ break;
+ case Z_DefaultDiagFormat_v3Addinfo:
+ yaz_log(LOG_LOG, "%s Error %d %s:%s",
+ m_session_str,
+ *r->condition, diagbib1_str(*r->condition),
+ r->u.v3Addinfo);
+ break;
+ }
+ }
+}
+
+int Yaz_Proxy::send_to_client(Z_APDU *apdu)
+{
+ int len = 0;
+ if (apdu->which == Z_APDU_searchResponse)
+ {
+ Z_SearchResponse *sr = apdu->u.searchResponse;
+ Z_Records *p = sr->records;
+ if (p && p->which == Z_Records_NSD)
+ {
+ Z_DiagRec dr, *dr_p = &dr;
+ dr.which = Z_DiagRec_defaultFormat;
+ dr.u.defaultFormat = p->u.nonSurrogateDiagnostic;
+
+ display_diagrecs(&dr_p, 1);
+ }
+ else
+ {
+ if (sr->resultCount)
+ yaz_log(LOG_LOG, "%s %d hits", m_session_str,
+ *sr->resultCount);
+ }
+ }
+ else if (apdu->which == Z_APDU_presentResponse)
+ {
+ Z_PresentResponse *sr = apdu->u.presentResponse;
+ Z_Records *p = sr->records;
+ if (p && p->which == Z_Records_NSD)
+ {
+ Z_DiagRec dr, *dr_p = &dr;
+ dr.which = Z_DiagRec_defaultFormat;
+ dr.u.defaultFormat = p->u.nonSurrogateDiagnostic;
+
+ display_diagrecs(&dr_p, 1);
+ }
+ }
+ int r = send_Z_PDU(apdu, &len);
+ yaz_log (LOG_LOG, "%s Sending %s to client %d bytes", m_session_str,
+ apdu_name(apdu), len);
+ m_bytes_sent += len;
+ m_bw_stat.add_bytes(len);
+ return r;
+}
+
+int Yaz_ProxyClient::send_to_target(Z_APDU *apdu)
+{
+ int len = 0;
+ int r = send_Z_PDU(apdu, &len);
+ yaz_log (LOG_LOG, "%s Sending %s to %s %d bytes",
+ get_session_str(),
+ apdu_name(apdu), get_hostname(), len);
+ m_bytes_sent += len;
+ return r;
+}
+
Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu)
{
if (*m_parent->m_optimize == '0')
pr->preferredRecordSyntax,
pr->recordComposition))
{
- yaz_log (LOG_LOG, "Returned cache records for present request");
+ yaz_log (LOG_LOG, "%s Returned cache records for present request",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentResponse);
new_apdu->u.presentResponse->referenceId = pr->referenceId;
new_apdu->u.presentResponse->records->u.databaseOrSurDiagnostics = npr;
new_apdu->u.presentResponse->nextResultSetPosition =
odr_intdup(odr_encode(), start+toget);
- send_Z_PDU(new_apdu);
+
+ send_to_client(new_apdu);
return 0;
}
}
sr->databaseNames);
this_query->set_Z_Query(sr->query);
-
+
+ char query_str[80];
+ this_query->print(query_str, sizeof(query_str)-1);
+ yaz_log(LOG_LOG, "%s Query %s", m_session_str, query_str);
+
if (m_client->m_last_ok && m_client->m_last_query &&
m_client->m_last_query->match(this_query) &&
!strcmp(m_client->m_last_resultSetId, sr->resultSetName) &&
if (m_client->m_cache.lookup (odr_encode(), &npr, 1, toget,
sr->preferredRecordSyntax, comp))
{
- yaz_log (LOG_LOG, "Returned cache records for medium set");
+ yaz_log (LOG_LOG, "%s Returned cache records for medium set",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
new_apdu->u.searchResponse->referenceId = sr->referenceId;
new_apdu->u.searchResponse->resultCount =
new_apdu->u.searchResponse->records->u.databaseOrSurDiagnostics = npr;
new_apdu->u.searchResponse->nextResultSetPosition =
odr_intdup(odr_encode(), toget+1);
- send_Z_PDU(new_apdu);
+ send_to_client(new_apdu);
return 0;
}
else
{
// medium Set
// send present request (medium size)
- yaz_log (LOG_LOG, "Optimizing search for medium set");
+ yaz_log (LOG_LOG, "%s Optimizing search for medium set",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest);
Z_PresentRequest *pr = new_apdu->u.presentRequest;
m_client->m_last_resultCount <= 0)
{
// large set. Return pseudo-search response immediately
- yaz_log (LOG_LOG, "Optimizing search for large set");
+ yaz_log (LOG_LOG, "%s Optimizing search for large set",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
new_apdu->u.searchResponse->referenceId = sr->referenceId;
new_apdu->u.searchResponse->resultCount =
&m_client->m_last_resultCount;
- send_Z_PDU(new_apdu);
+ send_to_client(new_apdu);
return 0;
}
else
if (m_client->m_cache.lookup (odr_encode(), &npr, 1, toget,
sr->preferredRecordSyntax, comp))
{
- yaz_log (LOG_LOG, "Returned cache records for small set");
+ yaz_log (LOG_LOG, "%s Returned cache records for small set",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
new_apdu->u.searchResponse->referenceId = sr->referenceId;
new_apdu->u.searchResponse->resultCount =
new_apdu->u.searchResponse->records->u.databaseOrSurDiagnostics = npr;
new_apdu->u.searchResponse->nextResultSetPosition =
odr_intdup(odr_encode(), toget+1);
- send_Z_PDU(new_apdu);
+ send_to_client(new_apdu);
return 0;
}
else
{
- yaz_log (LOG_LOG, "Optimizing search for small set");
+ yaz_log (LOG_LOG, "%s Optimizing search for small set",
+ m_session_str);
Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest);
Z_PresentRequest *pr = new_apdu->u.presentRequest;
pr->referenceId = sr->referenceId;
return apdu;
}
-static const char *apdu_name(Z_APDU *apdu)
+
+void Yaz_Proxy::recv_Z_PDU(Z_APDU *apdu, int len)
{
- switch (apdu->which)
+ int reduce = 0;
+ m_bytes_recv += len;
+
+ yaz_log (LOG_LOG, "%s Receiving %s from client %d bytes", m_session_str,
+ apdu_name(apdu), len);
+
+ if (m_bw_hold_PDU) // double incoming PDU. shutdown now.
+ shutdown();
+
+ m_bw_stat.add_bytes(len);
+ m_pdu_stat.add_bytes(1);
+
+ int bw_total = m_bw_stat.get_total();
+ int pdu_total = m_pdu_stat.get_total();
+
+ yaz_log(LOG_LOG, "%s stat bw=%d pdu=%d limit-bw=%d limit-pdu=%d",
+ m_session_str, bw_total, pdu_total, m_bw_max, m_pdu_max);
+ if (m_bw_max)
{
- case Z_APDU_initRequest:
- return "initRequest";
- case Z_APDU_initResponse:
- return "initResponse";
- case Z_APDU_searchRequest:
- return "searchRequest";
- case Z_APDU_searchResponse:
- return "searchResponse";
- case Z_APDU_presentRequest:
- return "presentRequest";
- case Z_APDU_presentResponse:
- return "presentResponse";
- case Z_APDU_deleteResultSetRequest:
- return "deleteResultSetRequest";
- case Z_APDU_deleteResultSetResponse:
- return "deleteResultSetResponse";
- case Z_APDU_scanRequest:
- return "scanRequest";
- case Z_APDU_scanResponse:
- return "scanResponse";
- case Z_APDU_sortRequest:
- return "sortRequest";
- case Z_APDU_sortResponse:
- return "sortResponse";
- case Z_APDU_extendedServicesRequest:
- return "extendedServicesRequest";
- case Z_APDU_extendedServicesResponse:
- return "extendedServicesResponse";
- case Z_APDU_close:
- return "close";
+ if (bw_total > m_bw_max)
+ {
+ reduce = (bw_total/m_bw_max);
+ }
}
- return "other";
+ if (m_pdu_max)
+ {
+ if (pdu_total > m_pdu_max)
+ {
+ int nreduce = (60/m_pdu_max);
+ reduce = (reduce > nreduce) ? reduce : nreduce;
+ }
+ }
+ if (reduce)
+ {
+ yaz_log(LOG_LOG, "%s Limit delay=%d", m_session_str, reduce);
+ m_bw_hold_PDU = apdu; // save PDU and signal "on hold"
+ timeout(reduce); // call us reduce seconds later
+ }
+ else
+ recv_Z_PDU_0(apdu); // all fine. Proceed receive PDU as usual
}
-void Yaz_Proxy::recv_Z_PDU(Z_APDU *apdu)
+void Yaz_Proxy::handle_max_record_retrieve(Z_APDU *apdu)
+{
+ if (m_max_record_retrieve)
+ {
+ if (apdu->which == Z_APDU_presentRequest)
+ {
+ Z_PresentRequest *pr = apdu->u.presentRequest;
+ if (pr->numberOfRecordsRequested &&
+ *pr->numberOfRecordsRequested > m_max_record_retrieve)
+ *pr->numberOfRecordsRequested = m_max_record_retrieve;
+ }
+ }
+}
+
+void Yaz_Proxy::recv_Z_PDU_0(Z_APDU *apdu)
{
- yaz_log (LOG_LOG, "Receiving %s from client", apdu_name(apdu));
// Determine our client.
m_client = get_client(apdu);
if (!m_client)
if (m_client->m_cookie && *m_client->m_cookie)
set_otherInformationString(apdu, VAL_COOKIE, 1,
m_client->m_cookie);
- send_Z_PDU(apdu);
+ send_to_client(apdu);
return;
}
m_client->m_init_flag = 1;
}
+ handle_max_record_retrieve(apdu);
+
apdu = result_set_optimize(apdu);
if (!apdu)
return;
- yaz_log (LOG_LOG, "Sending %s to %s",
- apdu_name(apdu), m_client->get_hostname());
-
// delete other info part from PDU before sending to target
Z_OtherInformation **oi;
get_otherInfoAPDU(apdu, &oi);
} else {
m_client->m_resultSetStartPoint = 0;
}
- if (m_client->send_Z_PDU(apdu) < 0)
+ if (m_client->send_to_target(apdu) < 0)
{
delete m_client;
m_client = 0;
// only keep if keep_alive flag is set...
if (m_keepalive && m_client && m_client->m_waiting == 0)
{
- yaz_log (LOG_LOG, "shutdown (client to proxy) keepalive %s",
+ yaz_log (LOG_LOG, "%s Shutdown (client to proxy) keepalive %s",
+ m_session_str,
m_client->get_hostname());
assert (m_client->m_waiting != 2);
// Tell client (if any) that no server connection is there..
}
else if (m_client)
{
- yaz_log (LOG_LOG, "shutdown (client to proxy) close %s",
+ yaz_log (LOG_LOG, "%s Shutdown (client to proxy) close %s",
+ m_session_str,
m_client->get_hostname());
assert (m_client->m_waiting != 2);
delete m_client;
}
else if (!m_parent)
{
- yaz_log (LOG_LOG, "shutdown (client to proxy) bad state");
+ yaz_log (LOG_LOG, "%s shutdown (client to proxy) bad state",
+ m_session_str);
assert (m_parent);
}
else
{
- yaz_log (LOG_LOG, "shutdown (client to proxy)");
+ yaz_log (LOG_LOG, "%s Shutdown (client to proxy)",
+ m_session_str);
}
delete this;
}
+const char *Yaz_ProxyClient::get_session_str()
+{
+ if (!m_server)
+ return "0";
+ return m_server->get_session_str();
+}
+
void Yaz_ProxyClient::shutdown()
{
- yaz_log (LOG_LOG, "shutdown (proxy to server) %s", get_hostname());
+ yaz_log (LOG_LOG, "%s Shutdown (proxy to target) %s", get_session_str(),
+ get_hostname());
delete m_server;
delete this;
}
void Yaz_Proxy::failNotify()
{
- yaz_log (LOG_LOG, "Yaz_Proxy connection closed by client");
+ yaz_log (LOG_LOG, "%s Connection closed by client",
+ get_session_str());
shutdown();
}
void Yaz_ProxyClient::failNotify()
{
- yaz_log (LOG_LOG, "Yaz_ProxyClient connection closed by %s", get_hostname());
+ yaz_log (LOG_LOG, "%s Connection closed by target %s",
+ get_session_str(), get_hostname());
shutdown();
}
void Yaz_ProxyClient::connectNotify()
{
- yaz_log (LOG_LOG, "Connection accepted by %s", get_hostname());
- timeout(600);
+ yaz_log (LOG_LOG, "%s Connection accepted by %s", get_session_str(),
+ get_hostname());
+ int to;
+ if (m_server)
+ to = m_server->get_target_idletime();
+ else
+ to = 600;
+ timeout(to);
}
IYaz_PDU_Observer *Yaz_ProxyClient::sessionNotify(IYaz_PDU_Observable
void Yaz_Proxy::timeoutNotify()
{
- yaz_log (LOG_LOG, "timeout (client to proxy)");
- shutdown();
+ if (m_bw_hold_PDU)
+ {
+ timeout(m_client_idletime);
+ Z_APDU *apdu = m_bw_hold_PDU;
+ m_bw_hold_PDU = 0;
+ recv_Z_PDU_0(apdu);
+ }
+ else
+ {
+ yaz_log (LOG_LOG, "%s Timeout (client to proxy)", m_session_str);
+ shutdown();
+ }
}
void Yaz_ProxyClient::timeoutNotify()
{
- yaz_log (LOG_LOG, "timeout (proxy to target) %s", get_hostname());
+ yaz_log (LOG_LOG, "%s Timeout (proxy to target) %s", get_session_str(),
+ get_hostname());
shutdown();
}
m_init_odr = odr_createmem (ODR_DECODE);
m_initResponse = 0;
m_resultSetStartPoint = 0;
+ m_bytes_sent = m_bytes_recv = 0;
}
const char *Yaz_Proxy::option(const char *name, const char *value)
return 0;
}
-void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu)
+void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu, int len)
{
+ m_bytes_recv += len;
m_waiting = 0;
- yaz_log (LOG_LOG, "Receiving %s from %s", apdu_name(apdu),
- get_hostname());
+ yaz_log (LOG_LOG, "%s Receiving %s from %s %d bytes", get_session_str(),
+ apdu_name(apdu), get_hostname(), len);
if (apdu->which == Z_APDU_initResponse)
{
NMEM nmem = odr_extract_mem (odr_decode());
set_otherInformationString (apdu, VAL_COOKIE, 1, m_cookie);
if (m_server)
{
- yaz_log (LOG_LOG, "Sending %s to client", apdu_name(apdu));
- m_server->send_Z_PDU(apdu);
+ m_server->send_to_client(apdu);
}
if (apdu->which == Z_APDU_close)
{
* Copyright (c) 1998-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-assoc.cpp,v 1.25 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-assoc.cpp,v 1.26 2003-10-01 13:13:51 adam Exp $
*/
#include <assert.h>
Z_APDU *apdu = decode_Z_PDU (buf, len);
if (apdu)
{
- recv_Z_PDU (apdu);
+ recv_Z_PDU (apdu, len);
}
else
{
*id_to = 0;
}
-int Yaz_Z_Assoc::send_Z_PDU(Z_APDU *apdu)
+int Yaz_Z_Assoc::send_Z_PDU(Z_APDU *apdu, int *plen)
{
char *buf;
int len;
if (encode_Z_PDU(apdu, &buf, &len) > 0)
+ {
+ if (plen)
+ *plen = len;
return m_PDU_Observable->send_PDU(buf, len);
+ }
return -1;
}
* Copyright (c) 2002-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-cache.cpp,v 1.4 2003-08-28 18:46:54 adam Exp $
+ * $Id: yaz-z-cache.cpp,v 1.5 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
Z_RecordComposition *comp)
{
int i;
- yaz_log(LOG_LOG, "cache lookup start=%d num=%d", start, num);
+ yaz_log(LOG_DEBUG, "cache lookup start=%d num=%d", start, num);
for (i = 0; i<num; i++)
{
/*
- * Copyright (c) 1998-2001, Index Data.
+ * Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-query.cpp,v 1.11 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-query.cpp,v 1.12 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz++/z-query.h>
Z_Query *query;
if (!buf)
return 0;
- odr_setbuf (odr_decode, buf, len, 0);
+ odr_reset(odr_decode);
+ odr_setbuf(odr_decode, buf, len, 0);
if (!z_Query(odr_decode, &query, 0, 0))
return 0;
return query;
void Yaz_Z_Query::print(char *str, int len)
{
-
+ Z_Query *query;
+ *str = 0;
+ if (!buf)
+ return;
+ odr_setbuf (odr_decode, buf, len, 0);
+ if (!z_Query(odr_decode, &query, 0, 0))
+ return;
+ WRBUF wbuf = zquery2pquery(query);
+ if (wbuf)
+ {
+ if (wrbuf_len(wbuf) > len-1)
+ {
+ memcpy(str, wrbuf_buf(wbuf), len-1);
+ str[len-1] = '\0';
+ }
+ else
+ strcpy(str, wrbuf_buf(wbuf));
+ }
+ odr_reset(odr_decode);
+ wrbuf_free(wbuf,1);
}
int Yaz_Z_Query::match(Yaz_Z_Query *other)
return 0;
return 1;
}
+
+void Yaz_Z_Query::oid2str(Odr_oid *o, WRBUF buf)
+{
+ for (; *o >= 0; o++) {
+ char ibuf[16];
+ sprintf(ibuf, "%d", *o);
+ wrbuf_puts(buf, ibuf);
+ if (o[1] > 0)
+ wrbuf_putc(buf, '.');
+ }
+}
+
+void Yaz_Z_Query::pr_term(WRBUF wbuf, char *buf, int len)
+{
+ int i;
+ wrbuf_putc(wbuf, '"');
+ for (i = 0; i<len; i++)
+ {
+ int ch = buf[i];
+ if (ch == '"')
+ wrbuf_putc(wbuf, '\\');
+ wrbuf_putc(wbuf, ch);
+ }
+ wrbuf_puts(wbuf, "\" ");
+}
+
+int Yaz_Z_Query::rpn2pquery(Z_RPNStructure *s, WRBUF buf)
+{
+ if (s->which == Z_RPNStructure_simple)
+ {
+ Z_Operand *o = s->u.simple;
+
+ if (o->which == Z_Operand_APT)
+ {
+ Z_AttributesPlusTerm *at = s->u.simple->u.attributesPlusTerm;
+ if (at->attributes) {
+ int i;
+ for (i = 0; i < at->attributes->num_attributes; i++) {
+ wrbuf_puts(buf, "@attr ");
+ if (at->attributes->attributes[i]->attributeSet) {
+ oid2str(at->attributes->attributes[i]->attributeSet, buf);
+ wrbuf_putc(buf, ' ');
+ }
+ wrbuf_printf(buf, "%d=", *at->attributes->attributes[i]->attributeType);
+ wrbuf_printf(buf, "%d ", *at->attributes->attributes[i]->value.numeric);
+ }
+ }
+ if (at->term->which == Z_Term_general)
+ {
+ pr_term(buf, (char*) at->term->u.general->buf,
+ at->term->u.general->len);
+ }
+ else if (at->term->which == Z_Term_characterString)
+ {
+ wrbuf_puts(buf, "@term string ");
+ pr_term(buf, at->term->u.characterString,
+ strlen(at->term->u.characterString));
+
+ }
+ }
+ else if (o->which == Z_Operand_resultSetId)
+ {
+ wrbuf_printf(buf, "@set %s ", o->u.resultSetId);
+ }
+ }
+ else if (s->which == Z_RPNStructure_complex)
+ {
+ Z_Complex *c = s->u.complex;
+
+ switch (c->roperator->which) {
+ case Z_Operator_and: wrbuf_puts(buf, "@and "); break;
+ case Z_Operator_or: wrbuf_puts(buf, "@or "); break;
+ case Z_Operator_and_not: wrbuf_puts(buf, "@not "); break;
+ case Z_Operator_prox: wrbuf_puts(buf, "@prox "); break;
+ default: wrbuf_puts(buf, "@unknown ");
+ }
+ if (!rpn2pquery(c->s1, buf))
+ return 0;
+ if (!rpn2pquery(c->s2, buf))
+ return 0;
+ }
+ return 1;
+}
+
+WRBUF Yaz_Z_Query::zquery2pquery(Z_Query *q)
+{
+ WRBUF buf = wrbuf_alloc();
+
+ if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101)
+ return 0;
+ if (q->u.type_1->attributeSetId) {
+ /* Output attribute set ID */
+ wrbuf_puts(buf, "@attrset ");
+ oid2str(q->u.type_1->attributeSetId, buf);
+ wrbuf_putc(buf, ' ');
+ }
+ return rpn2pquery(q->u.type_1->RPNStructure, buf) ? buf : 0;
+}
+
+
* Copyright (c) 2000-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-server-ill.cpp,v 1.8 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-server-ill.cpp,v 1.9 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
ill_service(req, req->taskSpecificParameters->u.itemOrder,
apdu_response->u.extendedServicesResponse);
s->transfer_referenceId(apdu_request, apdu_response);
- s->send_Z_PDU(apdu_response);
+ s->send_Z_PDU(apdu_response, 0);
return 1;
}
* Copyright (c) 2000-2001, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-server-sr.cpp,v 1.5 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-server-sr.cpp,v 1.6 2003-10-01 13:13:51 adam Exp $
*
*/
fetch_via_piggyback(s, apdu_request->u.searchRequest,
apdu_response->u.searchResponse);
}
- s->send_Z_PDU(apdu_response);
+ s->send_Z_PDU(apdu_response, 0);
return 1;
case Z_APDU_presentRequest:
yaz_log (LOG_LOG, "got PresentRequest p=%p", this);
if (!apdu_response->u.presentResponse->records)
fetch_via_present(s, apdu_request->u.presentRequest,
apdu_response->u.presentResponse);
- s->send_Z_PDU(apdu_response);
+ s->send_Z_PDU(apdu_response, 0);
return 1;
}
return 0;
/*
- * Copyright (c) 2000-2001, Index Data.
+ * Copyright (c) 2000-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-server-update.cpp,v 1.4 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-server-update.cpp,v 1.5 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
update_service(req, req->taskSpecificParameters->u.update,
apdu_response->u.extendedServicesResponse);
s->transfer_referenceId(apdu_request, apdu_response);
- s->send_Z_PDU(apdu_response);
+ s->send_Z_PDU(apdu_response, 0);
}
else if (req->taskSpecificParameters &&
req->taskSpecificParameters->which == Z_External_update0)
update_service0 (req, req->taskSpecificParameters->u.update0,
apdu_response->u.extendedServicesResponse);
s->transfer_referenceId(apdu_request, apdu_response);
- s->send_Z_PDU(apdu_response);
+ s->send_Z_PDU(apdu_response, 0);
}
return 1;
}
/*
- * Copyright (c) 2000-2001, Index Data.
+ * Copyright (c) 2000-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-server.cpp,v 1.15 2002-10-09 12:50:26 adam Exp $
+ * $Id: yaz-z-server.cpp,v 1.16 2003-10-01 13:13:51 adam Exp $
*/
#include <yaz/log.h>
(*p)->m_facility = facility;
}
-void Yaz_Z_Server::recv_Z_PDU (Z_APDU *apdu_request)
+void Yaz_Z_Server::recv_Z_PDU (Z_APDU *apdu_request, int len)
{
Yaz_Z_Server_Facility_Info *f = m_facilities;
f = f->m_next;
}
transfer_referenceId(apdu_request, apdu_response);
- send_Z_PDU(apdu_response);
+ send_Z_PDU(apdu_response, 0);
}
else
{