Modified for new location of YAZ header files. Experimental threaded
[yazpp-moved-to-github.git] / src / yaz-ir-assoc.cpp
1 /*
2  * Copyright (c) 1998-1999, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  * 
6  * $Log: yaz-ir-assoc.cpp,v $
7  * Revision 1.11  1999-12-06 13:52:45  adam
8  * Modified for new location of YAZ header files. Experimental threaded
9  * operation.
10  *
11  * Revision 1.10  1999/04/29 07:33:28  adam
12  * Changed setting of host in connect/proxy setting. YAZ' strtoaddr now
13  * ignores database part of host.
14  *
15  * Revision 1.9  1999/04/28 13:29:14  adam
16  * Yet another fix regarding database settings.
17  *
18  * Revision 1.8  1999/04/28 13:04:03  adam
19  * Fixed setting of proxy otherInfo so that database(s) are removed.
20  *
21  * Revision 1.7  1999/04/21 12:09:01  adam
22  * Many improvements. Modified to proxy server to work with "sessions"
23  * based on cookies.
24  *
25  * Revision 1.6  1999/04/20 10:30:05  adam
26  * Implemented various stuff for client and proxy. Updated calls
27  * to ODR to reflect new name parameter.
28  *
29  * Revision 1.5  1999/04/09 11:46:57  adam
30  * Added object Yaz_Z_Assoc. Much more functional client.
31  */
32
33 #include <assert.h>
34
35 #include <yaz/log.h>
36 #include <yaz-ir-assoc.h>
37
38 Yaz_IR_Assoc::Yaz_IR_Assoc(IYaz_PDU_Observable *the_PDU_Observable)
39     : Yaz_Z_Assoc(the_PDU_Observable)
40 {
41     m_num_databaseNames = 0;
42     m_databaseNames = 0;
43     m_preferredRecordSyntax = VAL_NONE;
44     m_elementSetNames = 0;
45     m_lastReceived = 0;
46     m_host = 0;
47     m_proxy = 0;
48     m_cookie = 0;
49     m_log = LOG_DEBUG;
50     const char *db = "Default";
51     set_databaseNames(1, &db);
52 }
53
54 Yaz_IR_Assoc::~Yaz_IR_Assoc()
55 {
56     if (m_elementSetNames)
57         delete [] m_elementSetNames->u.generic;
58     delete [] m_elementSetNames;
59     delete [] m_host;
60     delete [] m_proxy;
61     delete [] m_cookie;
62 }
63
64 void Yaz_IR_Assoc::get_databaseNames (int *num, char ***list)
65 {
66     *num = m_num_databaseNames;
67     *list = m_databaseNames;
68 }
69
70 void Yaz_IR_Assoc::set_databaseNames (int num, const char **list)
71 {
72     int i;
73     logf (m_log, "Yaz_IR_Assoc::set_databaseNames num=%d", num);
74     for (i = 0; i<m_num_databaseNames; i++)
75         delete [] m_databaseNames[i];
76     delete [] m_databaseNames;
77     m_num_databaseNames = num;
78     m_databaseNames = new (char*) [num];
79     for (i = 0; i<m_num_databaseNames; i++)
80     {
81         m_databaseNames[i] = new char[strlen(list[i])+1];
82         strcpy(m_databaseNames[i], list[i]);
83     }
84 }
85
86 void Yaz_IR_Assoc::set_databaseNames(const char *dblist, const char *sep)
87 {
88     const char **list = new (const char*) [strlen(dblist)];
89     char *dbtmp = new char[strlen(dblist)+1];
90     strcpy(dbtmp, dblist);
91     int num = 0;
92     int len = 0;
93     for (char *cp = dbtmp; ; cp++)
94         if (*cp && !strchr(sep, *cp))
95             len++;
96         else
97         {
98             if (len)
99             {
100                 list[num] = cp - len;
101                 num++;
102             }
103             if (!*cp)
104                 break;
105             *cp = '\0';
106             len = 0;
107         }
108     set_databaseNames (num, list);
109     delete [] dbtmp;
110     delete [] list;
111 }
112
113 void Yaz_IR_Assoc::set_preferredRecordSyntax (int value)
114 {
115     m_preferredRecordSyntax = value;
116 }
117
118 void Yaz_IR_Assoc::set_preferredRecordSyntax (const char *syntax)
119 {
120     m_preferredRecordSyntax = VAL_NONE;
121     if (syntax && *syntax)
122         m_preferredRecordSyntax = oid_getvalbyname (syntax);
123 }
124
125 void Yaz_IR_Assoc::get_preferredRecordSyntax (int *value)
126 {
127     *value = m_preferredRecordSyntax;
128 }
129
130 void Yaz_IR_Assoc::get_preferredRecordSyntax (const char **dst)
131 {
132     struct oident ent;
133     ent.proto = PROTO_Z3950;
134     ent.oclass = CLASS_RECSYN;
135     ent.value = (enum oid_value) m_preferredRecordSyntax;
136
137     int oid[OID_SIZE];
138     oid_ent_to_oid (&ent, oid);
139     struct oident *entp = oid_getentbyoid (oid);
140     
141     *dst = entp ? entp->desc : "";
142 }
143
144 void Yaz_IR_Assoc::set_elementSetName (const char *elementSetName)
145 {
146     if (m_elementSetNames)
147         delete [] m_elementSetNames->u.generic;
148     delete m_elementSetNames;
149     m_elementSetNames = 0;
150     if (elementSetName && *elementSetName)
151     {
152         m_elementSetNames = new Z_ElementSetNames;
153         m_elementSetNames->which = Z_ElementSetNames_generic;
154         m_elementSetNames->u.generic = new char[strlen(elementSetName)+1];
155         strcpy (m_elementSetNames->u.generic, elementSetName);
156     }
157 }
158
159 void Yaz_IR_Assoc::get_elementSetName (Z_ElementSetNames **elementSetNames)
160 {
161     *elementSetNames = m_elementSetNames;
162 }
163
164 void Yaz_IR_Assoc::get_elementSetName (const char **elementSetName)
165 {
166     if (!m_elementSetNames ||
167         m_elementSetNames->which != Z_ElementSetNames_generic)
168     {
169         *elementSetName = 0;
170         return;
171     }
172     *elementSetName = m_elementSetNames->u.generic;
173 }
174
175 void Yaz_IR_Assoc::recv_Z_PDU(Z_APDU *apdu)
176 {
177     logf (m_log, "recv_Z_PDU");
178     m_lastReceived = apdu->which;
179     switch (apdu->which)
180     {
181     case Z_APDU_initResponse:
182         logf (m_log, "recv InitResponse");
183         recv_initResponse(apdu->u.initResponse);
184         break;
185     case Z_APDU_initRequest:
186         logf (m_log, "recv InitRequest");
187         recv_initRequest(apdu->u.initRequest);
188         break;
189     case Z_APDU_searchRequest:
190         logf (m_log, "recv searchRequest");
191         recv_searchRequest(apdu->u.searchRequest);
192         break;
193     case Z_APDU_searchResponse:
194         logf (m_log, "recv searchResponse"); 
195         recv_searchResponse(apdu->u.searchResponse);
196         break;
197     case Z_APDU_presentRequest:
198         logf (m_log, "recv presentRequest");
199         recv_presentRequest(apdu->u.presentRequest);
200         break;
201     case Z_APDU_presentResponse:
202         logf (m_log, "recv presentResponse");
203         recv_presentResponse(apdu->u.presentResponse);
204         break;
205     }
206 }
207
208 int Yaz_IR_Assoc::send_searchRequest(Yaz_Z_Query *query)
209 {
210     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchRequest);
211     Z_SearchRequest *req = apdu->u.searchRequest;
212     int recordSyntax;
213
214     req->query = query->get_Z_Query();
215     if (!req->query)
216         return -1;
217     get_databaseNames (&req->num_databaseNames, &req->databaseNames);
218     int oid_syntax[OID_SIZE];
219     oident prefsyn;
220     get_preferredRecordSyntax(&recordSyntax);
221     if (recordSyntax != VAL_NONE)
222     {
223         prefsyn.proto = PROTO_Z3950;
224         prefsyn.oclass = CLASS_RECSYN;
225         prefsyn.value = (enum oid_value) recordSyntax;
226         oid_ent_to_oid(&prefsyn, oid_syntax);
227         req->preferredRecordSyntax = oid_syntax;
228     }
229     logf (m_log, "send_searchRequest");
230     assert (req->otherInfo == 0);
231     if (m_cookie)
232     {
233         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
234         assert (req->otherInfo);
235     }
236     return send_Z_PDU(apdu);
237 }
238
239 int Yaz_IR_Assoc::send_presentRequest(int start, int number)
240 {
241     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentRequest);
242     Z_PresentRequest *req = apdu->u.presentRequest;
243
244     req->resultSetStartPoint = &start;
245     req->numberOfRecordsRequested = &number;
246
247     int oid_syntax[OID_SIZE];
248     oident prefsyn;
249     int recordSyntax;
250     get_preferredRecordSyntax (&recordSyntax);
251     if (recordSyntax != VAL_NONE)
252     {
253         prefsyn.proto = PROTO_Z3950;
254         prefsyn.oclass = CLASS_RECSYN;
255         prefsyn.value = (enum oid_value) recordSyntax;
256         oid_ent_to_oid(&prefsyn, oid_syntax);
257         req->preferredRecordSyntax = oid_syntax;
258     }
259     Z_RecordComposition compo;
260     Z_ElementSetNames *elementSetNames;
261     get_elementSetName (&elementSetNames);
262     if (elementSetNames)
263     {
264         req->recordComposition = &compo;
265         compo.which = Z_RecordComp_simple;
266         compo.u.simple = elementSetNames;
267     }
268     if (m_cookie)
269         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
270     return send_Z_PDU(apdu);
271 }
272
273 void Yaz_IR_Assoc::set_proxy(const char *str)
274 {
275     delete [] m_proxy;
276     m_proxy = 0;
277     if (str)
278     {
279         m_proxy = new char[strlen(str)+1];
280         strcpy (m_proxy, str);
281     }
282 }
283
284 void Yaz_IR_Assoc::set_cookie(const char *str)
285 {
286     delete [] m_cookie;
287     m_cookie = 0;
288     if (str)
289     {
290         m_cookie = new char[strlen(str)+1];
291         strcpy(m_cookie, str);
292     }
293 }
294
295 const char *Yaz_IR_Assoc::get_cookie()
296 {
297     return m_cookie;
298 }
299
300 void Yaz_IR_Assoc::client(const char *addr)
301 {
302     delete [] m_host;
303     m_host = new char[strlen(addr)+1];
304     strcpy(m_host, addr);
305     const char *dbpart = strchr(m_host, '/');
306     if (dbpart)
307         set_databaseNames (dbpart+1, "+ ");
308     Yaz_Z_Assoc::client(m_proxy ? m_proxy : m_host);
309 }
310
311 const char *Yaz_IR_Assoc::get_proxy()
312 {
313     return m_proxy;
314 }
315
316 const char *Yaz_IR_Assoc::get_host()
317 {
318     return m_host;
319 }
320
321 void Yaz_IR_Assoc::recv_searchRequest(Z_SearchRequest *searchRequest)
322 {
323     Z_APDU *apdu = create_Z_PDU(Z_APDU_searchResponse);
324     send_Z_PDU(apdu);
325 }
326
327 void Yaz_IR_Assoc::recv_presentRequest(Z_PresentRequest *presentRequest)
328 {
329     Z_APDU *apdu = create_Z_PDU(Z_APDU_presentResponse);
330     send_Z_PDU(apdu);
331 }
332
333 void Yaz_IR_Assoc::recv_initRequest(Z_InitRequest *initRequest)
334 {
335     Z_APDU *apdu = create_Z_PDU(Z_APDU_initResponse);
336     send_Z_PDU(apdu);
337 }
338
339 void Yaz_IR_Assoc::recv_searchResponse (Z_SearchResponse *searchResponse)
340 {
341 }
342
343 void Yaz_IR_Assoc::recv_presentResponse (Z_PresentResponse *presentResponse)
344 {
345 }
346
347 void Yaz_IR_Assoc::recv_initResponse(Z_InitResponse *initResponse)
348 {
349 }
350
351 int Yaz_IR_Assoc::get_lastReceived()
352 {
353     return m_lastReceived;
354 }
355
356 void Yaz_IR_Assoc::set_lastReceived(int lastReceived)
357 {
358     m_lastReceived = lastReceived;
359 }
360
361 int Yaz_IR_Assoc::send_initRequest()
362 {
363     Z_APDU *apdu = create_Z_PDU(Z_APDU_initRequest);
364     Z_InitRequest *req = apdu->u.initRequest;
365     
366     ODR_MASK_SET(req->options, Z_Options_search);
367     ODR_MASK_SET(req->options, Z_Options_present);
368     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
369     ODR_MASK_SET(req->options, Z_Options_triggerResourceCtrl);
370     ODR_MASK_SET(req->options, Z_Options_scan);
371     ODR_MASK_SET(req->options, Z_Options_sort);
372     ODR_MASK_SET(req->options, Z_Options_extendedServices);
373     ODR_MASK_SET(req->options, Z_Options_delSet);
374
375     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1);
376     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2);
377     ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
378
379     if (m_proxy && m_host)
380         set_otherInformationString(&req->otherInfo, VAL_PROXY, 1, m_host);
381     if (m_cookie)
382         set_otherInformationString(&req->otherInfo, VAL_COOKIE, 1, m_cookie);
383     return send_Z_PDU(apdu);
384 }
385