1 /* $Id: filter_z3950_client.cpp,v 1.1 2005-10-16 16:05:44 adam Exp $
2 Copyright (c) 2005, Index Data.
11 #include "package.hpp"
13 #include <boost/thread/mutex.hpp>
15 #include "filter_z3950_client.hpp"
19 #include <yaz/otherinfo.h>
20 #include <yaz/diagbib1.h>
22 #include <yaz++/socket-manager.h>
23 #include <yaz++/pdu-assoc.h>
24 #include <yaz++/z-assoc.h>
28 namespace yf = yp2::filter;
32 class Z3950Client::Assoc : public yazpp_1::Z_Assoc{
35 Assoc(yp2::Session id, yazpp_1::SocketManager *socket_manager,
36 yazpp_1::IPDU_Observable *PDU_Observable,
42 void recv_GDU(Z_GDU *gdu, int len);
43 yazpp_1::IPDU_Observer* sessionNotify(
44 yazpp_1::IPDU_Observable *the_PDU_Observable,
47 yp2::Session m_session_id;
48 yazpp_1::SocketManager *m_socket_manager;
49 yazpp_1::IPDU_Observable *m_PDU_Observable;
56 class Z3950Client::Pimpl {
59 std::list<Z3950Client::Assoc *> m_clients;
60 Z3950Client::Assoc *get_assoc(Package &package);
61 void send_and_receive(Package &package,
62 yf::Z3950Client::Assoc *c);
68 yf::Z3950Client::Assoc::Assoc(yp2::Session id,
69 yazpp_1::SocketManager *socket_manager,
70 yazpp_1::IPDU_Observable *PDU_Observable,
72 : Z_Assoc(PDU_Observable), m_session_id(id),
73 m_socket_manager(socket_manager), m_PDU_Observable(PDU_Observable),
74 m_package(0), m_waiting(false), m_connected(false),
79 yf::Z3950Client::Assoc::~Assoc()
81 delete m_socket_manager;
84 void yf::Z3950Client::Assoc::connectNotify()
91 void yf::Z3950Client::Assoc::failNotify()
95 ODR odr = odr_createmem(ODR_ENCODE);
97 Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
99 *apdu->u.close->closeReason = Z_Close_peerAbort;
103 m_package->response() = apdu;
104 m_package->session().close();
110 void yf::Z3950Client::Assoc::timeoutNotify()
114 ODR odr = odr_createmem(ODR_ENCODE);
116 Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
118 *apdu->u.close->closeReason = Z_Close_lackOfActivity;
122 m_package->response() = apdu;
123 m_package->session().close();
128 void yf::Z3950Client::Assoc::recv_GDU(Z_GDU *gdu, int len)
133 m_package->response() = gdu;
136 yazpp_1::IPDU_Observer *yf::Z3950Client::Assoc::sessionNotify(
137 yazpp_1::IPDU_Observable *the_PDU_Observable,
144 yf::Z3950Client::Z3950Client() {
145 m_p = new yf::Z3950Client::Pimpl;
148 yf::Z3950Client::~Z3950Client() {
152 yf::Z3950Client::Assoc *yf::Z3950Client::Pimpl::get_assoc(Package &package)
154 Z_GDU *gdu = package.request().get();
156 // only deal with Z39.50
157 if (!gdu || gdu->which != Z_GDU_Z3950)
163 // only one thread messes with the clients list at a time
164 boost::mutex::scoped_lock lock(m_mutex);
166 Z_APDU *apdu = gdu->u.z3950;
168 std::list<yf::Z3950Client::Assoc *>::iterator it;
170 for (it = m_clients.begin(); it != m_clients.end(); it++)
172 if ((*it)->m_session_id == package.session())
175 if (it != m_clients.end())
180 // check that it is init. If not, close
181 if (apdu->which != Z_APDU_initRequest)
183 ODR odr = odr_createmem(ODR_ENCODE);
184 Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
186 *apdu->u.close->closeReason = Z_Close_protocolError;
187 package.response() = apdu;
189 package.session().close();
193 // check virtual host
195 yaz_oi_get_string_oidval(&apdu->u.initRequest->otherInfo,
199 ODR odr = odr_createmem(ODR_ENCODE);
200 Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
202 apdu->u.initResponse->userInformationField =
203 zget_init_diagnostics(odr,
204 YAZ_BIB1_INIT_NEGOTIATION_OPTION_REQUIRED,
205 "Virtual host not given");
206 package.response() = apdu;
208 package.session().close();
213 yazpp_1::SocketManager *sm = new yazpp_1::SocketManager;
214 yazpp_1::PDU_Assoc *pdu_as = new yazpp_1::PDU_Assoc(sm);
215 yf::Z3950Client::Assoc *as = new yf::Z3950Client::Assoc(package.session(),
218 m_clients.push_back(as);
222 void yf::Z3950Client::Pimpl::send_and_receive(Package &package,
223 yf::Z3950Client::Assoc *c)
227 c->m_package = &package;
231 c->client(c->m_host.c_str());
233 while (c->m_waiting && c->m_socket_manager->processEvent() > 0)
244 // relay the package ..
246 c->send_GDU(package.request().get(), &len);
248 while (c->m_waiting && c->m_socket_manager->processEvent() > 0)
252 void yf::Z3950Client::process(Package &package) const
254 yf::Z3950Client::Assoc *c = m_p->get_assoc(package);
257 m_p->send_and_receive(package, c);
264 * indent-tabs-mode: nil
265 * c-file-style: "stroustrup"
267 * vim: shiftwidth=4 tabstop=8 expandtab