Fix Metaproxy stops logging after check config failed MP-590
[metaproxy-moved-to-github.git] / src / filter_z3950_client.cpp
index d4f78a9..dd16ffe 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of Metaproxy.
-   Copyright (C) 2005-2012 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
@@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #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>
@@ -83,6 +85,9 @@ namespace metaproxy_1 {
             int m_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;
@@ -238,9 +243,10 @@ void yf::Z3950Client::Assoc::fixup_init(ODR odr, Z_InitResponse *initrs)
                             odr,
                             (oaddinfo ? strlen(oaddinfo) : 0) + 20 +
                             m_host.length());
+                        *naddinfo = '\0';
                         if (oaddinfo && *oaddinfo)
                         {
-                            strcpy(naddinfo, oaddinfo);
+                            strcat(naddinfo, oaddinfo);
                             strcat(naddinfo, " ");
                         }
                         strcat(naddinfo, "(backend=");
@@ -295,6 +301,8 @@ yf::Z3950Client::Z3950Client() :  m_p(new yf::Z3950Client::Rep)
     m_p->m_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() {
@@ -424,12 +432,19 @@ yf::Z3950Client::Assoc *yf::Z3950Client::Rep::get_assoc(Package &package)
             mp::odr odr;
 
             package.response() = odr.create_initResponse(
-                apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, "max sessions");
+                apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
+                "z3950_client: max sessions");
             package.session().close();
             return 0;
         }
         boost::xtime xt;
-        xtime_get(&xt, boost::TIME_UTC);
+        xtime_get(&xt,
+#if BOOST_VERSION >= 105000 
+                boost::TIME_UTC_
+#else
+                boost::TIME_UTC
+#endif 
+                );
 
         xt.sec += 15;
         if (!m_cond_session_ready.timed_wait(lock, xt))
@@ -437,7 +452,8 @@ yf::Z3950Client::Assoc *yf::Z3950Client::Rep::get_assoc(Package &package)
             mp::odr odr;
 
             package.response() = odr.create_initResponse(
-                apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, "max sessions");
+                apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
+                "z3950_client: max sessions");
             package.session().close();
             return 0;
         }
@@ -452,6 +468,35 @@ yf::Z3950Client::Assoc *yf::Z3950Client::Rep::get_assoc(Package &package)
     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)
 {
@@ -477,12 +522,25 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package,
     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() =
@@ -501,6 +559,29 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package,
     {
         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;
@@ -588,6 +669,18 @@ void yf::Z3950Client::configure(const xmlNode *ptr, bool test_only,
         {
             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 "