0ec90bd1e354e2b259682ea438117891988940bf
[yazpp-moved-to-github.git] / src / yaz-my-server.cpp
1 /*
2  * Copyright (c) 1998-2001, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Log: yaz-my-server.cpp,v $
6  * Revision 1.7  2001-08-13 16:39:12  adam
7  * PDU_Assoc keeps track of children. Using yaz_log instead of logf.
8  *
9  * Revision 1.6  2001/05/17 14:18:03  adam
10  * New handler for old version item update for server:
11  *  void update_service0 (Z_ExtendedServicesRequest *req,
12  *                        Z_IU0Update *io, Z_ExtendedServicesResponse *res)
13  *
14  * Revision 1.5  2001/05/03 12:39:39  adam
15  * Added Update server service.
16  *
17  * Revision 1.4  2001/04/05 13:09:44  adam
18  * Removed ursula dependancy.
19  *
20  * Revision 1.3  2001/04/04 14:02:49  adam
21  * URSULA / Z-ruth service.
22  *
23  * Revision 1.2  2001/03/29 15:14:26  adam
24  * Minor updates.
25  *
26  * Revision 1.1  2001/03/27 14:47:45  adam
27  * New server facility scheme.
28  *
29  * Revision 1.15  2001/03/26 14:43:49  adam
30  * New threaded PDU association.
31  *
32  * Revision 1.14  2000/11/01 14:22:59  adam
33  * Added fd parameter for method IYaz_PDU_Observer::clone.
34  *
35  * Revision 1.13  2000/10/11 11:58:16  adam
36  * Moved header files to include/yaz++. Switched to libtool and automake.
37  * Configure script creates yaz++-config script.
38  *
39  * Revision 1.12  2000/09/21 21:43:20  adam
40  * Better high-level server API.
41  *
42  * Revision 1.11  2000/09/12 16:23:49  adam
43  * Updated server example.
44  *
45  * Revision 1.10  2000/09/12 16:04:17  adam
46  * Added comstack method for Yaz_PDU_Assoc..
47  *
48  * Revision 1.9  2000/09/12 12:09:53  adam
49  * More work on high-level server.
50  *
51  * Revision 1.8  2000/09/08 10:23:42  adam
52  * Added skeleton of yaz-z-server.
53  *
54  * Revision 1.7  1999/12/06 13:52:45  adam
55  * Modified for new location of YAZ header files. Experimental threaded
56  * operation.
57  *
58  * Revision 1.6  1999/04/21 12:09:01  adam
59  * Many improvements. Modified to proxy server to work with "sessions"
60  * based on cookies.
61  *
62  * Revision 1.5  1999/04/09 11:46:57  adam
63  * Added object Yaz_Z_Assoc. Much more functional client.
64  *
65  * Revision 1.4  1999/03/23 14:17:57  adam
66  * More work on timeout handling. Work on yaz-client.
67  *
68  * Revision 1.3  1999/02/02 14:01:22  adam
69  * First WIN32 port of YAZ++.
70  *
71  * Revision 1.2  1999/01/28 13:08:47  adam
72  * Yaz_PDU_Assoc better encapsulated. Memory leak fix in
73  * yaz-socket-manager.cc.
74  *
75  * Revision 1.1.1.1  1999/01/28 09:41:07  adam
76  * First implementation of YAZ++.
77  *
78  */
79
80 #include <yaz/log.h>
81 #include <yaz/options.h>
82 #include <yaz++/yaz-z-server.h>
83 #include <yaz++/yaz-pdu-assoc.h>
84 #include <yaz++/yaz-socket-manager.h>
85
86 class MyILL : public Yaz_Facility_ILL {
87 public:
88     void ill_service (Z_ExtendedServicesRequest *req,
89                       Z_ItemOrder *io,
90                       Z_ExtendedServicesResponse *res);
91 };
92
93 class MyUpdate : public Yaz_Facility_Update {
94 public:
95     void update_service (Z_ExtendedServicesRequest *req,
96                          Z_IUUpdate *io,
97                          Z_ExtendedServicesResponse *res);
98     void update_service0 (Z_ExtendedServicesRequest *req,
99                          Z_IU0Update *io,
100                          Z_ExtendedServicesResponse *res);
101 };
102
103
104 class MyRetrieval : public Yaz_Facility_Retrieval, Yaz_USMARC {
105 public:
106     int sr_init (Z_InitRequest *initRequest,
107                  Z_InitResponse *initResponse);
108     void sr_search (Z_SearchRequest *searchRequest,
109                         Z_SearchResponse *searchResponse);
110     void sr_present (Z_PresentRequest *presentRequest,
111                          Z_PresentResponse *presentResponse);
112     void sr_record (const char *resultSetName,
113                     int position,
114                     int *format,
115                     Z_RecordComposition *comp,
116                     Z_NamePlusRecord *namePlusRecord,
117                     Z_Records *records);
118 };
119
120 #if HAVE_YAZ_URSULA_H
121 class MyUrsula : public Yaz_Facility_Ursula {
122 public:
123     void ursula_service (Z_ExtendedServicesRequest *req,
124                          Z_UrsPDU *u,
125                          Z_ExtendedServicesResponse *res);
126 };
127 #endif
128
129 class MyServer : public Yaz_Z_Server {
130 public:
131     ~MyServer();
132     MyServer(IYaz_PDU_Observable *the_PDU_Observable);
133     IYaz_PDU_Observer* sessionNotify(IYaz_PDU_Observable *the_PDU_Observable,
134                                      int fd);
135     void failNotify();
136     void timeoutNotify();
137     void connectNotify();
138
139 private:
140     MyRetrieval m_retrieval;
141     MyILL       m_ill;
142     MyUpdate    m_update;
143 #if HAVE_YAZ_URSULA_H
144     MyUrsula    m_ursula;
145 #endif
146     int m_no;
147 };
148
149 void MyILL::ill_service (Z_ExtendedServicesRequest *req,
150                          Z_ItemOrder *io,
151                          Z_ExtendedServicesResponse *res)
152 {
153     yaz_log (LOG_LOG, "MyServer::ill_service");
154 }
155
156 void MyUpdate::update_service (Z_ExtendedServicesRequest *req,
157                            Z_IUUpdate *io,
158                            Z_ExtendedServicesResponse *res)
159 {
160     yaz_log (LOG_LOG, "MyServer::update_service (v1.1)");
161 }
162
163 void MyUpdate::update_service0 (Z_ExtendedServicesRequest *req,
164                            Z_IU0Update *io,
165                                 Z_ExtendedServicesResponse *res)
166 {
167     yaz_log (LOG_LOG, "MyServer::update_service (v1.0)");
168 }
169
170 #if HAVE_YAZ_URSULA_H
171 void MyUrsula::ursula_service (Z_ExtendedServicesRequest *req,
172                                Z_UrsPDU *u,
173                                Z_ExtendedServicesResponse *res)
174 {
175     yaz_log (LOG_LOG, "MyServer::ursula_service");
176     switch (u->which)
177     {
178     case  Z_UrsPDU_request:
179         yaz_log(LOG_LOG, "request");
180         if (u->u.request->libraryNo)
181             yaz_log (LOG_LOG, "libraryNo: %s", u->u.request->libraryNo);
182         break;
183     case  Z_UrsPDU_update:
184         yaz_log(LOG_LOG, "request");
185         break;
186     case  Z_UrsPDU_reservation:
187         yaz_log(LOG_LOG, "request");
188         break;
189     case  Z_UrsPDU_renewal:
190         yaz_log(LOG_LOG, "request");
191         break;
192     default:
193         yaz_log(LOG_LOG, "unknown");
194         break;
195     }
196 }
197 #endif
198
199 int MyRetrieval::sr_init (Z_InitRequest *initRequest,
200                        Z_InitResponse *initResponse)
201 {
202     yaz_log (LOG_LOG, "MyServer::sr_init");
203     return 1;
204 }
205
206 void MyRetrieval::sr_search (Z_SearchRequest *searchRequest,
207                              Z_SearchResponse *searchResponse)
208 {
209     yaz_log (LOG_LOG, "MyServer::recv_Z_search");
210     if (searchRequest->query->which == Z_Query_type_1)
211     {
212         Z_RPNStructure *s = searchRequest->query->u.type_1->RPNStructure;
213         if (s->which == Z_RPNStructure_simple &&
214             s->u.simple->which == Z_Operand_APT &&
215             s->u.simple->u.attributesPlusTerm->term->which == Z_Term_general)
216         {
217             Odr_oct *term = s->u.simple->u.attributesPlusTerm->term->u.general;
218             char *str = (char *) odr_malloc (odr_encode(), term->len+1);
219             if (term->len)
220                 memcpy (str, term->buf, term->len);
221             str[term->len] = '\0';
222             *searchResponse->resultCount = atoi(str);
223         }
224     }
225 }
226
227 void MyRetrieval::sr_present (Z_PresentRequest *presentRequest,
228                                Z_PresentResponse *presentResponse)
229 {
230     yaz_log (LOG_LOG, "MyServer::recv_Z_present");
231 }
232
233 void MyRetrieval::sr_record (const char *resultSetName,
234                              int position,
235                              int *format,
236                              Z_RecordComposition *comp,
237                              Z_NamePlusRecord *namePlusRecord,
238                              Z_Records *records)
239 {
240     yaz_log (LOG_LOG, "MyServer::recv_Z_record");
241     const char *rec = get_record(position);
242     create_databaseRecord (odr_encode(), namePlusRecord, 0, VAL_USMARC, rec,
243                            strlen(rec));
244 }
245
246 MyServer::~MyServer()
247 {
248 }
249
250 IYaz_PDU_Observer *MyServer::sessionNotify(
251     IYaz_PDU_Observable *the_PDU_Observable, int fd)
252 {
253     MyServer *new_server;
254     m_no++;
255     new_server = new MyServer(the_PDU_Observable);
256     new_server->timeout(900);
257     new_server->facility_add(&new_server->m_retrieval, "my sr");
258     new_server->facility_add(&new_server->m_ill, "my ill");
259     new_server->facility_add(&new_server->m_update, "my update");
260 #if HAVE_YAZ_URSULA_H
261     new_server->facility_add(&new_server->m_ursula, "my ursula");
262 #endif
263
264     new_server->set_APDU_log(get_APDU_log());
265
266     return new_server;
267 }
268
269 MyServer::MyServer(IYaz_PDU_Observable *the_PDU_Observable) :
270     Yaz_Z_Server (the_PDU_Observable)
271 {
272     m_no = 0;
273 }
274
275 void MyServer::timeoutNotify()
276 {
277     yaz_log (LOG_LOG, "connection timed out");
278     delete this;
279 }
280
281 void MyServer::failNotify()
282 {
283     yaz_log (LOG_LOG, "connection closed by client");
284     delete this;
285 }
286
287 void MyServer::connectNotify()
288 {
289 }
290
291 void usage(char *prog)
292 {
293     fprintf (stderr, "%s: [-a log] [-v level] [-T] @:port\n", prog);
294     exit (1);
295 }
296
297 int main(int argc, char **argv)
298 {
299     int thread_flag = 0;
300     char *arg;
301     char *prog = *argv;
302     char *addr = "tcp:@:9999";
303     char *apdu_log = 0;
304     
305     Yaz_SocketManager mySocketManager;
306     
307     Yaz_PDU_Assoc *my_PDU_Assoc = 0;
308     
309     MyServer *z = 0;
310     int ret;
311     
312     while ((ret = options("a:v:T", argv, argc, &arg)) != -2)
313     {
314         switch (ret)
315         {
316         case 0:
317             addr = xstrdup(arg);
318             break;
319         case 'a':
320             apdu_log = xstrdup(arg);
321             break;
322         case 'v':
323             yaz_log_init_level (yaz_log_mask_str(arg));
324             break;
325         case 'T':
326             thread_flag = 1;
327             break;
328         default:
329             usage(prog);
330             return 1;
331         }
332     }
333     if (thread_flag)
334         my_PDU_Assoc = new Yaz_PDU_AssocThread(&mySocketManager);
335     else
336         my_PDU_Assoc = new Yaz_PDU_Assoc(&mySocketManager);
337     
338     z = new MyServer(my_PDU_Assoc);
339     z->server(addr);
340     if (apdu_log)
341     {
342         yaz_log (LOG_LOG, "set_APDU_log %s", apdu_log);
343         z->set_APDU_log(apdu_log);
344     }
345
346     while (mySocketManager.processEvent() > 0)
347         ;
348     delete z;
349     return 0;
350 }