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