PDU_Assoc keeps track of children. Using yaz_log instead of logf.
[yazpp-moved-to-github.git] / src / yaz-ir-assoc.cpp
1 /*
2  * Copyright (c) 1998-2000, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Log: yaz-ir-assoc.cpp,v $
6  * Revision 1.16  2001-08-13 16:39:12  adam
7  * PDU_Assoc keeps track of children. Using yaz_log instead of logf.
8  *
9  * Revision 1.15  2001/04/26 12:17:49  heikki
10  * Ursula stuff, mostly in the test client
11  *
12  * Revision 1.14  2000/10/11 11:58:16  adam
13  * Moved header files to include/yaz++. Switched to libtool and automake.
14  * Configure script creates yaz++-config script.
15  *
16  * Revision 1.13  2000/09/06 14:23:45  adam
17  * WIN32 updates.
18  *
19  * Revision 1.12  2000/05/10 11:36:58  ian
20  * Added default parameters for refid to request functions.
21  * Added default parameter for result set name to search and present request.
22  * Commented out forced logging of PDU contents.
23  * Added send_deleteResultSetRequest
24  *
25  * Revision 1.11  1999/12/06 13:52:45  adam
26  * Modified for new location of YAZ header files. Experimental threaded
27  * operation.
28  *
29  * Revision 1.10  1999/04/29 07:33:28  adam
30  * Changed setting of host in connect/proxy setting. YAZ' strtoaddr now
31  * ignores database part of host.
32  *
33  * Revision 1.9  1999/04/28 13:29:14  adam
34  * Yet another fix regarding database settings.
35  *
36  * Revision 1.8  1999/04/28 13:04:03  adam
37  * Fixed setting of proxy otherInfo so that database(s) are removed.
38  *
39  * Revision 1.7  1999/04/21 12:09:01  adam
40  * Many improvements. Modified to proxy server to work with "sessions"
41  * based on cookies.
42  *
43  * Revision 1.6  1999/04/20 10:30:05  adam
44  * Implemented various stuff for client and proxy. Updated calls
45  * to ODR to reflect new name parameter.
46  *
47  * Revision 1.5  1999/04/09 11:46:57  adam
48  * Added object Yaz_Z_Assoc. Much more functional client.
49  */
50
51 #include <assert.h>
52
53 #include <yaz/log.h>
54 #include <yaz++/yaz-ir-assoc.h>
55
56 Yaz_IR_Assoc::Yaz_IR_Assoc(IYaz_PDU_Observable *the_PDU_Observable)
57     : Yaz_Z_Assoc(the_PDU_Observable)
58 {
59     m_num_databaseNames = 0;
60     m_databaseNames = 0;
61     m_preferredRecordSyntax = VAL_NONE;
62     m_elementSetNames = 0;
63     m_lastReceived = 0;
64     m_host = 0;
65     m_proxy = 0;
66     m_cookie = 0;
67     m_log = LOG_DEBUG;
68     const char *db = "Default";
69     set_databaseNames(1, &db);
70 }
71
72 Yaz_IR_Assoc::~Yaz_IR_Assoc()
73 {
74     if (m_elementSetNames)
75         delete [] m_elementSetNames->u.generic;
76     delete [] m_elementSetNames;
77     delete [] m_host;
78     delete [] m_proxy;
79     delete [] m_cookie;
80 }
81
82 void Yaz_IR_Assoc::get_databaseNames (int *num, char ***list)
83 {
84     *num = m_num_databaseNames;
85     *list = m_databaseNames;
86 }
87
88 typedef char *charp;
89 void Yaz_IR_Assoc::set_databaseNames (int num, const char **list)
90 {
91     int i;
92     yaz_log (m_log, "Yaz_IR_Assoc::set_databaseNames num=%d", num);
93     for (i = 0; i<m_num_databaseNames; i++)
94         delete [] m_databaseNames[i];
95     delete [] m_databaseNames;
96     m_num_databaseNames = num;
97
98     m_databaseNames = new char *[num];
99     for (i = 0; i<m_num_databaseNames; i++)
100     {
101         m_databaseNames[i] = new char[strlen(list[i])+1];
102         strcpy(m_databaseNames[i], list[i]);
103     }
104 }
105
106 void Yaz_IR_Assoc::set_databaseNames(const char *dblist, const char *sep)
107 {
108     const char **list = new const char* [strlen(dblist)];
109     char *dbtmp = new char[strlen(dblist)+1];
110     strcpy(dbtmp, dblist);
111     int num = 0;
112     int len = 0;
113     for (char *cp = dbtmp; ; cp++)
114         if (*cp && !strchr(sep, *cp))
115             len++;
116         else
117         {
118             if (len)
119             {
120                 list[num] = cp - len;
121                 num++;
122             }
123             if (!*cp)
124                 break;
125             *cp = '\0';
126             len = 0;
127         }
128     set_databaseNames (num, list);
129     delete [] dbtmp;
130     delete [] list;
131 }
132
133 void Yaz_IR_Assoc::set_preferredRecordSyntax (int value)
134 {
135     m_preferredRecordSyntax = value;
136 }
137
138 void Yaz_IR_Assoc::set_preferredRecordSyntax (const char *syntax)
139 {
140     m_preferredRecordSyntax = VAL_NONE;
141     if (syntax && *syntax)
142         m_preferredRecordSyntax = oid_getvalbyname (syntax);
143 }
144
145 void Yaz_IR_Assoc::get_preferredRecordSyntax (int *value)
146 {
147     *value = m_preferredRecordSyntax;
148 }
149
150 void Yaz_IR_Assoc::get_preferredRecordSyntax (const char **dst)
151 {
152     struct oident ent;
153     ent.proto = PROTO_Z3950;
154     ent.oclass = CLASS_RECSYN;
155     ent.value = (enum oid_value) m_preferredRecordSyntax;
156
157     int oid[OID_SIZE];
158     oid_ent_to_oid (&ent, oid);
159     struct oident *entp = oid_getentbyoid (oid);
160     
161     *dst = entp ? entp->desc : "";
162 }
163
164 void Yaz_IR_Assoc::set_elementSetName (const char *elementSetName)
165 {
166     if (m_elementSetNames)
167         delete [] m_elementSetNames->u.generic;
168     delete m_elementSetNames;
169     m_elementSetNames = 0;
170     if (elementSetName && *elementSetName)
171     {
172         m_elementSetNames = new Z_ElementSetNames;
173         m_elementSetNames->which = Z_ElementSetNames_generic;
174         m_elementSetNames->u.generic = new char[strlen(elementSetName)+1];
175         strcpy (m_elementSetNames->u.generic, elementSetName);
176     }
177 }
178
179 void Yaz_IR_Assoc::get_elementSetName (Z_ElementSetNames **elementSetNames)
180 {
181     *elementSetNames = m_elementSetNames;
182 }
183
184 void Yaz_IR_Assoc::get_elementSetName (const char **elementSetName)
185 {
186     if (!m_elementSetNames ||
187         m_elementSetNames->which != Z_ElementSetNames_generic)
188     {
189         *elementSetName = 0;
190         return;
191     }
192     *elementSetName = m_elementSetNames->u.generic;
193 }
194
195 void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu)
196 {
197     yaz_log (m_log, "recv_Z_PDU");
198     m_lastReceived = apdu->which;
199     switch (apdu->which)
200     {
201     case Z_APDU_initResponse:
202         yaz_log (m_log, "recv InitResponse");
203         recv_initResponse(apdu->u.initResponse);
204         break;
205     case Z_APDU_initRequest:
206         yaz_log (m_log, "recv InitRequest");
207         recv_initRequest(apdu->u.initRequest);
208         break;
209     case Z_APDU_searchRequest:
210         yaz_log (m_log, "recv searchRequest");
211         recv_searchRequest(apdu->u.searchRequest);
212         break;
213     case Z_APDU_searchResponse:
214         yaz_log (m_log, "recv searchResponse"); 
215         recv_searchResponse(apdu->u.searchResponse);
216         break;
217     case Z_APDU_presentRequest:
218         yaz_log (m_log, "recv presentRequest");
219         recv_presentRequest(apdu->u.presentRequest);
220         break;
221     case Z_APDU_presentResponse:
222         yaz_log (m_log, "recv presentResponse");
223         recv_presentResponse(apdu->u.presentResponse);
224         break;
225     case Z_APDU_extendedServicesResponse:
226         yaz_log (m_log, "recv extendedServiceResponse");
227         recv_extendedServicesResponse(apdu->u.extendedServicesResponse);
228         break;
229     }
230 }
231
232 int Yaz_IR_Assoc::send_searchRequest(Yaz_Z_Query *query,
233                                      char* pResultSetId,
234                                      char* pRefId)
235 {
236     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchRequest);
237     Z_SearchRequest *req = apdu->u.searchRequest;
238     int recordSyntax;
239
240     req->query = query->get_Z_Query();
241     if (!req->query)
242         return -1;
243     get_databaseNames (&req->num_databaseNames, &req->databaseNames);
244     int oid_syntax[OID_SIZE];
245     oident prefsyn;
246     get_preferredRecordSyntax(&recordSyntax);
247     if (recordSyntax != VAL_NONE)
248     {
249         prefsyn.proto = PROTO_Z3950;
250         prefsyn.oclass = CLASS_RECSYN;
251         prefsyn.value = (enum oid_value) recordSyntax;
252         oid_ent_to_oid(&prefsyn, oid_syntax);
253         req->preferredRecordSyntax = oid_syntax;
254     }
255     yaz_log (m_log, "send_searchRequest");
256     assert (req->otherInfo == 0);
257     if (m_cookie)
258     {
259         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
260         assert (req->otherInfo);
261     }
262
263     if ( pRefId )
264     {
265         req->referenceId = getRefID(pRefId);
266     }
267
268     if ( pResultSetId )
269     {
270         req->resultSetName = pResultSetId;
271     }
272
273     return send_Z_PDU(apdu);
274 }
275
276 int Yaz_IR_Assoc::send_presentRequest(int start, 
277                                       int number, 
278                                       char* pResultSetId,
279                                       char* pRefId)
280 {
281     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentRequest);
282     Z_PresentRequest *req = apdu->u.presentRequest;
283
284     req->resultSetStartPoint = &start;
285     req->numberOfRecordsRequested = &number;
286
287     int oid_syntax[OID_SIZE];
288     oident prefsyn;
289     int recordSyntax;
290     get_preferredRecordSyntax (&recordSyntax);
291     if (recordSyntax != VAL_NONE)
292     {
293         prefsyn.proto = PROTO_Z3950;
294         prefsyn.oclass = CLASS_RECSYN;
295         prefsyn.value = (enum oid_value) recordSyntax;
296         oid_ent_to_oid(&prefsyn, oid_syntax);
297         req->preferredRecordSyntax = oid_syntax;
298     }
299     Z_RecordComposition compo;
300     Z_ElementSetNames *elementSetNames;
301     get_elementSetName (&elementSetNames);
302     if (elementSetNames)
303     {
304         req->recordComposition = &compo;
305         compo.which = Z_RecordComp_simple;
306         compo.u.simple = elementSetNames;
307     }
308
309     if (m_cookie)
310         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
311
312     if ( pRefId )
313     {
314         req->referenceId = getRefID(pRefId);
315     }
316
317     if ( pResultSetId )
318     {
319         req->resultSetId = pResultSetId;
320     }
321
322     return send_Z_PDU(apdu);
323 }
324
325 void Yaz_IR_Assoc::set_proxy(const char *str)
326 {
327     delete [] m_proxy;
328     m_proxy = 0;
329     if (str)
330     {
331         m_proxy = new char[strlen(str)+1];
332         strcpy (m_proxy, str);
333     }
334 }
335
336 void Yaz_IR_Assoc::set_cookie(const char *str)
337 {
338     delete [] m_cookie;
339     m_cookie = 0;
340     if (str)
341     {
342         m_cookie = new char[strlen(str)+1];
343         strcpy(m_cookie, str);
344     }
345 }
346
347 const char *Yaz_IR_Assoc::get_cookie()
348 {
349     return m_cookie;
350 }
351
352 void Yaz_IR_Assoc::client(const char *addr)
353 {
354     delete [] m_host;
355     m_host = new char[strlen(addr)+1];
356     strcpy(m_host, addr);
357     const char *dbpart = strchr(m_host, '/');
358     if (dbpart)
359         set_databaseNames (dbpart+1, "+ ");
360     Yaz_Z_Assoc::client(m_proxy ? m_proxy : m_host);
361 }
362
363 const char *Yaz_IR_Assoc::get_proxy()
364 {
365     return m_proxy;
366 }
367
368 const char *Yaz_IR_Assoc::get_host()
369 {
370     return m_host;
371 }
372
373 void Yaz_IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
374 {
375     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
376     send_Z_PDU(apdu);
377 }
378
379 void Yaz_IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
380 {
381     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
382     send_Z_PDU(apdu);
383 }
384
385 void Yaz_IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
386 {
387     Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
388     send_Z_PDU(apdu);
389 }
390
391 void Yaz_IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
392 {
393 }
394
395 void Yaz_IR_Assoc::recv_presentResponse (Z_PresentResponse *presentResponse)
396 {
397 }
398
399 void Yaz_IR_Assoc::recv_initResponse(Z_InitResponse *initResponse)
400 {
401 }
402
403 void Yaz_IR_Assoc::recv_extendedServicesResponse(Z_ExtendedServicesResponse *ExtendedServicesResponse)
404 {
405 }
406
407 int Yaz_IR_Assoc::get_lastReceived()
408 {
409     return m_lastReceived;
410 }
411
412 void Yaz_IR_Assoc::set_lastReceived(int lastReceived)
413 {
414     m_lastReceived = lastReceived;
415 }
416
417 int Yaz_IR_Assoc::send_initRequest(char* pRefId)
418 {
419     Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest);
420     Z_InitRequest *req = apdu->u.initRequest;
421     
422     ODR_MASK_SET(req->options, Z_Options_search);
423     ODR_MASK_SET(req->options, Z_Options_present);
424     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
425     ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
426     ODR_MASK_SET(req->options, Z_Options_scan);
427     ODR_MASK_SET(req->options, Z_Options_sort);
428     ODR_MASK_SET(req->options, Z_Options_extendedServices);
429     ODR_MASK_SET(req->options, Z_Options_delSet);
430
431     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
432     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
433     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
434
435     if ( pRefId )
436     {
437         req->referenceId = getRefID(pRefId);
438     }
439
440     if (m_proxy && m_host)
441         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
442     if (m_cookie)
443         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
444     return send_Z_PDU(apdu);
445 }
446
447 int Yaz_IR_Assoc::send_deleteResultSetRequest(char* pResultSetId, char* pRefId)
448 {
449     char* ResultSetIds[1];
450
451     Z_APDU *apdu = create_Z_PDU(Z_APDU_deleteResultSetRequest);
452     Z_DeleteResultSetRequest *req = apdu->u.deleteResultSetRequest;
453
454     if ( pResultSetId )
455     {
456         *req->deleteFunction = Z_DeleteResultSetRequest_list;
457         req->num_resultSetList = 1;
458         ResultSetIds[0] = pResultSetId;
459         req->resultSetList = ResultSetIds;
460     }
461     else
462     {
463         *req->deleteFunction = Z_DeleteResultSetRequest_all;
464     }
465     
466     if ( pRefId )
467     {
468         req->referenceId = getRefID(pRefId);
469     }
470
471     if (m_proxy && m_host)
472         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
473     if (m_cookie)
474         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
475
476
477     return send_Z_PDU(apdu);
478 }
479
480