-/* $Id: yaz-proxy.cpp,v 1.37 2005-09-26 09:25:06 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.
{
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;
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)
low_socket_open();
m_my_thread = 0;
m_ref_count = 1;
+ m_main_ptr_dec = false;
m_peername = 0;
}
}
}
}
- 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.
{
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",
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;
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;
{
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)
m_bytes_sent += len;
m_bw_stat.add_bytes(len);
logtime();
+
+ recv_GDU_more(true);
+
return r;
}
m_bytes_sent += len;
m_bw_stat.add_bytes(len);
logtime();
+
+ recv_GDU_more(true);
+
return r;
}
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,
}
+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)
{
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;
void Yaz_Proxy::recv_GDU_normal(GDU *gdu)
{
- Z_GDU *apdu = gdu->get();
- gdu->extract_odr_to(odr_decode());
+ Z_GDU *apdu = 0;
+ gdu->move_away_gdu(odr_decode(), &apdu);
delete gdu;
if (apdu->which == Z_GDU_Z3950)
{
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(
else
ret = cfg->client_authentication(m_default_target, 0, 0, 0,
m_peername);
-
- cfg->target_authentication(m_default_target, odr_encode(), req);
-
return ret;
}
}
int len;
send_GDU(gdu, &len);
+ recv_GDU_more(true);
return 1;
}
const char *pqf_msg;
size_t off;
int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off);
- yaz_log(YLOG_LOG, "%*s^\n", off+4, "");
+ int ioff = off;
+ yaz_log(YLOG_LOG, "%*s^\n", ioff+4, "");
yaz_log(YLOG_LOG, "Bad PQF: %s (code %d)\n", pqf_msg, code);
send_to_srw_client_error(10, 0);
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)
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;
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();
}
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);
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);
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,
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)