HTTP X-Forwarded-For/Z39.50 Client-IP support
[metaproxy-moved-to-github.git] / src / filter_z3950_client.cpp
index 2241503..6ea58e4 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,7 @@ 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 <yazpp/socket-manager.h>
 #include <yazpp/pdu-assoc.h>
@@ -56,6 +57,7 @@ namespace metaproxy_1 {
             void timeoutNotify();
             void recv_GDU(Z_GDU *gdu, int len);
             void fixup_nsd(ODR odr, Z_Records *records);
+            void fixup_nsd(ODR odr, Z_DefaultDiagFormat *nsd);
             void fixup_init(ODR odr, Z_InitResponse *initrs);
             yazpp_1::IPDU_Observer* sessionNotify(
                 yazpp_1::IPDU_Observable *the_PDU_Observable,
@@ -170,25 +172,40 @@ void yf::Z3950Client::Assoc::timeoutNotify()
     }
 }
 
+void yf::Z3950Client::Assoc::fixup_nsd(ODR odr, Z_DefaultDiagFormat *nsd)
+{
+    std::string addinfo;
+
+    // should really check for nsd->which.. But union has two members
+    // containing almost same data
+    const char *v2Addinfo = nsd->u.v2Addinfo;
+    //  Z_InternationalString *v3Addinfo;
+    if (v2Addinfo && *v2Addinfo)
+    {
+        addinfo.assign(nsd->u.v2Addinfo);
+        addinfo += " ";
+    }
+    addinfo += "(backend=" + m_host + ")";
+    nsd->u.v2Addinfo = odr_strdup(odr, addinfo.c_str());
+}
+
 void yf::Z3950Client::Assoc::fixup_nsd(ODR odr, Z_Records *records)
 {
     if (records && records->which == Z_Records_NSD)
     {
-        Z_DefaultDiagFormat *nsd = records->u.nonSurrogateDiagnostic;
-       std::string addinfo;
-
-        // should really check for nsd->which.. But union has two members
-        // containing almost same data
-        const char *v2Addinfo = nsd->u.v2Addinfo;
-       //  Z_InternationalString *v3Addinfo;
-
-        if (v2Addinfo && *v2Addinfo)
+        fixup_nsd(odr, records->u.nonSurrogateDiagnostic);
+    }
+    if (records && records->which == Z_Records_multipleNSD)
+    {
+        Z_DiagRecs *drecs = records->u.multipleNonSurDiagnostics;
+        int i;
+        for (i = 0; i < drecs->num_diagRecs; i++)
         {
-            addinfo.assign(nsd->u.v2Addinfo);
-            addinfo += " ";
+            Z_DiagRec *dr = drecs->diagRecs[i];
+
+            if (dr->which == Z_DiagRec_defaultFormat)
+                fixup_nsd(odr, dr->u.defaultFormat);
         }
-        addinfo += "(backend=" + m_host + ")";
-        nsd->u.v2Addinfo = odr_strdup(odr, addinfo.c_str());
     }
 }
 
@@ -222,9 +239,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=");
@@ -408,12 +426,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))
@@ -421,7 +446,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;
         }
@@ -461,6 +487,8 @@ 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;
@@ -485,7 +513,27 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package,
     {
         return;
     }
-
+    const char *peer_name2 = package.origin().get_address().c_str();
+    mp::odr odr;
+    if (apdu->which == Z_APDU_initRequest && peer_name2)
+    {
+        Z_OtherInformation **oi = &apdu->u.initRequest->otherInfo;
+        char *peer_name1 =
+            yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 1);
+        char *pcomb = (char *)
+            odr_malloc(odr, (peer_name1 ? strlen(peer_name1) : 0)
+                       + strlen(peer_name2) + 4);
+        strcpy(pcomb, "");
+        if (peer_name1)
+        {
+            strcat(pcomb, peer_name1);
+            strcat(pcomb, ", ");
+        }
+        strcat(pcomb, peer_name2);
+        yaz_oi_set_string_oid(&apdu->u.initRequest->otherInfo,
+                              odr, yaz_oid_userinfo_client_ip,
+                              1, pcomb);
+    }
     // prepare response
     c->m_time_elapsed = 0;
     c->m_waiting = true;