* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: proxy.h,v 1.8 2003-10-01 13:13:51 adam Exp $
+ * $Id: proxy.h,v 1.9 2003-10-03 13:01:42 adam Exp $
*/
#include <yaz++/z-assoc.h>
~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);
+ int *limit_bw, int *limit_pdu, int *limit_req,
+ int *target_idletime, int *client_idletime,
+ int *max_clients);
void operator=(const Yaz_ProxyConfig &conf);
+ int check_query(ODR odr, const char *name, Z_Query *query, char **addinfo);
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);
+ int *limit_bw, int *limit_pdu, int *limit_req,
+ int *target_idletime, int *client_idletime);
void return_limit(xmlNodePtr ptr,
int *limit_bw, int *limit_pdu, int *limit_req);
+ int check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
+ char **addinfo);
+ xmlNodePtr find_target_node(const char *name);
const char *get_text(xmlNodePtr ptr);
+ int check_type_1_attributes(ODR odr, xmlNodePtr ptr,
+ Z_AttributeList *attrs,
+ char **addinfo);
+ int check_type_1_structure(ODR odr, xmlNodePtr ptr, Z_RPNStructure *q,
+ char **addinfo);
#endif
int m_copy;
};
int m_max_record_retrieve;
void handle_max_record_retrieve(Z_APDU *apdu);
void display_diagrecs(Z_DiagRec **pp, int num);
+ Z_Records *create_nonSurrogateDiagnostics(ODR o, int error,
+ const char *addinfo);
+
+ Z_APDU *handle_query_validation(Z_APDU *apdu);
public:
Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable);
~Yaz_Proxy();
* Copyright (c) 1998-2000, Index Data.
* See the file LICENSE for details.
*
- * $Id: z-query.h,v 1.2 2003-10-01 13:13:51 adam Exp $
+ * $Id: z-query.h,v 1.3 2003-10-03 13:01:42 adam Exp $
*/
#include <yaz/proto.h>
/// match query
int match(Yaz_Z_Query *other);
private:
- char *buf;
- int len;
+ char *m_buf;
+ int m_len;
ODR odr_decode;
ODR odr_encode;
ODR odr_print;
* 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 $
+ * $Id: yaz-proxy-config.cpp,v 1.2 2003-10-03 13:01:42 adam Exp $
*/
#include <yaz/log.h>
int *keepalive,
int *limit_bw,
int *limit_pdu,
- int *limit_req)
+ int *limit_req,
+ int *target_idletime,
+ int *client_idletime)
{
ptr = ptr->children;
for (; ptr; ptr = ptr->next)
if (ptr->type == XML_ELEMENT_NODE
&& !strcmp((const char *) ptr->name, "limit"))
return_limit(ptr, limit_bw, limit_pdu, limit_req);
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "target-timeout"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ {
+ *target_idletime = atoi(t);
+ if (*target_idletime < 0)
+ *target_idletime = 0;
+ }
+ }
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "client-timeout"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ {
+ *client_idletime = atoi(t);
+ if (*client_idletime < 0)
+ *client_idletime = 0;
+ }
+ }
}
}
#endif
-void Yaz_ProxyConfig::get_target_info(const char *name,
- const char **url,
- int *keepalive,
- int *limit_bw,
- int *limit_pdu,
- int *limit_req)
+int Yaz_ProxyConfig::check_type_1_attributes(ODR odr, xmlNodePtr ptr,
+ Z_AttributeList *attrs,
+ char **addinfo)
+{
+ for(ptr = ptr->children; ptr; ptr = ptr->next)
+ {
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "query"))
+ {
+ const char *match_type = 0;
+ const char *match_value = 0;
+ const char *match_error = 0;
+ struct _xmlAttr *attr;
+ for (attr = ptr->properties; attr; attr = attr->next)
+ {
+ if (!strcmp((const char *) attr->name, "type") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_type = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "value") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_value = (const char *) attr->children->content;
+ if (!strcmp((const char *) attr->name, "error") &&
+ attr->children && attr->children->type == XML_TEXT_NODE)
+ match_error = (const char *) attr->children->content;
+ }
+ int i;
+
+ if (match_type && match_value)
+ {
+ for (i = 0; i<attrs->num_attributes; i++)
+ {
+ Z_AttributeElement *el = attrs->attributes[i];
+ char value_str[20];
+
+ value_str[0] = '\0';
+ if (!el->attributeType)
+ continue;
+ int type = *el->attributeType;
+
+ if (strcmp(match_type, "*")) {
+ if (type != atoi(match_type))
+ continue; // no match on type
+ }
+ if (el->which == Z_AttributeValue_numeric &&
+ el->value.numeric)
+ {
+ int value = *el->value.numeric;
+ if (strcmp(match_value, "*")) {
+ if (value != atoi(match_value))
+ continue; // no match on value
+ }
+ sprintf(value_str, "%d", value);
+ }
+ else
+ continue;
+ if (match_error)
+ {
+ if (*value_str)
+ *addinfo = odr_strdup(odr, value_str);
+ return atoi(match_error);
+ }
+ return 0;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int Yaz_ProxyConfig::check_type_1_structure(ODR odr, xmlNodePtr ptr,
+ Z_RPNStructure *q,
+ char **addinfo)
+{
+ int c;
+ if (q->which == Z_RPNStructure_complex)
+ {
+ int e = check_type_1_structure(odr, ptr, q->u.complex->s1, addinfo);
+ if (e)
+ return e;
+ e = check_type_1_structure(odr, ptr, q->u.complex->s2, addinfo);
+ return e;
+ }
+ else if (q->which == Z_RPNStructure_simple)
+ {
+ if (q->u.simple->which == Z_Operand_APT)
+ {
+ return check_type_1_attributes(
+ odr, ptr, q->u.simple->u.attributesPlusTerm->attributes,
+ addinfo);
+ }
+ }
+ return 0;
+}
+
+int Yaz_ProxyConfig::check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
+ char **addinfo)
+{
+ // possibly check for Bib-1
+ return check_type_1_structure(odr, ptr, query->RPNStructure, addinfo);
+}
+
+int Yaz_ProxyConfig::check_query(ODR odr, const char *name, Z_Query *query,
+ char **addinfo)
{
-#if HAVE_XML2
xmlNodePtr ptr;
- if (!m_proxyPtr)
+
+ ptr = find_target_node(name);
+ if (ptr)
{
- *url = name;
- return;
+ if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
+ return check_type_1(odr, ptr, query->u.type_1, addinfo);
}
+ return 0;
+}
+
+xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name)
+{
+ xmlNodePtr ptr;
for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
{
if (ptr->type == XML_ELEMENT_NODE &&
{
xmlChar *t = attr->children->content;
if (!t || *t == '1')
- {
- return_target_info(ptr, url, keepalive,
- limit_bw, limit_pdu, limit_req);
- return;
- }
+ return ptr;
}
}
else
|| !strcmp((const char *) attr->children->content,
"*")))
{
- *url = name;
- return_target_info(ptr, url, keepalive,
- limit_bw, limit_pdu, limit_req);
- return;
+ return ptr;
}
}
}
}
}
+ return 0;
+}
+
+
+void Yaz_ProxyConfig::get_target_info(const char *name,
+ const char **url,
+ int *keepalive,
+ int *limit_bw,
+ int *limit_pdu,
+ int *limit_req,
+ int *target_idletime,
+ int *client_idletime,
+ int *max_clients)
+{
+#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, "max-clients"))
+ {
+ const char *t = get_text(ptr);
+ if (t)
+ {
+ *max_clients = atoi(t);
+ if (*max_clients < 1)
+ *max_clients = 1;
+ }
+ }
+ }
+ ptr = find_target_node(name);
+ if (ptr)
+ {
+ if (name)
+ *url = name;
+ return_target_info(ptr, url, keepalive, limit_bw, limit_pdu, limit_req,
+ target_idletime, client_idletime);
+ }
#else
*url = name;
return;
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy.cpp,v 1.48 2003-10-01 13:13:51 adam Exp $
+ * $Id: yaz-proxy.cpp,v 1.49 2003-10-03 13:01:42 adam Exp $
*/
#include <assert.h>
return "other";
}
-
Yaz_Proxy::Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable) :
Yaz_Z_Assoc(the_PDU_Observable), m_bw_stat(60), m_pdu_stat(60)
{
{
const char *proxy_host = get_proxy(oi);
if (!proxy_host)
+ {
+ xfree(m_default_target);
+ m_default_target = xstrdup(proxy_host);
proxy_host = m_default_target;
+ }
const char *url = 0;
+ int client_idletime = -1;
m_config.get_target_info(proxy_host, &url, &m_keepalive, &m_bw_max,
- &m_pdu_max, &m_max_record_retrieve);
-
+ &m_pdu_max, &m_max_record_retrieve,
+ &m_target_idletime, &client_idletime,
+ &parent->m_max_clients);
+ if (client_idletime != -1)
+ {
+ m_client_idletime = client_idletime;
+ timeout(m_client_idletime);
+ }
if (!url)
{
yaz_log(LOG_LOG, "%s No default target", m_session_str);
}
}
+Z_Records *Yaz_Proxy::create_nonSurrogateDiagnostics(ODR odr,
+ int error,
+ const char *addinfo)
+{
+ Z_Records *rec = (Z_Records *)
+ odr_malloc (odr, sizeof(*rec));
+ int *err = (int *)
+ odr_malloc (odr, sizeof(*err));
+ Z_DiagRec *drec = (Z_DiagRec *)
+ odr_malloc (odr, sizeof(*drec));
+ Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
+ odr_malloc (odr, sizeof(*dr));
+ *err = error;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic = dr;
+ dr->diagnosticSetId =
+ yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1);
+ dr->condition = err;
+ dr->which = Z_DefaultDiagFormat_v2Addinfo;
+ dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
+ return rec;
+}
+
+Z_APDU *Yaz_Proxy::handle_query_validation(Z_APDU *apdu)
+{
+ if (apdu->which == Z_APDU_searchRequest)
+ {
+ Z_SearchRequest *sr = apdu->u.searchRequest;
+ int err;
+ char *addinfo = 0;
+ err = m_config.check_query(odr_encode(), m_default_target, sr->query,
+ &addinfo);
+ if (err)
+ {
+ Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse);
+ int *nulint = odr_intdup (odr_encode(), 0);
+
+ new_apdu->u.searchResponse->referenceId = sr->referenceId;
+ new_apdu->u.searchResponse->records =
+ create_nonSurrogateDiagnostics(odr_encode(), err, addinfo);
+ new_apdu->u.searchResponse->searchStatus = nulint;
+ new_apdu->u.searchResponse->resultCount = nulint;
+
+ send_to_client(new_apdu);
+
+ return 0;
+ }
+ }
+ return apdu;
+}
+
void Yaz_Proxy::recv_Z_PDU_0(Z_APDU *apdu)
{
// Determine our client.
}
handle_max_record_retrieve(apdu);
- apdu = result_set_optimize(apdu);
+ if (apdu)
+ apdu = handle_query_validation(apdu);
+
+ if (apdu)
+ apdu = result_set_optimize(apdu);
if (!apdu)
+ {
+ m_client->timeout(m_target_idletime); // mark it active even
+ // though we didn't use it
return;
+ }
// delete other info part from PDU before sending to target
Z_OtherInformation **oi;
odr_reset (m_init_odr);
nmem_transfer (m_init_odr->mem, nmem);
m_initResponse = apdu;
+
+ Z_InitResponse *ir = apdu->u.initResponse;
+ char *im0 = ir->implementationName;
+
+ char *im1 = (char*)
+ odr_malloc(m_init_odr, 20 + (im0 ? strlen(im0) : 0));
+ *im1 = '\0';
+ if (im0)
+ {
+ strcat(im1, im0);
+ strcat(im1, " ");
+ }
+ strcat(im1, "(YAZ Proxy)");
+ ir->implementationName = im1;
+
nmem_destroy (nmem);
}
if (apdu->which == Z_APDU_searchResponse)
sr->numberOfRecordsReturned = pr->numberOfRecordsReturned;
apdu = new_apdu;
}
- if (pr->records->which == Z_Records_DBOSD && m_resultSetStartPoint)
+ if (pr->records &&
+ pr->records->which == Z_Records_DBOSD && m_resultSetStartPoint)
{
m_cache.add(odr_decode(),
pr->records->u.databaseOrSurDiagnostics,
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-z-query.cpp,v 1.12 2003-10-01 13:13:51 adam Exp $
+ * $Id: yaz-z-query.cpp,v 1.13 2003-10-03 13:01:42 adam Exp $
*/
#include <yaz++/z-query.h>
int Yaz_Z_Query::set_rpn (const char *rpn)
{
- buf = 0;
+ m_buf = 0;
odr_reset (odr_encode);
Z_Query *query = (Z_Query*) odr_malloc (odr_encode, sizeof(*query));
query->which = Z_Query_type_1;
if (!z_Query (odr_encode, &query, 0, 0))
return -1;
// z_Query(odr_print, &query, 0, 0);
- buf = odr_getbuf (odr_encode, &len, 0);
- return len;
+ m_buf = odr_getbuf (odr_encode, &m_len, 0);
+ return m_len;
}
void Yaz_Z_Query::set_Z_Query(Z_Query *z_query)
{
- buf = 0;
+ m_buf = 0;
odr_reset (odr_encode);
if (!z_Query (odr_encode, &z_query, 0, 0))
return;
- buf = odr_getbuf (odr_encode, &len, 0);
+ m_buf = odr_getbuf (odr_encode, &m_len, 0);
}
Yaz_Z_Query::~Yaz_Z_Query()
Z_Query *Yaz_Z_Query::get_Z_Query ()
{
Z_Query *query;
- if (!buf)
+ if (!m_buf)
return 0;
odr_reset(odr_decode);
- odr_setbuf(odr_decode, buf, len, 0);
+ odr_setbuf(odr_decode, m_buf, m_len, 0);
if (!z_Query(odr_decode, &query, 0, 0))
return 0;
return query;
{
Z_Query *query;
*str = 0;
- if (!buf)
+ if (!m_buf)
return;
- odr_setbuf (odr_decode, buf, len, 0);
+ odr_setbuf (odr_decode, m_buf, m_len, 0);
if (!z_Query(odr_decode, &query, 0, 0))
return;
WRBUF wbuf = zquery2pquery(query);
int Yaz_Z_Query::match(Yaz_Z_Query *other)
{
- if (len != other->len)
+ if (m_len != other->m_len)
return 0;
- if (!buf || !other->buf)
+ if (!m_buf || !other->m_buf)
return 0;
- if (memcmp(buf, other->buf, len))
+ if (memcmp(m_buf, other->m_buf, m_len))
return 0;
return 1;
}