X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fyaz-proxy.cpp;h=1fb30d9b9c7348aa0b21a6bde2f9437c401667e3;hb=aab482fc16e30ee61267da7a19f7bf7663a31117;hp=f296d79b8e8b700816a55c26c525ddd25842f293;hpb=aea59072802dbcc47655a4ed12b9ae28b89fea8e;p=yazproxy-moved-to-github.git diff --git a/src/yaz-proxy.cpp b/src/yaz-proxy.cpp index f296d79..1fb30d9 100644 --- a/src/yaz-proxy.cpp +++ b/src/yaz-proxy.cpp @@ -1,4 +1,4 @@ -/* $Id: yaz-proxy.cpp,v 1.39 2005-11-25 19:37:28 adam Exp $ +/* $Id: yaz-proxy.cpp,v 1.43 2006-03-09 14:12:57 adam Exp $ Copyright (c) 1998-2005, Index Data. This file is part of the yaz-proxy. @@ -106,18 +106,18 @@ void Auth_Msg::result() { yaz_log(YLOG_LOG, "Auth_Msg:result proxy ok buf=%p len=%d", m_apdu_buf, m_apdu_len); - 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 - yaz_log(YLOG_LOG, "Auth_Msg::result z_APDU failed"); - if (m_proxy->dec_ref()) + 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 + yaz_log(YLOG_LOG, "Auth_Msg::result z_APDU failed"); m_proxy->result_authentication(apdu, m_ret); } delete this; @@ -132,10 +132,19 @@ void Yaz_Proxy::result_authentication(Z_APDU *apdu, int ret) Z_APDU *apdu_reject = zget_APDU(odr_encode(), Z_APDU_initResponse); *apdu_reject->u.initResponse->result = 0; send_to_client(apdu_reject); - dec_ref(); + dec_ref(false); } else + { + if (apdu->which == Z_APDU_initRequest) + { + Yaz_ProxyConfig *cfg = check_reconfigure(); + if (cfg) + cfg->target_authentication(m_default_target, odr_encode(), + apdu->u.initRequest); + } handle_incoming_Z_PDU_2(apdu); + } } static const char *apdu_name(Z_APDU *apdu) @@ -280,6 +289,7 @@ Yaz_Proxy::Yaz_Proxy(IPDU_Observable *the_PDU_Observable, low_socket_open(); m_my_thread = 0; m_ref_count = 1; + m_main_ptr_dec = false; m_peername = 0; } @@ -619,10 +629,10 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, } } } - else if (!c && - apdu->which == Z_APDU_initRequest && - apdu->u.initRequest->idAuthentication == 0 && - !ODR_MASK_GET(apdu->u.initRequest->options, Z_Options_negotiationModel)) + else if (!c + && apdu->which == Z_APDU_initRequest + && !ODR_MASK_GET(apdu->u.initRequest->options, + Z_Options_negotiationModel)) { // anonymous sessions without cookie. // if authentication is set it is NOT anonymous se we can't share them. @@ -631,9 +641,9 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, { assert(c->m_prev); assert(*c->m_prev == c); - if (c->m_server == 0 && c->m_cookie == 0 && - c->m_waiting == 0 && - !strcmp(m_proxyTarget, c->get_hostname())) + if (c->m_server == 0 && c->m_cookie == 0 && c->m_waiting == 0 + && c->compare_idAuthentication(apdu) + && !strcmp(m_proxyTarget, c->get_hostname())) { // found it in cache yaz_log (YLOG_LOG, "%sREUSE %d %s", @@ -663,14 +673,6 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, yaz_log (YLOG_LOG, "%sno init request as first PDU", m_session_str); return 0; } - Z_InitRequest *initRequest = apdu->u.initRequest; - - if (initRequest->idAuthentication) - { - // the client uses authentication. We set the keepalive PDU - // to 0 so we don't cache it in releaseClient - m_keepalive_limit_pdu = 0; - } // go through list of clients - and find the lowest/oldest one. Yaz_ProxyClient *c_min = 0; int min_seq = -1; @@ -765,6 +767,8 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, c->set_APDU_yazlog(1); else c->set_APDU_yazlog(0); + + c->set_idAuthentication(apdu); } yaz_log (YLOG_DEBUG, "get_client 3 %p %p", this, c); return c; @@ -1040,7 +1044,7 @@ void Yaz_Proxy::convert_to_marcxml(Z_NamePlusRecordList *p, { WRBUF w = wrbuf_alloc(); - yaz_display_OPAC(w, r->u.opac, 0); + yaz_opac_decode_wrbuf(mt, r->u.opac, w); npr->u.databaseRecord = z_ext_record( odr_encode(), VAL_TEXT_XML, wrbuf_buf(w), wrbuf_len(w) @@ -1165,14 +1169,11 @@ int Yaz_Proxy::send_srw_response(Z_SRW_PDU *srw_pdu) 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); - Z_SRW_searchRetrieveResponse *srw_res = srw_pdu->u.response; - - srw_res->num_diagnostics = 1; - srw_res->diagnostics = (Z_SRW_diagnostic *) - odr_malloc(o, sizeof(*srw_res->diagnostics)); - yaz_mk_std_diagnostic(o, srw_res->diagnostics, srw_error, add); - return send_srw_response(srw_pdu); + Z_SRW_diagnostic *diagnostic = (Z_SRW_diagnostic *) + odr_malloc(o, sizeof(*diagnostic)); + int num_diagnostic = 1; + yaz_mk_std_diagnostic(o, diagnostic, srw_error, add); + return send_srw_search_response(diagnostic, num_diagnostic); } int Yaz_Proxy::z_to_srw_diag(ODR o, Z_SRW_searchRetrieveResponse *srw_res, @@ -1249,6 +1250,18 @@ int Yaz_Proxy::send_to_srw_client_ok(int hits, Z_Records *records, int start) } +int Yaz_Proxy::send_srw_search_response(Z_SRW_diagnostic *diagnostics, + int num_diagnostics) +{ + ODR o = odr_encode(); + Z_SRW_PDU *srw_pdu = yaz_srw_get(o, Z_SRW_searchRetrieve_response); + Z_SRW_searchRetrieveResponse *srw_res = srw_pdu->u.response; + + srw_res->num_diagnostics = num_diagnostics; + srw_res->diagnostics = diagnostics; + return send_srw_response(srw_pdu); +} + int Yaz_Proxy::send_srw_explain_response(Z_SRW_diagnostic *diagnostics, int num_diagnostics) { @@ -1499,6 +1512,38 @@ int Yaz_Proxy::send_to_client(Z_APDU *apdu) return r; } +void Yaz_ProxyClient::set_idAuthentication(Z_APDU *apdu) +{ + Z_IdAuthentication *t = apdu->u.initRequest->idAuthentication; + + odr_reset(m_idAuthentication_odr); + z_IdAuthentication(m_idAuthentication_odr, &t, 1, 0); + m_idAuthentication_ber_buf = + odr_getbuf(m_idAuthentication_odr, + &m_idAuthentication_ber_size, 0); +} + +bool Yaz_ProxyClient::compare_idAuthentication(Z_APDU *apdu) +{ + Z_IdAuthentication *t = apdu->u.initRequest->idAuthentication; + ODR odr = odr_createmem(ODR_ENCODE); + + z_IdAuthentication(odr, &t, 1, 0); + int sz; + char *buf = odr_getbuf(odr, &sz, 0); + if (buf && m_idAuthentication_ber_buf + && sz == m_idAuthentication_ber_size + && !memcmp(m_idAuthentication_ber_buf, buf, sz)) + { + odr_destroy(odr); + return true; + } + odr_destroy(odr); + if (!buf && !m_idAuthentication_ber_buf) + return true; + return false; +} + int Yaz_ProxyClient::send_to_target(Z_APDU *apdu) { int len = 0; @@ -2019,9 +2064,10 @@ void Yaz_Proxy::handle_charset_lang_negotiation(Z_APDU *apdu) { ODR_MASK_SET(initResponse->options, Z_Options_negotiationModel); - ODR_MASK_SET(m_initRequest_options, - Z_Options_negotiationModel); - + if (m_initRequest_options) + ODR_MASK_SET(m_initRequest_options, + Z_Options_negotiationModel); + oi->which = Z_OtherInfo_externallyDefinedInfo; oi->information.externallyDefinedInfo = yaz_set_response_charneg( @@ -2187,9 +2233,6 @@ int Yaz_Proxy::handle_authentication(Z_APDU *apdu) else ret = cfg->client_authentication(m_default_target, 0, 0, 0, m_peername); - - cfg->target_authentication(m_default_target, odr_encode(), req); - return ret; } @@ -3058,10 +3101,19 @@ void Yaz_Proxy::releaseClient() m_parent->pre_init(); } -bool Yaz_Proxy::dec_ref() +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) + { + if (m_main_ptr_dec) + return false; + m_main_ptr_dec = true; + } + + m_http_keepalive = 0; --m_ref_count; if (m_ref_count > 0) @@ -3088,7 +3140,7 @@ void Yaz_ProxyClient::shutdown() if (m_server) { m_waiting = 1; // ensure it's released from Proxy in releaseClient - m_server->dec_ref(); + m_server->dec_ref(true); } else delete this; @@ -3099,15 +3151,35 @@ void Yaz_Proxy::failNotify() inc_request_no(); yaz_log (YLOG_LOG, "%sConnection closed by client", get_session_str()); - dec_ref(); + dec_ref(true); } +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 num_diagnostic = 0; + + yaz_add_srw_diagnostic(odr_encode(), + &diagnostic, &num_diagnostic, + YAZ_SRW_SYSTEM_TEMPORARILY_UNAVAILABLE, addr); + if (m_s2z_search_apdu) + send_srw_search_response(diagnostic, num_diagnostic); + else + send_srw_explain_response(diagnostic, num_diagnostic); + } +} void Yaz_ProxyClient::failNotify() { if (m_server) m_server->inc_request_no(); yaz_log (YLOG_LOG, "%sConnection closed by target %s", get_session_str(), get_hostname()); + + if (m_server) + m_server->send_response_fail_client(get_hostname()); shutdown(); } @@ -3136,6 +3208,7 @@ Yaz_ProxyClient::~Yaz_ProxyClient() m_next->m_prev = m_prev; m_waiting = 2; // for debugging purposes only. odr_destroy(m_init_odr); + odr_destroy(m_idAuthentication_odr); delete m_last_query; xfree (m_last_resultSetId); xfree (m_cookie); @@ -3279,7 +3352,7 @@ void Yaz_Proxy::timeoutNotify() inc_request_no(); m_in_queue.clear(); yaz_log (YLOG_LOG, "%sTimeout (client to proxy)", m_session_str); - dec_ref(); + dec_ref(true); break; case timeout_reduce: timeout(m_client_idletime); @@ -3314,17 +3387,12 @@ void Yaz_ProxyClient::timeoutNotify() yaz_log (YLOG_LOG, "%sTimeout (proxy to target) %s", get_session_str(), 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; - } + + if (m_server) + m_server->send_response_fail_client(get_hostname()); shutdown(); + + m_root->pre_init(); } Yaz_ProxyClient::Yaz_ProxyClient(IPDU_Observable *the_PDU_Observable, @@ -3354,6 +3422,9 @@ Yaz_ProxyClient::Yaz_ProxyClient(IPDU_Observable *the_PDU_Observable, m_seqno = 0; m_target_idletime = 600; m_root = parent; + m_idAuthentication_odr = odr_createmem(ODR_ENCODE); + m_idAuthentication_ber_buf = 0; + m_idAuthentication_ber_size = 0; } const char *Yaz_Proxy::option(const char *name, const char *value)