/* This file is part of Metaproxy.
- Copyright (C) 2005-2013 Index Data
+ Copyright (C) Index Data
Metaproxy is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
#include <yaz/log.h>
#include <yaz/otherinfo.h>
#include <yaz/diagbib1.h>
+#include <yaz/oid_db.h>
+#include <yaz/charneg.h>
#include <yazpp/socket-manager.h>
#include <yazpp/pdu-assoc.h>
friend class Rep;
Assoc(yazpp_1::SocketManager *socket_manager,
yazpp_1::IPDU_Observable *PDU_Observable,
- std::string host, int timeout);
+ std::string host, int connect_timeout,
+ int init_timeout, int general_timeout);
~Assoc();
void connectNotify();
void failNotify();
bool m_in_use;
bool m_waiting;
bool m_destroyed;
- bool m_connected;
+ int m_connected; // 0=not connected, 1=init phase, 2=rest
bool m_has_closed;
int m_queue_len;
int m_time_elapsed;
- int m_time_max;
- int m_time_connect_max;
+ int m_connect_time_max;
+ int m_init_time_max;
+ int m_general_time_max;
std::string m_host;
};
class Z3950Client::Rep {
public:
// number of seconds to wait before we give up request
- int m_timeout_sec;
+ int m_general_timeout_sec;
+ int m_connect_timeout_sec;
+ int m_init_timeout_sec;
int m_max_sockets;
bool m_force_close;
+ bool m_client_ip;
+ bool m_bind_host;
+ std::string m_charset;
std::string m_default_target;
std::string m_force_target;
boost::mutex m_mutex;
yf::Z3950Client::Assoc::Assoc(yazpp_1::SocketManager *socket_manager,
yazpp_1::IPDU_Observable *PDU_Observable,
- std::string host, int timeout_sec)
+ std::string host,
+ int connect_timeout,
+ int init_timeout, int general_timeout)
: Z_Assoc(PDU_Observable),
m_socket_manager(socket_manager), m_PDU_Observable(PDU_Observable),
m_package(0), m_in_use(true), m_waiting(false),
- m_destroyed(false), m_connected(false), m_has_closed(false),
+ m_destroyed(false), m_connected(0), m_has_closed(false),
m_queue_len(1),
- m_time_elapsed(0), m_time_max(timeout_sec), m_time_connect_max(10),
+ m_time_elapsed(0),
+ m_connect_time_max(connect_timeout),
+ m_init_time_max(init_timeout),
+ m_general_time_max(general_timeout),
m_host(host)
{
// std::cout << "create assoc " << this << "\n";
{
m_waiting = false;
- m_connected = true;
+ m_connected = 1;
}
void yf::Z3950Client::Assoc::failNotify()
void yf::Z3950Client::Assoc::timeoutNotify()
{
m_time_elapsed++;
- if ((m_connected && m_time_elapsed >= m_time_max)
- || (!m_connected && m_time_elapsed >= m_time_connect_max))
+ if ((m_connected == 0 && m_time_elapsed >= m_connect_time_max)
+ || (m_connected == 1 && m_time_elapsed >= m_init_time_max)
+ || (m_connected >= 2 && m_time_elapsed >= m_general_time_max))
{
m_waiting = false;
if (gdu && gdu->which == Z_GDU_Z3950)
apdu = gdu->u.z3950;
- if (m_connected)
+ if (m_connected == 2)
m_package->response() =
odr.create_close(apdu, Z_Close_lackOfActivity, 0);
else
break;
case Z_APDU_initResponse:
fixup_init(odr, apdu->u.initResponse);
+ m_connected = 2;
break;
}
}
yf::Z3950Client::Z3950Client() : m_p(new yf::Z3950Client::Rep)
{
- m_p->m_timeout_sec = 30;
+ m_p->m_connect_timeout_sec = 10;
+ m_p->m_init_timeout_sec = 10;
+ m_p->m_general_timeout_sec = 30;
m_p->m_max_sockets = 0;
m_p->m_force_close = false;
+ m_p->m_client_ip = false;
+ m_p->m_bind_host = false;
}
yf::Z3950Client::~Z3950Client() {
yazpp_1::SocketManager *sm = new yazpp_1::SocketManager;
yazpp_1::PDU_Assoc *pdu_as = new yazpp_1::PDU_Assoc(sm);
- yf::Z3950Client::Assoc *as = new yf::Z3950Client::Assoc(sm, pdu_as,
- target.c_str(),
- m_timeout_sec);
+ yf::Z3950Client::Assoc *as =
+ new yf::Z3950Client::Assoc(sm, pdu_as, target.c_str(),
+ m_connect_timeout_sec,
+ m_init_timeout_sec,
+ m_general_timeout_sec);
m_clients[package.session()] = as;
return as;
}
+static void set_charset_proposal(ODR odr, Z_InitRequest *req, const char *charset)
+{
+ Z_OtherInformation **p = &req->otherInfo;
+ Z_OtherInformationUnit *oi;
+
+ if (*p)
+ {
+ int i;
+ for (i = 0; i < (*p)->num_elements; i++)
+ {
+ Z_External *ext = (*p)->list[i]->information.externallyDefinedInfo;
+ if ((*p)->list[i]->which == Z_OtherInfo_externallyDefinedInfo
+ && ext &&
+ ext->which == Z_External_charSetandLanguageNegotiation)
+ return;
+ }
+ }
+ if ((oi = yaz_oi_update(p, odr, 0, 0, 0)))
+ {
+ ODR_MASK_SET(req->options, Z_Options_negotiationModel);
+ oi->which = Z_OtherInfo_externallyDefinedInfo;
+ oi->information.externallyDefinedInfo =
+ yaz_set_proposal_charneg_list(odr, ",",
+ charset,
+ 0 /* lang */,
+ 1 /* records included */);
+ }
+}
+
void yf::Z3950Client::Rep::send_and_receive(Package &package,
yf::Z3950Client::Assoc *c)
{
if (gdu->u.z3950->which == Z_APDU_close)
c->m_has_closed = true;
+ Z_APDU *apdu = gdu->u.z3950;
+
// prepare connect
c->m_time_elapsed = 0;
c->m_waiting = true;
if (!c->m_connected)
{
- if (c->client(c->m_host.c_str()))
+ std::string host(c->m_host);
+
+ if (m_bind_host)
+ {
+ std::string bind_host = package.origin().get_bind_address();
+ if (bind_host.length())
+ {
+ host.append(" ");
+ host.append(bind_host);
+ }
+ }
+ if (c->client(host.c_str()))
{
mp::odr odr;
package.response() =
{
return;
}
+ mp::odr odr;
+ if (m_client_ip)
+ {
+ std::string peer_name2 = package.origin().get_address();
+ if (apdu->which == Z_APDU_initRequest && peer_name2.length())
+ {
+ Z_OtherInformation **oi = &apdu->u.initRequest->otherInfo;
+ char *peer_name1 =
+ yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 1);
+ std::string pcomb;
+ if (peer_name1)
+ {
+ pcomb.append(peer_name1);
+ pcomb.append(", ");
+ }
+ pcomb.append(peer_name2);
+ yaz_oi_set_string_oid(&apdu->u.initRequest->otherInfo,
+ odr, yaz_oid_userinfo_client_ip,
+ 1, pcomb.c_str());
+ }
+ }
+ if (apdu->which == Z_APDU_initRequest && m_charset.length() > 0)
+ set_charset_proposal(odr, apdu->u.initRequest, m_charset.c_str());
// prepare response
c->m_time_elapsed = 0;
continue;
if (!strcmp((const char *) ptr->name, "timeout"))
{
- m_p->m_timeout_sec = mp::xml::get_int(ptr, 30);
+ m_p->m_general_timeout_sec = mp::xml::get_int(ptr, 30);
+ }
+ else if (!strcmp((const char *) ptr->name, "connect-timeout"))
+ {
+ m_p->m_connect_timeout_sec = mp::xml::get_int(ptr, 10);
+ }
+ else if (!strcmp((const char *) ptr->name, "init-timeout"))
+ {
+ m_p->m_init_timeout_sec = mp::xml::get_int(ptr, 10);
}
else if (!strcmp((const char *) ptr->name, "default_target"))
{
{
m_p->m_force_close = mp::xml::get_bool(ptr, 0);
}
+ else if (!strcmp((const char *) ptr->name, "client_ip"))
+ {
+ m_p->m_client_ip = mp::xml::get_bool(ptr, 0);
+ }
+ else if (!strcmp((const char *) ptr->name, "charset"))
+ {
+ m_p->m_charset = mp::xml::get_text(ptr);
+ }
+ else if (!strcmp((const char *) ptr->name, "bind_host"))
+ {
+ m_p->m_bind_host = mp::xml::get_bool(ptr, 0);
+ }
else
{
throw mp::filter::FilterException("Bad element "