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