Started work on shared session filter.
[metaproxy-moved-to-github.git] / src / filter_session_shared.cpp
1 /* $Id: filter_session_shared.cpp,v 1.1 2005-11-14 23:35:22 adam Exp $
2    Copyright (c) 2005, Index Data.
3
4 %LICENSE%
5  */
6
7 #include "config.hpp"
8
9 #include "filter.hpp"
10 #include "router.hpp"
11 #include "package.hpp"
12
13 #include <boost/thread/mutex.hpp>
14 #include <boost/shared_ptr.hpp>
15
16 #include "util.hpp"
17 #include "filter_session_shared.hpp"
18
19 #include <yaz/log.h>
20 #include <yaz/zgdu.h>
21 #include <yaz/otherinfo.h>
22 #include <yaz/diagbib1.h>
23
24 #include <map>
25 #include <iostream>
26
27 namespace yf = yp2::filter;
28
29 namespace yp2 {
30     namespace filter {
31         class Session_shared::Rep {
32             friend class Session_shared;
33             void handle_init(Z_InitRequest *req, Package &package);
34             void handle_search(Z_SearchRequest *req, Package &package);
35         public:
36             typedef boost::shared_ptr<Session_shared::List> SharedList;
37
38             typedef std::map<Session_shared::InitKey,SharedList> InitListMap;
39             InitListMap m_init_list_map;
40
41             typedef std::map<Session,SharedList> SessionListMap;
42             SessionListMap m_session_list_map;
43
44         };
45         class Session_shared::InitKey {
46             friend class Session_shared;
47             friend class Session_shared::Rep;
48             std::string m_vhost;
49             std::string m_open;
50             std::string m_user;
51             std::string m_group;
52             std::string m_password;
53         public:
54             bool operator < (const Session_shared::InitKey &k) const;
55         };
56         class Session_shared::List {
57         public:
58             yazpp_1::GDU m_init_response;  // init response for backend 
59             Session m_session;             // session for backend
60         };
61     }
62     
63 }
64
65
66 using namespace yp2;
67
68 bool yf::Session_shared::InitKey::operator < (const Session_shared::InitKey &k) const {
69     if (m_vhost < k.m_vhost)
70         return true;
71     else if (m_vhost < k.m_vhost)
72         return false;
73
74     if (m_open < k.m_open)
75         return true;
76     else if (m_open > k.m_open)
77         return false;
78
79     if (m_user < k.m_user)
80         return true;
81     else if (m_user > k.m_user)
82         return false;
83  
84     if (m_group < k.m_group)
85         return true;
86     else if (m_group > k.m_group)
87         return false;
88
89     if (m_password < k.m_password)
90         return true;
91     else if (m_password > k.m_password)
92         return false;
93     return false;
94 }
95
96 yf::Session_shared::Session_shared() : m_p(new Rep)
97 {
98 }
99
100 yf::Session_shared::~Session_shared()
101 {
102 }
103
104 void yf::Session_shared::Rep::handle_search(Z_SearchRequest *req,
105                                             Package &package)
106 {
107     yaz_log(YLOG_LOG, "Got search");
108
109     SessionListMap::iterator it = m_session_list_map.find(package.session());
110     if (it == m_session_list_map.end())
111     {
112         yp2::odr odr;
113         package.response() = odr.create_close(
114                 Z_Close_protocolError,
115                 "no session for search request in session_shared");
116         package.session().close();
117         
118         return;
119     }
120     Package search_package(it->second->m_session, package.origin());
121     search_package.copy_filter(package);
122     search_package.request() = package.request();
123     
124     search_package.move();
125         
126     // transfer to frontend
127     package.response() = search_package.response();
128 }
129
130 void yf::Session_shared::Rep::handle_init(Z_InitRequest *req, Package &package)
131 {
132     yaz_log(YLOG_LOG, "Got init");
133
134     Session_shared::InitKey key;
135     const char *vhost =
136         yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
137     if (vhost)
138         key.m_vhost = vhost;
139
140     if (!req->idAuthentication)
141     {
142         yaz_log(YLOG_LOG, "No authentication");
143     }
144     else
145     {
146         Z_IdAuthentication *auth = req->idAuthentication;
147         switch(auth->which)
148         {
149         case Z_IdAuthentication_open:
150             yaz_log(YLOG_LOG, "open auth open=%s", auth->u.open);
151             key.m_open = auth->u.open;
152             break;
153         case Z_IdAuthentication_idPass:
154             yaz_log(YLOG_LOG, "idPass user=%s group=%s pass=%s",
155                     auth->u.idPass->userId, auth->u.idPass->groupId,
156                     auth->u.idPass->password);
157             if (auth->u.idPass->userId)
158                 key.m_user = auth->u.idPass->userId;
159             if (auth->u.idPass->groupId)
160                 key.m_group  = auth->u.idPass->groupId;
161             if (auth->u.idPass->password)
162                 key.m_password  = auth->u.idPass->password;
163             break;
164         case Z_IdAuthentication_anonymous:
165             yaz_log(YLOG_LOG, "anonymous");
166             break;
167         default:
168             yaz_log(YLOG_LOG, "other");
169         } 
170     }
171     InitListMap::iterator it = m_init_list_map.find(key);
172     if (it == m_init_list_map.end())
173     {
174         yaz_log(YLOG_LOG, "New KEY");
175
176         // building new package with original init and new session 
177         SharedList l(new Session_shared::List);  // new session for backend
178
179         Package init_package(l->m_session, package.origin());
180         init_package.copy_filter(package);
181         init_package.request() = package.request();
182
183         init_package.move();
184         
185         // transfer to frontend
186         package.response() = init_package.response();
187          
188         // check that we really got Z39.50 Init Response
189         Z_GDU *gdu = init_package.response().get();
190         if (gdu && gdu->which == Z_GDU_Z3950
191            && gdu->u.z3950->which == Z_APDU_initResponse)
192         {
193             // save the init response
194             l->m_init_response = init_package.response();
195             
196             // save session and init response for later
197             m_init_list_map[key] = l;
198
199             m_session_list_map[package.session()] = l;
200         }
201     }
202     else
203     {
204         yaz_log(YLOG_LOG, "Existing KEY");
205         package.response() = it->second->m_init_response;
206
207         m_session_list_map[package.session()] = it->second;
208     }
209 }
210
211 void yf::Session_shared::process(Package &package) const
212 {
213     // don't tell the backend if the "fronent" filter closes..
214     // we want to keep them alive
215     if (package.session().is_closed())
216     {
217         m_p->m_session_list_map.erase(package.session());
218         return;
219     }
220
221     Z_GDU *gdu = package.request().get();
222
223     if (gdu && gdu->which == Z_GDU_Z3950)
224     {
225         Z_APDU *apdu = gdu->u.z3950;
226
227         switch(apdu->which)
228         {
229         case Z_APDU_initRequest:
230             m_p->handle_init(apdu->u.initRequest, package);
231             break;
232         case Z_APDU_searchRequest:
233             m_p->handle_search(apdu->u.searchRequest, package);
234             break;
235         default:
236             yp2::odr odr;
237             package.response() = odr.create_close(
238                 Z_Close_protocolError,
239                 "cannot handle a package of this type");
240             package.session().close();
241             break;
242             
243         }
244         if (package.session().is_closed()) {
245             m_p->m_session_list_map.erase(package.session());
246         }
247     }
248     else
249         package.move();  // Not Z39.50 or not Init
250 }
251
252
253 /*
254  * Local variables:
255  * c-basic-offset: 4
256  * indent-tabs-mode: nil
257  * c-file-style: "stroustrup"
258  * End:
259  * vim: shiftwidth=4 tabstop=8 expandtab
260  */