X-Git-Url: http://git.indexdata.com/?p=yazpp-moved-to-github.git;a=blobdiff_plain;f=src%2Fyaz-proxy.cpp;h=97ec2de71592f07ae649c8f71620ccf90df18499;hp=8a5a27e70781798a6f2904655654878d62007fdc;hb=d84b43231c7c5b0786e9aa62d0f7ca7ecd83bdb5;hpb=113c16a5254c24ec5dfc1b72a2b124f0bd356501 diff --git a/src/yaz-proxy.cpp b/src/yaz-proxy.cpp index 8a5a27e..97ec2de 100644 --- a/src/yaz-proxy.cpp +++ b/src/yaz-proxy.cpp @@ -2,7 +2,7 @@ * Copyright (c) 1998-2004, Index Data. * See the file LICENSE for details. * - * $Id: yaz-proxy.cpp,v 1.79 2004-01-07 11:37:45 adam Exp $ + * $Id: yaz-proxy.cpp,v 1.91 2004-01-15 23:44:58 adam Exp $ */ #include @@ -106,10 +106,14 @@ Yaz_Proxy::Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable, m_invalid_session = 0; m_config = 0; m_marcxml_flag = 0; - m_stylesheet = 0; + m_stylesheet_schema = 0; + m_s2z_stylesheet = 0; + m_s2z_database = 0; m_schema = 0; m_initRequest_apdu = 0; m_initRequest_mem = 0; + m_initRequest_options = 0; + m_initRequest_version = 0; m_apdu_invalid_session = 0; m_mem_invalid_session = 0; m_s2z_odr_init = 0; @@ -135,7 +139,7 @@ Yaz_Proxy::~Yaz_Proxy() xfree (m_default_target); xfree (m_proxy_authentication); xfree (m_optimize); - xfree (m_stylesheet); + xfree (m_stylesheet_schema); xfree (m_schema); if (m_s2z_odr_init) odr_destroy(m_s2z_odr_init); @@ -292,7 +296,6 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, { assert (m_parent); Yaz_Proxy *parent = m_parent; - Z_OtherInformation **oi; Yaz_ProxyClient *c = m_client; if (!m_proxyTarget) @@ -426,7 +429,7 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, { if (apdu->which != Z_APDU_initRequest) { - yaz_log (LOG_LOG, "no first INIT!"); + yaz_log (LOG_LOG, "%sno init request as first PDU", m_session_str); return 0; } Z_InitRequest *initRequest = apdu->u.initRequest; @@ -445,7 +448,6 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, odr_strdup (odr_encode(), m_proxy_authentication); } } - // go through list of clients - and find the lowest/oldest one. Yaz_ProxyClient *c_min = 0; int min_seq = -1; @@ -583,12 +585,11 @@ void Yaz_Proxy::display_diagrecs(Z_DiagRec **pp, int num) void Yaz_Proxy::convert_xsl(Z_NamePlusRecordList *p) { - if (!m_stylesheet) + if (!m_stylesheet_schema) return; - xmlDocPtr xslt_doc = xmlParseFile(m_stylesheet); xsltStylesheetPtr xsp; - xsp = xsltParseStylesheetDoc(xslt_doc); + xsp = xsltParseStylesheetFile((const xmlChar *) m_stylesheet_schema); int i; for (i = 0; i < p->num_records; i++) @@ -607,10 +608,12 @@ void Yaz_Proxy::convert_xsl(Z_NamePlusRecordList *p) xmlChar *out_buf; int out_len; - xmlDocDumpMemory (res, &out_buf, &out_len); + xmlDocDumpFormatMemory (res, &out_buf, &out_len, 1); + p->records[i]->u.databaseRecord = z_ext_record(odr_encode(), VAL_TEXT_XML, (char*) out_buf, out_len); + xmlFree(out_buf); xmlFreeDoc(doc); xmlFreeDoc(res); } @@ -699,7 +702,6 @@ void Yaz_Proxy::logtime() int Yaz_Proxy::send_http_response(int code) { ODR o = odr_encode(); - const char *ctype = "text/xml"; Z_GDU *gdu = z_get_HTTP_Response(o, code); Z_HTTP_Response *hres = gdu->u.HTTP_Response; if (m_http_version) @@ -744,9 +746,9 @@ int Yaz_Proxy::send_srw_response(Z_SRW_PDU *srw_pdu) soap_package->u.generic->ns = soap_handlers[0].ns; soap_package->u.generic->p = (void *) srw_pdu; soap_package->ns = m_soap_ns; - int ret = z_soap_codec_enc(o, &soap_package, - &hres->content_buf, &hres->content_len, - soap_handlers, 0); + z_soap_codec_enc_xsl(o, &soap_package, + &hres->content_buf, &hres->content_len, + soap_handlers, 0, m_s2z_stylesheet); if (m_log_mask & PROXY_LOG_REQ_CLIENT) { yaz_log (LOG_LOG, "%sSending %s to client", m_session_str, @@ -758,7 +760,7 @@ int Yaz_Proxy::send_srw_response(Z_SRW_PDU *srw_pdu) return r; } -int Yaz_Proxy::send_to_srw_client_error(int srw_error) +int Yaz_Proxy::send_to_srw_client_error(int srw_error, const char *add) { ODR o = odr_encode(); Z_SRW_PDU *srw_pdu = yaz_srw_get(o, Z_SRW_searchRetrieve_response); @@ -768,7 +770,7 @@ int Yaz_Proxy::send_to_srw_client_error(int srw_error) srw_res->diagnostics = (Z_SRW_diagnostic *) odr_malloc(o, sizeof(*srw_res->diagnostics)); srw_res->diagnostics[0].code = odr_intdup(o, srw_error); - srw_res->diagnostics[0].details = 0; + srw_res->diagnostics[0].details = add ? odr_strdup(o, add) : 0; return send_srw_response(srw_pdu); } @@ -846,26 +848,30 @@ int Yaz_Proxy::send_to_srw_client_ok(int hits, Z_Records *records, int start) } -int Yaz_Proxy::send_srw_explain() +int Yaz_Proxy::send_srw_explain_response(Z_SRW_diagnostic *diagnostics, + int num_diagnostics) { - Z_SRW_PDU *res = yaz_srw_get(odr_encode(), Z_SRW_explain_response); - Z_SRW_explainResponse *er = res->u.explain_response; - Yaz_ProxyConfig *cfg = check_reconfigure(); if (cfg) { int len; - assert (m_proxyTarget); char *b = cfg->get_explain(odr_encode(), 0 /* target */, - 0 /* db */, &len); + m_s2z_database, &len); if (b) { + Z_SRW_PDU *res = yaz_srw_get(odr_encode(), Z_SRW_explain_response); + Z_SRW_explainResponse *er = res->u.explain_response; + er->record.recordData_buf = b; er->record.recordData_len = len; er->record.recordPacking = m_s2z_packing; + + er->diagnostics = diagnostics; + er->num_diagnostics = num_diagnostics; + return send_srw_response(res); } } - return send_srw_response(res); + return send_http_response(404); } int Yaz_Proxy::send_PDU_convert(Z_APDU *apdu, int *len) @@ -877,11 +883,11 @@ int Yaz_Proxy::send_PDU_convert(Z_APDU *apdu, int *len) Z_InitResponse *res = apdu->u.initResponse; if (*res->result == 0) { - send_to_srw_client_error(3); + send_to_srw_client_error(3, 0); } else if (!m_s2z_search_apdu) { - send_srw_explain(); + send_srw_explain_response(0, 0); } else { @@ -897,12 +903,23 @@ int Yaz_Proxy::send_PDU_convert(Z_APDU *apdu, int *len) { send_to_srw_client_ok(0, res->records, 1); } - else if (m_s2z_present_apdu) + else if (m_s2z_present_apdu && m_s2z_hit_count > 0) { + // adjust + Z_PresentRequest *pr = m_s2z_present_apdu->u.presentRequest; + + if (*pr->resultSetStartPoint <= m_s2z_hit_count) + { + if (*pr->numberOfRecordsRequested+ *pr->resultSetStartPoint + > m_s2z_hit_count) + *pr->numberOfRecordsRequested = + 1 + m_s2z_hit_count - *pr->resultSetStartPoint; + } handle_incoming_Z_PDU(m_s2z_present_apdu); } else { + m_s2z_present_apdu = 0; send_to_srw_client_ok(m_s2z_hit_count, res->records, 1); } } @@ -990,6 +1007,37 @@ int Yaz_Proxy::send_to_client(Z_APDU *apdu) convert_xsl(p->u.databaseOrSurDiagnostics); } } + else if (apdu->which == Z_APDU_initResponse) + { + if (m_initRequest_options) + { + Z_Options *nopt = + (Odr_bitmask *)odr_malloc(odr_encode(), + sizeof(Odr_bitmask)); + ODR_MASK_ZERO(nopt); + + int i; + for (i = 0; i<24; i++) + if (ODR_MASK_GET(m_initRequest_options, i) && + ODR_MASK_GET(apdu->u.initResponse->options, i)) + ODR_MASK_SET(nopt, i); + apdu->u.initResponse->options = nopt; + } + if (m_initRequest_version) + { + Z_ProtocolVersion *nopt = + (Odr_bitmask *)odr_malloc(odr_encode(), + sizeof(Odr_bitmask)); + ODR_MASK_ZERO(nopt); + + int i; + for (i = 0; i<8; i++) + if (ODR_MASK_GET(m_initRequest_version, i) && + ODR_MASK_GET(apdu->u.initResponse->protocolVersion, i)) + ODR_MASK_SET(nopt, i); + apdu->u.initResponse->protocolVersion = nopt; + } + } int r = send_PDU_convert(apdu, &len); if (r) return r; @@ -1450,7 +1498,7 @@ Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu) err = cfg->check_syntax(odr_encode(), m_default_target, sr->preferredRecordSyntax, rc, - &addinfo, &m_stylesheet, &m_schema); + &addinfo, &m_stylesheet_schema, &m_schema); if (err == -1) { sr->preferredRecordSyntax = @@ -1482,7 +1530,7 @@ Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu) err = cfg->check_syntax(odr_encode(), m_default_target, pr->preferredRecordSyntax, pr->recordComposition, - &addinfo, &m_stylesheet, &m_schema); + &addinfo, &m_stylesheet_schema, &m_schema); if (err == -1) { pr->preferredRecordSyntax = @@ -1520,7 +1568,6 @@ Z_ElementSetNames *Yaz_Proxy::mk_esn_from_schema(ODR o, const char *schema) void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) { - if (m_s2z_odr_init) { odr_destroy(m_s2z_odr_init); @@ -1556,10 +1603,12 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) Z_SRW_PDU *srw_pdu = 0; Z_SOAP *soap_package = 0; char *charset = 0; + Z_SRW_diagnostic *diagnostic = 0; + int num_diagnostic = 0; if (yaz_srw_decode(hreq, &srw_pdu, &soap_package, odr_decode(), &charset) == 0 || yaz_sru_decode(hreq, &srw_pdu, &soap_package, odr_decode(), - &charset) == 0) + &charset, &diagnostic, &num_diagnostic) == 0) { m_s2z_odr_init = odr_createmem(ODR_ENCODE); m_s2z_odr_search = odr_createmem(ODR_ENCODE); @@ -1567,10 +1616,40 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) m_s2z_init_apdu = 0; m_s2z_search_apdu = 0; m_s2z_present_apdu = 0; + + m_s2z_stylesheet = 0; + if (srw_pdu->which == Z_SRW_searchRetrieve_request) { Z_SRW_searchRetrieveRequest *srw_req = srw_pdu->u.request; + m_s2z_database = odr_strdup(m_s2z_odr_init, srw_req->database); + // recordXPath unsupported. + if (srw_req->recordXPath) + { + yaz_add_srw_diagnostic(odr_decode(), + &diagnostic, &num_diagnostic, + 72, 0); + } + // must have a query + if (!srw_req->query.cql) + { + yaz_add_srw_diagnostic(odr_decode(), + &diagnostic, &num_diagnostic, + 7, "query"); + } + // sort unsupported + if (srw_req->sort_type != Z_SRW_sort_type_none) + { + yaz_add_srw_diagnostic(odr_decode(), + &diagnostic, &num_diagnostic, + 80, 0); + } + // save stylesheet + if (srw_req->stylesheet) + m_s2z_stylesheet = + odr_strdup(m_s2z_odr_init, srw_req->stylesheet); + // set packing for response records .. if (srw_req->recordPacking && !strcmp(srw_req->recordPacking, "xml")) @@ -1578,6 +1657,19 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) else m_s2z_packing = Z_SRW_recordPacking_string; + if (num_diagnostic) + { + Z_SRW_PDU *srw_pdu = + yaz_srw_get(odr_encode(), + Z_SRW_searchRetrieve_response); + Z_SRW_searchRetrieveResponse *srw_res = srw_pdu->u.response; + + srw_res->diagnostics = diagnostic; + srw_res->num_diagnostics = num_diagnostic; + send_srw_response(srw_pdu); + return; + } + // prepare search PDU m_s2z_search_apdu = zget_APDU(m_s2z_odr_search, Z_APDU_searchRequest); @@ -1626,7 +1718,7 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) yaz_log(LOG_LOG, "%*s^\n", off+4, ""); yaz_log(LOG_LOG, "Bad PQF: %s (code %d)\n", pqf_msg, code); - send_to_srw_client_error(10); + send_to_srw_client_error(10, 0); return; } query->which = Z_Query_type_1; @@ -1636,7 +1728,7 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) } else { - send_to_srw_client_error(11); + send_to_srw_client_error(7, "query"); return; } @@ -1714,16 +1806,28 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) else if (srw_pdu->which == Z_SRW_explain_request) { Z_SRW_explainRequest *srw_req = srw_pdu->u.explain_request; - + + m_s2z_database = odr_strdup(m_s2z_odr_init, srw_req->database); + + // save stylesheet + if (srw_req->stylesheet) + m_s2z_stylesheet = + odr_strdup(m_s2z_odr_init, srw_req->stylesheet); + if (srw_req->recordPacking && !strcmp(srw_req->recordPacking, "xml")) m_s2z_packing = Z_SRW_recordPacking_XML; else m_s2z_packing = Z_SRW_recordPacking_string; + if (num_diagnostic) + { + send_srw_explain_response(diagnostic, num_diagnostic); + return; + } + if (!m_client) { - yaz_log(LOG_LOG, "handle_incoming: initRequest"); m_s2z_init_apdu = zget_APDU(m_s2z_odr_init, Z_APDU_initRequest); @@ -1733,9 +1837,33 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) handle_incoming_Z_PDU(m_s2z_init_apdu); } else - send_srw_explain(); + send_srw_explain_response(0, 0); return; } + else if (srw_pdu->which == Z_SRW_scan_request) + { + m_s2z_database = odr_strdup(m_s2z_odr_init, + srw_pdu->u.scan_request->database); + + yaz_add_srw_diagnostic(odr_decode(), + &diagnostic, &num_diagnostic, + 4, "scan"); + Z_SRW_PDU *srw_pdu = + yaz_srw_get(odr_encode(), + Z_SRW_scan_response); + Z_SRW_scanResponse *srw_res = srw_pdu->u.scan_response; + + srw_res->diagnostics = diagnostic; + srw_res->num_diagnostics = num_diagnostic; + send_srw_response(srw_pdu); + return; + } + else + { + m_s2z_database = 0; + + send_to_srw_client_error(4, 0); + } } int len = 0; Z_GDU *p = z_get_HTTP_Response(odr_encode(), 400); @@ -1780,6 +1908,29 @@ void Yaz_Proxy::handle_incoming_Z_PDU(Z_APDU *apdu) nmem_destroy(m_initRequest_mem); m_initRequest_apdu = apdu; m_initRequest_mem = odr_extract_mem(odr_decode()); + + // save init options for the response.. + m_initRequest_options = apdu->u.initRequest->options; + + apdu->u.initRequest->options = + (Odr_bitmask *)nmem_malloc(m_initRequest_mem, + sizeof(Odr_bitmask)); + ODR_MASK_ZERO(apdu->u.initRequest->options); + int i; + for (i = 0; i<= 24; i++) + ODR_MASK_SET(apdu->u.initRequest->options, i); + ODR_MASK_CLEAR(apdu->u.initRequest->options, + Z_Options_negotiationModel); + + // make new version + m_initRequest_version = apdu->u.initRequest->protocolVersion; + apdu->u.initRequest->protocolVersion = + (Odr_bitmask *)nmem_malloc(m_initRequest_mem, + sizeof(Odr_bitmask)); + ODR_MASK_ZERO(apdu->u.initRequest->protocolVersion); + + for (i = 0; i<= 8; i++) + ODR_MASK_SET(apdu->u.initRequest->protocolVersion, i); } if (m_client->m_init_flag) { @@ -1792,6 +1943,10 @@ void Yaz_Proxy::handle_incoming_Z_PDU(Z_APDU *apdu) m_client->m_cookie); apdu2->u.initResponse->referenceId = apdu->u.initRequest->referenceId; + apdu2->u.initResponse->options = m_client->m_initResponse_options; + apdu2->u.initResponse->protocolVersion = + m_client->m_initResponse_version; + send_to_client(apdu2); return; } @@ -1957,19 +2112,14 @@ void Yaz_ProxyClient::pre_init_client() Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest); Z_InitRequest *req = apdu->u.initRequest; - ODR_MASK_SET(req->options, Z_Options_search); - ODR_MASK_SET(req->options, Z_Options_present); - ODR_MASK_SET(req->options, Z_Options_namedResultSets); - ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl); - ODR_MASK_SET(req->options, Z_Options_scan); - ODR_MASK_SET(req->options, Z_Options_sort); - ODR_MASK_SET(req->options, Z_Options_extendedServices); - ODR_MASK_SET(req->options, Z_Options_delSet); - - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1); - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2); - ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3); - + int i; + for (i = 0; i<= 24; i++) + ODR_MASK_SET(req->options, i); + ODR_MASK_CLEAR(apdu->u.initRequest->options, + Z_Options_negotiationModel); + for (i = 0; i<= 10; i++) + ODR_MASK_SET(req->protocolVersion, i); + if (send_to_target(apdu) < 0) { delete this; @@ -1992,7 +2142,6 @@ void Yaz_Proxy::pre_init() int keepalive_limit_bw, keepalive_limit_pdu; int pre_init; const char *cql2rpn = 0; - const char *zeerex = 0; Yaz_ProxyConfig *cfg = check_reconfigure(); @@ -2099,6 +2248,12 @@ void Yaz_Proxy::timeoutNotify() } } +void Yaz_Proxy::markInvalid() +{ + m_client = 0; + m_invalid_session = 1; +} + void Yaz_ProxyClient::timeoutNotify() { if (m_server) @@ -2108,6 +2263,14 @@ void Yaz_ProxyClient::timeoutNotify() get_hostname()); m_waiting = 1; m_root->pre_init(); + if (m_server && m_init_flag) + { + // target timed out in a session that was properly initialized + // server object stay alive but we mark it as invalid so it + // gets initialized again + m_server->markInvalid(); + m_server = 0; + } shutdown(); } @@ -2127,6 +2290,8 @@ Yaz_ProxyClient::Yaz_ProxyClient(IYaz_PDU_Observable *the_PDU_Observable, m_waiting = 0; m_init_odr = odr_createmem (ODR_DECODE); m_initResponse = 0; + m_initResponse_options = 0; + m_initResponse_version = 0; m_resultSetStartPoint = 0; m_bytes_sent = m_bytes_recv = 0; m_pdu_recv = 0; @@ -2191,6 +2356,8 @@ void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu, int len) odr_reset (m_init_odr); nmem_transfer (m_init_odr->mem, nmem); m_initResponse = apdu; + m_initResponse_options = apdu->u.initResponse->options; + m_initResponse_version = apdu->u.initResponse->protocolVersion; Z_InitResponse *ir = apdu->u.initResponse; char *im0 = ir->implementationName;