Many improvements. Modified to proxy server to work with "sessions"
[yazpp-moved-to-github.git] / src / yaz-z-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-z-assoc.cpp,v $
7  * Revision 1.3  1999-04-21 12:09:01  adam
8  * Many improvements. Modified to proxy server to work with "sessions"
9  * based on cookies.
10  *
11  * Revision 1.2  1999/04/20 10:30:05  adam
12  * Implemented various stuff for client and proxy. Updated calls
13  * to ODR to reflect new name parameter.
14  *
15  * Revision 1.1  1999/04/09 11:46:57  adam
16  * Added object Yaz_Z_Assoc. Much more functional client.
17  *
18  */
19
20 #include <assert.h>
21
22 #include <log.h>
23 #include <yaz-z-assoc.h>
24
25 int Yaz_Z_Assoc::yaz_init_func()
26 {
27     logf (LOG_LOG, "nmem_init");
28     nmem_init();
29     logf (LOG_LOG, "done");
30     return 1;
31 }
32
33 int Yaz_Z_Assoc::yaz_init_flag = Yaz_Z_Assoc::yaz_init_func();
34
35 Yaz_Z_Assoc::Yaz_Z_Assoc(IYaz_PDU_Observable *the_PDU_Observable)
36 {
37     m_PDU_Observable = the_PDU_Observable;
38     m_odr_in = odr_createmem (ODR_DECODE);
39     m_odr_out = odr_createmem (ODR_ENCODE);
40     m_odr_print = odr_createmem (ODR_PRINT);
41 }
42
43 Yaz_Z_Assoc::~Yaz_Z_Assoc()
44 {
45     m_PDU_Observable->destroy();
46     delete m_PDU_Observable;
47     odr_destroy (m_odr_print);
48     odr_destroy (m_odr_out);
49     odr_destroy (m_odr_in);
50 }
51
52 void Yaz_Z_Assoc::recv_PDU(const char *buf, int len)
53 {
54     logf (LOG_LOG, "recv_PDU len=%d", len);
55     Z_APDU *apdu = decode_Z_PDU (buf, len);
56     if (apdu)
57     {
58         recv_Z_PDU (apdu);
59     }
60 }
61
62 Z_APDU *Yaz_Z_Assoc::create_Z_PDU(int type)
63 {
64     Z_APDU *apdu = zget_APDU(m_odr_out, type);
65     if (apdu->which == Z_APDU_initRequest)
66     {
67         Z_InitRequest * p = apdu->u.initRequest;
68         char *newName = (char*) odr_malloc(m_odr_out, 50);
69         strcpy (newName, p->implementationName);
70         strcat (newName, " YAZ++");
71         p->implementationName = newName;
72     }
73     return apdu;
74 }
75
76 int Yaz_Z_Assoc::send_Z_PDU(Z_APDU *apdu)
77 {
78     char *buf;
79     int len;
80     logf (LOG_LOG, "Yaz_Z_Assoc:send_Z_PDU");
81     if (encode_Z_PDU(apdu, &buf, &len) > 0)
82         return m_PDU_Observable->send_PDU(buf, len);
83     return -1;
84 }
85
86 Z_APDU *Yaz_Z_Assoc::decode_Z_PDU(const char *buf, int len)
87 {
88     Z_APDU *apdu;
89
90     odr_reset (m_odr_in);
91     odr_setbuf (m_odr_in, (char*) buf, len, 0);
92
93     if (!z_APDU(m_odr_in, &apdu, 0, 0))
94     {
95         logf(LOG_LOG, "ODR error on incoming PDU: %s [near byte %d] ",
96              odr_errmsg(odr_geterror(m_odr_in)),
97              odr_offset(m_odr_in));
98         logf(LOG_LOG, "PDU dump:");
99         odr_dumpBER(log_file(), buf, len);
100         return 0;
101     }
102     else
103     {
104         z_APDU(m_odr_print, &apdu, 0, "decode");
105         return apdu;
106     }
107 }
108
109 int Yaz_Z_Assoc::encode_Z_PDU(Z_APDU *apdu, char **buf, int *len)
110 {
111     if (!z_APDU(m_odr_out, &apdu, 0, 0))
112     {
113         logf (LOG_LOG, "yaz_Z_Assoc::encode_Z_PDU failed");
114         return -1;
115     }
116     z_APDU(m_odr_print, &apdu, 0, "encode");
117     *buf = odr_getbuf (m_odr_out, len, 0);
118     odr_reset (m_odr_out);
119     return *len;
120 }
121
122 void Yaz_Z_Assoc::connectNotify()
123 {
124     logf (LOG_LOG, "connectNotify");
125 }
126
127 void Yaz_Z_Assoc::failNotify()
128 {
129     logf (LOG_LOG, "failNotify");
130 }
131
132 void Yaz_Z_Assoc::timeoutNotify()
133 {
134     logf (LOG_LOG, "timeoutNotify");
135 }
136
137 void Yaz_Z_Assoc::client(const char *addr)
138 {
139     m_PDU_Observable->connect (this, addr);
140 }
141
142 void Yaz_Z_Assoc::close()
143 {
144     m_PDU_Observable->close ();
145 }
146
147 void Yaz_Z_Assoc::server(const char *addr)
148 {
149     m_PDU_Observable->listen (this, addr);
150 }
151
152 ODR Yaz_Z_Assoc::odr_encode()
153 {
154     return m_odr_out;
155 }
156
157 ODR Yaz_Z_Assoc::odr_decode()
158 {
159     return m_odr_in;
160 }
161 ODR Yaz_Z_Assoc::odr_print()
162 {
163     return m_odr_print;
164 }
165
166 void Yaz_Z_Assoc::timeout(int timeout)
167 {
168     m_PDU_Observable->idleTime(timeout);
169 }
170
171 void Yaz_Z_Assoc::get_otherInfoAPDU(Z_APDU *apdu, Z_OtherInformation ***oip)
172 {
173     switch (apdu->which)
174     {
175     case Z_APDU_initRequest:
176         *oip = &apdu->u.initRequest->otherInfo;
177         break;
178     case Z_APDU_searchRequest:
179         *oip = &apdu->u.searchRequest->otherInfo;
180         break;
181     case Z_APDU_presentRequest:
182         *oip = &apdu->u.presentRequest->otherInfo;
183         break;
184     case Z_APDU_sortRequest:
185         *oip = &apdu->u.sortRequest->otherInfo;
186         break;
187     case Z_APDU_scanRequest:
188         *oip = &apdu->u.scanRequest->otherInfo;
189         break;
190     case Z_APDU_initResponse:
191         *oip = &apdu->u.initResponse->otherInfo;
192         break;
193     case Z_APDU_searchResponse:
194         *oip = &apdu->u.searchResponse->otherInfo;
195         break;
196     case Z_APDU_presentResponse:
197         *oip = &apdu->u.presentResponse->otherInfo;
198         break;
199     case Z_APDU_sortResponse:
200         *oip = &apdu->u.sortResponse->otherInfo;
201         break;
202     case Z_APDU_scanResponse:
203         *oip = &apdu->u.scanResponse->otherInfo;
204         break;
205     default:
206         *oip = 0;
207         break;
208     }
209 }
210
211 void Yaz_Z_Assoc::set_otherInformationString (
212     Z_APDU *apdu,
213     int oidval, int categoryValue,
214     const char *str)
215 {
216     Z_OtherInformation **otherInformation;
217     get_otherInfoAPDU(apdu, &otherInformation);
218     if (!otherInformation)
219         return;
220     set_otherInformationString(otherInformation, oidval, categoryValue, str);
221 }
222
223 void Yaz_Z_Assoc::set_otherInformationString (
224     Z_OtherInformation **otherInformation,
225     int oidval, int categoryValue,
226     const char *str)
227 {
228     int oid[OID_SIZE];
229     struct oident ent;
230     ent.proto = PROTO_Z3950;
231     ent.oclass = CLASS_USERINFO;
232     ent.value = (oid_value) oidval;
233     if (!oid_ent_to_oid (&ent, oid))
234         return ;
235     set_otherInformationString(otherInformation, oid, categoryValue, str);
236 }
237
238 void Yaz_Z_Assoc::set_otherInformationString (
239     Z_OtherInformation **otherInformation,
240     int *oid, int categoryValue,
241     const char *str)
242 {
243     Z_OtherInformationUnit *oi =
244         update_otherInformation(otherInformation, 1, oid, categoryValue);
245     if (!oi)
246         return;
247     oi->information.characterInfo = odr_strdup (odr_encode(), str);
248 }
249
250 Z_OtherInformationUnit *Yaz_Z_Assoc::update_otherInformation (
251     Z_OtherInformation **otherInformationP, int createFlag,
252     int *oid, int categoryValue)
253 {
254     int i;
255     Z_OtherInformation *otherInformation = *otherInformationP;
256     if (!otherInformation)
257     {
258         if (!createFlag)
259             return 0;
260         otherInformation = *otherInformationP = (Z_OtherInformation *)
261             odr_malloc (odr_encode(), sizeof(*otherInformation));
262         otherInformation->num_elements = 0;
263         otherInformation->list = (Z_OtherInformationUnit **)
264             odr_malloc (odr_encode(), 8*sizeof(*otherInformation));
265         for (i = 0; i<8; i++)
266             otherInformation->list[i] = 0;
267     }
268     logf (LOG_LOG, "Yaz_Z_Assoc::update_otherInformation num=%d",
269           otherInformation->num_elements);
270     for (i = 0; i<otherInformation->num_elements; i++)
271     {
272         assert (otherInformation->list[i]);
273         if (!oid)
274         {
275             if (!otherInformation->list[i]->category)
276                 return otherInformation->list[i];
277         }
278         else
279         {
280             if (otherInformation->list[i]->category &&
281                 categoryValue ==
282                 *otherInformation->list[i]->category->categoryValue &&
283                 !oid_oidcmp (oid, otherInformation->list[i]->category->
284                              categoryTypeId))
285                 return otherInformation->list[i];
286         }
287     }
288     if (!createFlag)
289         return 0;
290     otherInformation->list[i] = (Z_OtherInformationUnit*)
291         odr_malloc (odr_encode(), sizeof(Z_OtherInformationUnit));
292     if (oid)
293     {
294         otherInformation->list[i]->category = (Z_InfoCategory*)
295             odr_malloc (odr_encode(), sizeof(Z_InfoCategory));
296         otherInformation->list[i]->category->categoryTypeId = (int*)
297             odr_oiddup (odr_encode(), oid);
298         otherInformation->list[i]->category->categoryValue = (int*)
299             odr_malloc (odr_encode(), sizeof(int));
300         *otherInformation->list[i]->category->categoryValue =
301             categoryValue;
302     }
303     else
304         otherInformation->list[i]->category = 0;
305     otherInformation->list[i]->which = Z_OtherInfo_characterInfo;
306     otherInformation->list[i]->information.characterInfo = 0;
307     
308     otherInformation->num_elements = i+1;
309     return otherInformation->list[i];
310 }
311