test_thread_pool_observer
test_session1
test_session2
+test_filter_z3950_client
-## $Id: Makefile.am,v 1.19 2005-10-15 11:02:08 adam Exp $
+## $Id: Makefile.am,v 1.20 2005-10-16 16:05:44 adam Exp $
MAINTAINERCLEANFILES = Makefile.in config.in config.hpp
session.cpp session.hpp package.hpp filter.hpp router.hpp \
thread_pool_observer.cpp thread_pool_observer.hpp \
filter_frontend_net.cpp filter_frontend_net.hpp \
- filter_log.cpp filter_log.hpp
+ filter_log.cpp filter_log.hpp \
+ filter_z3950_client.cpp filter_z3950_client.hpp
# Rules for programs..
test_session1 test_session2 \
test_thread_pool_observer \
test_boost_threads test_boost_time \
- test_filter_frontend_net
+ test_filter_frontend_net \
+ test_filter_z3950_client
TESTS=$(check_PROGRAMS)
test_boost_time_SOURCES=test_boost_time.cpp
test_thread_pool_observer_SOURCES = test_thread_pool_observer.cpp
test_filter_frontend_net_SOURCES = test_filter_frontend_net.cpp
+test_filter_z3950_client_SOURCES = test_filter_z3950_client.cpp
TESTLDADD = $(LDADD) -lboost_unit_test_framework
test_thread_pool_observer_LDADD = $(TESTLDADD)
test_package1_LDADD = $(TESTLDADD)
test_filter_frontend_net_LDADD = $(TESTLDADD)
+test_filter_z3950_client_LDADD = $(TESTLDADD)
# doxygen target
dox:
-/* $Id: ex_filter_frontend_net.cpp,v 1.7 2005-10-15 14:09:09 adam Exp $
+/* $Id: ex_filter_frontend_net.cpp,v 1.8 2005-10-16 16:05:44 adam Exp $
Copyright (c) 2005, Index Data.
%LICENSE%
#include "config.hpp"
#include "filter_frontend_net.hpp"
+#include "filter_z3950_client.hpp"
#include "filter_log.hpp"
#include "router.hpp"
#include "session.hpp"
#include "package.hpp"
-class FilterInit: public yp2::filter::Base {
+class HTTPFilter: public yp2::filter::Base {
public:
void process(yp2::Package & package) const {
-
if (package.session().is_closed())
{
// std::cout << "Got Close.\n";
}
Z_GDU *gdu = package.request().get();
- if (gdu)
+ if (gdu && gdu->which == Z_GDU_HTTP_Request)
{
ODR odr = odr_createmem(ODR_ENCODE);
- switch(gdu->which)
- {
- case Z_GDU_Z3950:
- // std::cout << "Got PDU. Sending init response\n";
- Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
-
- apdu->u.initResponse->implementationName = "YP2/YAZ";
-
- package.response() = apdu;
- break;
- case Z_GDU_HTTP_Request:
- Z_GDU *gdu = z_get_HTTP_Response(odr, 200);
- Z_HTTP_Response *http_res = gdu->u.HTTP_Response;
-
- z_HTTP_header_add(odr, &http_res->headers,
- "Content-Type", "text/plain");
-
- http_res->content_buf =
- odr_strdup(odr, "Welcome to YP2");
- http_res->content_len = strlen(http_res->content_buf);
-
- package.response() = gdu;
- break;
- default:
- break;
- }
+ Z_GDU *gdu = z_get_HTTP_Response(odr, 200);
+ Z_HTTP_Response *http_res = gdu->u.HTTP_Response;
+
+ z_HTTP_header_add(odr, &http_res->headers,
+ "Content-Type", "text/plain");
+
+ http_res->content_buf =
+ odr_strdup(odr, "Welcome to YP2");
+ http_res->content_len = strlen(http_res->content_buf);
+
+ package.response() = gdu;
odr_destroy(odr);
}
return package.move();
yp2::filter::Log filter_log;
router.rule(filter_log);
- // put backend init filter in router
- FilterInit filter_init;
+ // put HTTP backend filter in router
+ HTTPFilter filter_init;
router.rule(filter_init);
+ // put Z39.50 backend filter in router
+ yp2::filter::Z3950Client z3950_client;
+ router.rule(z3950_client);
+
yp2::Session session;
yp2::Origin origin;
yp2::Package pack(session, origin);
-/* $Id: filter.hpp,v 1.4 2005-10-15 14:09:09 adam Exp $
+/* $Id: filter.hpp,v 1.5 2005-10-16 16:05:44 adam Exp $
Copyright (c) 2005, Index Data.
%LICENSE%
virtual ~Base(){};
///sends Package off to next Filter, returns altered Package
- virtual void process(Package & package) const {
- };
- virtual void configure(){};
+ virtual void process(Package & package) const = 0;
+
+ virtual void configure(){};
/// get function - right val in assignment
std::string name() const {
-/* $Id: filter_log.cpp,v 1.3 2005-10-15 14:09:09 adam Exp $
+/* $Id: filter_log.cpp,v 1.4 2005-10-16 16:05:44 adam Exp $
Copyright (c) 2005, Index Data.
%LICENSE%
Z_GDU *gdu;
+ std::cout << "---- req id=" << package.session().id();
+
+ std::cout << " close=" << (package.session().is_closed() ? "yes" : "no")
+ << "\n";
gdu = package.request().get();
if (gdu)
{
}
package.move();
+
+ std::cout << "---- res id=" << package.session().id();
+
+ std::cout << " close=" << (package.session().is_closed() ? "yes" : "no")
+ << "\n";
gdu = package.response().get();
if (gdu)
{
--- /dev/null
+/* $Id: filter_z3950_client.cpp,v 1.1 2005-10-16 16:05:44 adam Exp $
+ Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#include "config.hpp"
+
+#include "filter.hpp"
+#include "router.hpp"
+#include "package.hpp"
+
+#include <boost/thread/mutex.hpp>
+
+#include "filter_z3950_client.hpp"
+
+#include <yaz/zgdu.h>
+#include <yaz/log.h>
+#include <yaz/otherinfo.h>
+#include <yaz/diagbib1.h>
+
+#include <yaz++/socket-manager.h>
+#include <yaz++/pdu-assoc.h>
+#include <yaz++/z-assoc.h>
+
+#include <iostream>
+
+namespace yf = yp2::filter;
+
+namespace yp2 {
+ namespace filter {
+ class Z3950Client::Assoc : public yazpp_1::Z_Assoc{
+ friend class Pimpl;
+ public:
+ Assoc(yp2::Session id, yazpp_1::SocketManager *socket_manager,
+ yazpp_1::IPDU_Observable *PDU_Observable,
+ std::string host);
+ ~Assoc();
+ void connectNotify();
+ void failNotify();
+ void timeoutNotify();
+ void recv_GDU(Z_GDU *gdu, int len);
+ yazpp_1::IPDU_Observer* sessionNotify(
+ yazpp_1::IPDU_Observable *the_PDU_Observable,
+ int fd);
+ private:
+ yp2::Session m_session_id;
+ yazpp_1::SocketManager *m_socket_manager;
+ yazpp_1::IPDU_Observable *m_PDU_Observable;
+ Package *m_package;
+ bool m_waiting;
+ bool m_connected;
+ std::string m_host;
+ };
+
+ class Z3950Client::Pimpl {
+ public:
+ boost::mutex m_mutex;
+ std::list<Z3950Client::Assoc *> m_clients;
+ Z3950Client::Assoc *get_assoc(Package &package);
+ void send_and_receive(Package &package,
+ yf::Z3950Client::Assoc *c);
+ };
+ }
+}
+
+
+yf::Z3950Client::Assoc::Assoc(yp2::Session id,
+ yazpp_1::SocketManager *socket_manager,
+ yazpp_1::IPDU_Observable *PDU_Observable,
+ std::string host)
+ : Z_Assoc(PDU_Observable), m_session_id(id),
+ m_socket_manager(socket_manager), m_PDU_Observable(PDU_Observable),
+ m_package(0), m_waiting(false), m_connected(false),
+ m_host(host)
+{
+}
+
+yf::Z3950Client::Assoc::~Assoc()
+{
+ delete m_socket_manager;
+}
+
+void yf::Z3950Client::Assoc::connectNotify()
+{
+ m_waiting = false;
+
+ m_connected = true;
+}
+
+void yf::Z3950Client::Assoc::failNotify()
+{
+ m_waiting = false;
+
+ ODR odr = odr_createmem(ODR_ENCODE);
+
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
+
+ *apdu->u.close->closeReason = Z_Close_peerAbort;
+
+ if (m_package)
+ {
+ m_package->response() = apdu;
+ m_package->session().close();
+ }
+
+ odr_destroy(odr);
+}
+
+void yf::Z3950Client::Assoc::timeoutNotify()
+{
+ m_waiting = false;
+
+ ODR odr = odr_createmem(ODR_ENCODE);
+
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
+
+ *apdu->u.close->closeReason = Z_Close_lackOfActivity;
+
+ if (m_package)
+ {
+ m_package->response() = apdu;
+ m_package->session().close();
+ }
+ odr_destroy(odr);
+}
+
+void yf::Z3950Client::Assoc::recv_GDU(Z_GDU *gdu, int len)
+{
+ m_waiting = false;
+
+ if (m_package)
+ m_package->response() = gdu;
+}
+
+yazpp_1::IPDU_Observer *yf::Z3950Client::Assoc::sessionNotify(
+ yazpp_1::IPDU_Observable *the_PDU_Observable,
+ int fd)
+{
+ return 0;
+}
+
+
+yf::Z3950Client::Z3950Client() {
+ m_p = new yf::Z3950Client::Pimpl;
+}
+
+yf::Z3950Client::~Z3950Client() {
+ delete m_p;
+}
+
+yf::Z3950Client::Assoc *yf::Z3950Client::Pimpl::get_assoc(Package &package)
+{
+ Z_GDU *gdu = package.request().get();
+
+ // only deal with Z39.50
+ if (!gdu || gdu->which != Z_GDU_Z3950)
+ {
+ package.move();
+ return 0;
+ }
+
+ // only one thread messes with the clients list at a time
+ boost::mutex::scoped_lock lock(m_mutex);
+
+ Z_APDU *apdu = gdu->u.z3950;
+
+ std::list<yf::Z3950Client::Assoc *>::iterator it;
+
+ for (it = m_clients.begin(); it != m_clients.end(); it++)
+ {
+ if ((*it)->m_session_id == package.session())
+ break;
+ }
+ if (it != m_clients.end())
+ return *it;
+
+ // new session ..
+
+ // check that it is init. If not, close
+ if (apdu->which != Z_APDU_initRequest)
+ {
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
+
+ *apdu->u.close->closeReason = Z_Close_protocolError;
+ package.response() = apdu;
+
+ package.session().close();
+ odr_destroy(odr);
+ return 0;
+ }
+ // check virtual host
+ const char *vhost =
+ yaz_oi_get_string_oidval(&apdu->u.initRequest->otherInfo,
+ VAL_PROXY, 1, 0);
+ if (!vhost)
+ {
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
+
+ apdu->u.initResponse->userInformationField =
+ zget_init_diagnostics(odr,
+ YAZ_BIB1_INIT_NEGOTIATION_OPTION_REQUIRED,
+ "Virtual host not given");
+ package.response() = apdu;
+
+ package.session().close();
+ odr_destroy(odr);
+ return 0;
+ }
+
+ 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(package.session(),
+ sm, pdu_as,
+ vhost);
+ m_clients.push_back(as);
+ return as;
+}
+
+void yf::Z3950Client::Pimpl::send_and_receive(Package &package,
+ yf::Z3950Client::Assoc *c)
+{
+ // we should lock c!
+
+ c->m_package = &package;
+ c->m_waiting = true;
+ if (!c->m_connected)
+ {
+ c->client(c->m_host.c_str());
+
+ while (c->m_waiting && c->m_socket_manager->processEvent() > 0)
+ ;
+ }
+ if (!c->m_connected)
+ {
+ return;
+ }
+
+ // prepare response
+ c->m_waiting = true;
+
+ // relay the package ..
+ int len;
+ c->send_GDU(package.request().get(), &len);
+
+ while (c->m_waiting && c->m_socket_manager->processEvent() > 0)
+ ;
+}
+
+void yf::Z3950Client::process(Package &package) const
+{
+ yf::Z3950Client::Assoc *c = m_p->get_assoc(package);
+ if (!c)
+ return;
+ m_p->send_and_receive(package, c);
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
--- /dev/null
+/* $Id: filter_z3950_client.hpp,v 1.1 2005-10-16 16:05:44 adam Exp $
+ Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#ifndef FILTER_Z3950_CLIENT_HPP
+#define FILTER_Z3950_CLIENT_HPP
+
+#include <stdexcept>
+#include <list>
+
+#include "filter.hpp"
+
+namespace yp2 {
+ namespace filter {
+ class Z3950Client : public Base {
+ class Pimpl;
+ class Assoc;
+ public:
+ ~Z3950Client();
+ Z3950Client();
+ void process(yp2::Package & package) const;
+ private:
+ Pimpl *m_p;
+ };
+ }
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
-/* $Id: test_filter_frontend_net.cpp,v 1.7 2005-10-15 14:09:09 adam Exp $
+/* $Id: test_filter_frontend_net.cpp,v 1.8 2005-10-16 16:05:44 adam Exp $
Copyright (c) 2005, Index Data.
%LICENSE%
class FilterInit: public yp2::filter::Base {
public:
void process(yp2::Package & package) const {
-
+
if (package.session().is_closed())
{
// std::cout << "Got Close.\n";
--- /dev/null
+/* $Id: test_filter_z3950_client.cpp,v 1.1 2005-10-16 16:05:44 adam Exp $
+ Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#include "config.hpp"
+#include <iostream>
+#include <stdexcept>
+
+#include "filter_z3950_client.hpp"
+
+#include "router.hpp"
+#include "session.hpp"
+#include "package.hpp"
+
+#define BOOST_AUTO_TEST_MAIN
+#include <boost/test/auto_unit_test.hpp>
+
+#include <yaz/zgdu.h>
+#include <yaz/otherinfo.h>
+using namespace boost::unit_test;
+
+
+BOOST_AUTO_TEST_CASE( test_filter_z3950_client_1 )
+{
+ try
+ {
+ {
+ yp2::filter::Z3950Client zc;
+ }
+ }
+ catch ( ... ) {
+ BOOST_CHECK (false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE( test_filter_z3950_client_2 )
+{
+ try
+ {
+ {
+ yp2::RouterChain router;
+
+ yp2::filter::Z3950Client zc;
+
+ router.rule(zc);
+
+ // Create package with Z39.50 init request in it
+ yp2::Package pack;
+
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_initRequest);
+
+ BOOST_CHECK(apdu);
+
+ pack.request() = apdu;
+ odr_destroy(odr);
+
+ // Put it in router
+ pack.router(router).move();
+
+ // Inspect that we got Z39.50 init Response - a Z39.50 session
+ // specify a virtual host
+ yazpp_1::GDU *gdu = &pack.response();
+
+ BOOST_CHECK(pack.session().is_closed());
+
+ Z_GDU *z_gdu = gdu->get();
+ BOOST_CHECK(z_gdu);
+ if (z_gdu) {
+ BOOST_CHECK_EQUAL(z_gdu->which, Z_GDU_Z3950);
+ BOOST_CHECK_EQUAL(z_gdu->u.z3950->which, Z_APDU_initResponse);
+ }
+ }
+ }
+ catch ( ... ) {
+ BOOST_CHECK (false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE( test_filter_z3950_client_3 )
+{
+ try
+ {
+ {
+ yp2::RouterChain router;
+
+ yp2::filter::Z3950Client zc;
+
+ router.rule(zc);
+
+ // Create package with Z39.50 present request in it
+ yp2::Package pack;
+
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_presentRequest);
+
+ BOOST_CHECK(apdu);
+
+ pack.request() = apdu;
+ odr_destroy(odr);
+
+ // Put it in router
+ pack.router(router).move();
+
+ // Inspect that we got Z39.50 close - a Z39.50 session must start
+ // with an init !
+ yazpp_1::GDU *gdu = &pack.response();
+
+ BOOST_CHECK(pack.session().is_closed());
+
+ Z_GDU *z_gdu = gdu->get();
+ BOOST_CHECK(z_gdu);
+ if (z_gdu) {
+ BOOST_CHECK_EQUAL(z_gdu->which, Z_GDU_Z3950);
+ BOOST_CHECK_EQUAL(z_gdu->u.z3950->which, Z_APDU_close);
+ }
+ }
+ }
+ catch ( ... ) {
+ BOOST_CHECK (false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE( test_filter_z3950_client_4 )
+{
+ try
+ {
+ {
+ yp2::RouterChain router;
+
+ yp2::filter::Z3950Client zc;
+
+ router.rule(zc);
+
+ // Create package with Z39.50 init request in it
+ yp2::Package pack;
+
+ ODR odr = odr_createmem(ODR_ENCODE);
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_initRequest);
+
+ const char *vhost = "localhost:9999";
+ if (vhost)
+ yaz_oi_set_string_oidval(&apdu->u.initRequest->otherInfo,
+ odr, VAL_PROXY, 1, vhost);
+
+ BOOST_CHECK(apdu);
+
+ pack.request() = apdu;
+ odr_destroy(odr);
+
+ // Put it in router
+ pack.router(router).move();
+
+ // Inspect that we got Z39.50 close - a Z39.50 session must start
+ // with an init !
+ yazpp_1::GDU *gdu = &pack.response();
+
+ BOOST_CHECK(!pack.session().is_closed());
+
+ Z_GDU *z_gdu = gdu->get();
+ BOOST_CHECK(z_gdu);
+ if (z_gdu) {
+ BOOST_CHECK_EQUAL(z_gdu->which, Z_GDU_Z3950);
+ BOOST_CHECK_EQUAL(z_gdu->u.z3950->which, Z_APDU_initResponse);
+ }
+ }
+ }
+ catch ( ... ) {
+ BOOST_CHECK (false);
+ }
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */