1 /* This file is part of the yazpp toolkit.
2 * Copyright (C) 1998-2012 Index Data and Mike Taylor
3 * See the file LICENSE for details.
13 #include <yazpp/z-assoc.h>
14 #include <yaz/otherinfo.h>
15 #include <yaz/oid_db.h>
23 Z_Assoc_priv(IPDU_Observable *the_PDU_Observable);
25 static int yaz_init_flag;
26 static int yaz_init_func();
27 IPDU_Observable *PDU_Observable;
39 using namespace yazpp_1;
41 int Z_Assoc_priv::yaz_init_func()
44 signal(SIGPIPE, SIG_IGN);
49 int Z_Assoc_priv::yaz_init_flag = Z_Assoc_priv::yaz_init_func();
51 Z_Assoc_priv::Z_Assoc_priv(IPDU_Observable *the_PDU_Observable)
53 PDU_Observable = the_PDU_Observable;
54 odr_in = odr_createmem(ODR_DECODE);
55 odr_out = odr_createmem(ODR_ENCODE);
56 odr_print = odr_createmem(ODR_PRINT);
64 Z_Assoc_priv::~Z_Assoc_priv()
66 PDU_Observable->destroy();
67 delete PDU_Observable;
68 odr_destroy(odr_print); // note: also runs fclose on APDU_file ..
75 Z_Assoc::Z_Assoc(IPDU_Observable *the_PDU_Observable)
77 m_p = new Z_Assoc_priv(the_PDU_Observable);
85 void Z_Assoc::set_APDU_log(const char *fname)
87 if (m_p->APDU_file && m_p->APDU_file != stderr)
89 fclose(m_p->APDU_file);
92 delete [] m_p->APDU_fname;
97 m_p->APDU_fname = new char[strlen(fname)+1];
98 strcpy(m_p->APDU_fname, fname);
99 if (!strcmp(fname, "-"))
100 m_p->APDU_file = stderr;
101 else if (*fname == '\0')
104 m_p->APDU_file = fopen(fname, "a");
105 odr_setprint(m_p->odr_print, m_p->APDU_file);
109 int Z_Assoc::set_APDU_yazlog(int v)
111 int old = m_p->APDU_yazlog;
112 m_p->APDU_yazlog = v;
116 const char *Z_Assoc::get_APDU_log()
118 return m_p->APDU_fname;
121 void Z_Assoc::recv_PDU(const char *buf, int len)
123 yaz_log(m_p->log, "recv_PDU len=%d", len);
124 Z_GDU *apdu = decode_GDU(buf, len);
131 m_p->PDU_Observable->shutdown();
136 Z_APDU *Z_Assoc::create_Z_PDU(int type)
138 Z_APDU *apdu = zget_APDU(m_p->odr_out, type);
139 if (apdu->which == Z_APDU_initRequest)
141 Z_InitRequest * p = apdu->u.initRequest;
142 char *newName = (char*) odr_malloc(m_p->odr_out, 50);
143 strcpy(newName, p->implementationName);
144 strcat(newName, " YAZ++");
145 p->implementationName = newName;
150 Z_ReferenceId **Z_Assoc::get_referenceIdP(Z_APDU *apdu)
154 case Z_APDU_initRequest:
155 return &apdu->u.initRequest->referenceId;
156 case Z_APDU_initResponse:
157 return &apdu->u.initResponse->referenceId;
158 case Z_APDU_searchRequest:
159 return &apdu->u.searchRequest->referenceId;
160 case Z_APDU_searchResponse:
161 return &apdu->u.searchResponse->referenceId;
162 case Z_APDU_presentRequest:
163 return &apdu->u.presentRequest->referenceId;
164 case Z_APDU_presentResponse:
165 return &apdu->u.presentResponse->referenceId;
166 case Z_APDU_deleteResultSetRequest:
167 return &apdu->u.deleteResultSetRequest->referenceId;
168 case Z_APDU_deleteResultSetResponse:
169 return &apdu->u.deleteResultSetResponse->referenceId;
170 case Z_APDU_accessControlRequest:
171 return &apdu->u.accessControlRequest->referenceId;
172 case Z_APDU_accessControlResponse:
173 return &apdu->u.accessControlResponse->referenceId;
174 case Z_APDU_resourceControlRequest:
175 return &apdu->u.resourceControlRequest->referenceId;
176 case Z_APDU_resourceControlResponse:
177 return &apdu->u.resourceControlResponse->referenceId;
178 case Z_APDU_triggerResourceControlRequest:
179 return &apdu->u.triggerResourceControlRequest->referenceId;
180 case Z_APDU_resourceReportRequest:
181 return &apdu->u.resourceReportRequest->referenceId;
182 case Z_APDU_resourceReportResponse:
183 return &apdu->u.resourceReportResponse->referenceId;
184 case Z_APDU_scanRequest:
185 return &apdu->u.scanRequest->referenceId;
186 case Z_APDU_scanResponse:
187 return &apdu->u.scanResponse->referenceId;
188 case Z_APDU_sortRequest:
189 return &apdu->u.sortRequest->referenceId;
190 case Z_APDU_sortResponse:
191 return &apdu->u.sortResponse->referenceId;
192 case Z_APDU_segmentRequest:
193 return &apdu->u.segmentRequest->referenceId;
194 case Z_APDU_extendedServicesRequest:
195 return &apdu->u.extendedServicesRequest->referenceId;
196 case Z_APDU_extendedServicesResponse:
197 return &apdu->u.extendedServicesResponse->referenceId;
199 return &apdu->u.close->referenceId;
204 void Z_Assoc::transfer_referenceId(Z_APDU *from, Z_APDU *to)
206 Z_ReferenceId **id_from = get_referenceIdP(from);
207 Z_ReferenceId **id_to = get_referenceIdP(to);
208 if (id_from && *id_from && id_to)
210 *id_to = (Z_ReferenceId*) odr_malloc(m_p->odr_out, sizeof(**id_to));
211 (*id_to)->size = (*id_to)->len = (*id_from)->len;
212 (*id_to)->buf = (unsigned char*)
213 odr_malloc(m_p->odr_out, (*id_to)->len);
214 memcpy((*id_to)->buf, (*id_from)->buf, (*id_to)->len);
220 int Z_Assoc::send_Z_PDU(Z_APDU *apdu, int *plen)
222 Z_GDU *gdu = (Z_GDU*) odr_malloc(odr_encode(), sizeof(*gdu));
223 gdu->which = Z_GDU_Z3950;
225 return send_GDU(gdu, plen);
228 int Z_Assoc::send_GDU(Z_GDU *apdu, int *plen)
232 if (encode_GDU(apdu, &buf, &len) > 0)
236 return m_p->PDU_Observable->send_PDU(buf, len);
241 Z_GDU *Z_Assoc::decode_GDU(const char *buf, int len)
245 odr_reset(m_p->odr_in);
246 odr_setbuf(m_p->odr_in, (char*) buf, len, 0);
248 if (!z_GDU(m_p->odr_in, &apdu, 0, 0))
250 const char *element = odr_getelement(m_p->odr_in);
251 yaz_log(YLOG_LOG, "PDU decode failed '%s' near byte %ld. Element %s",
252 odr_errmsg(odr_geterror(m_p->odr_in)),
253 (long) odr_offset(m_p->odr_in),
254 element && *element ? element : "unknown");
255 yaz_log(YLOG_LOG, "Buffer length: %d", (int) len);
258 WRBUF w = wrbuf_alloc();
259 wrbuf_write_escaped(w, buf, len > 1024 ? 1024 : len);
260 yaz_log(YLOG_LOG, "Buffer bytes: %s", wrbuf_cstr(w));
263 yaz_log(YLOG_LOG, "PDU dump:");
264 odr_dumpBER(yaz_log_file(), buf, len);
269 if (m_p->APDU_yazlog)
270 { // use YAZ log FILE
271 FILE *save = m_p->APDU_file;
273 odr_setprint(m_p->odr_print, yaz_log_file());
274 z_GDU(m_p->odr_print, &apdu, 0, "decode");
275 m_p->APDU_file = save;
276 odr_setprint(m_p->odr_print, save);
280 z_GDU(m_p->odr_print, &apdu, 0, "decode");
281 fflush(m_p->APDU_file);
287 int Z_Assoc::encode_GDU(Z_GDU *apdu, char **buf, int *len)
289 const char *element = 0;
290 int r = z_GDU(m_p->odr_out, &apdu, 0, 0);
292 if (!r) // decoding failed. Get the failed element
293 element = odr_getelement(m_p->odr_out);
295 if (m_p->APDU_yazlog || !r)
298 yaz_log(YLOG_LOG, "PDU encode failed. Element %s",
299 element ? element : "unknown");
300 FILE *save = m_p->APDU_file;
301 FILE *yazf = yaz_log_file();
302 odr_setprint(m_p->odr_print, yazf); // use YAZ log FILE
303 z_GDU(m_p->odr_print, &apdu, 0, "encode");
304 m_p->APDU_file = save;
305 odr_setprint(m_p->odr_print, save);
310 fprintf(m_p->APDU_file, "PDU encode failed. Element %s",
311 element ? element : "unknown");
312 z_GDU(m_p->odr_print, &apdu, 0, "encode");
313 fflush(m_p->APDU_file);
315 if (!r) // encoding failed
317 *buf = odr_getbuf(m_p->odr_out, len, 0);
318 odr_reset(m_p->odr_out);
322 const char *Z_Assoc::get_hostname()
324 return m_p->hostname;
327 int Z_Assoc::client(const char *addr)
329 delete [] m_p->hostname;
330 m_p->hostname = new char[strlen(addr)+1];
331 strcpy(m_p->hostname, addr);
332 return m_p->PDU_Observable->connect(this, addr);
335 void Z_Assoc::close()
337 m_p->PDU_Observable->close_session();
340 int Z_Assoc::server(const char *addr)
342 delete [] m_p->hostname;
343 m_p->hostname = new char[strlen(addr)+1];
344 strcpy(m_p->hostname, addr);
345 return m_p->PDU_Observable->listen(this, addr);
348 ODR Z_Assoc::odr_encode()
353 ODR Z_Assoc::odr_decode()
357 ODR Z_Assoc::odr_print()
359 return m_p->odr_print;
362 void Z_Assoc::timeout(int timeout)
364 m_p->PDU_Observable->idleTime(timeout);
367 void Z_Assoc::get_otherInfoAPDU(Z_APDU *apdu, Z_OtherInformation ***oip)
371 case Z_APDU_initRequest:
372 *oip = &apdu->u.initRequest->otherInfo;
374 case Z_APDU_searchRequest:
375 *oip = &apdu->u.searchRequest->otherInfo;
377 case Z_APDU_presentRequest:
378 *oip = &apdu->u.presentRequest->otherInfo;
380 case Z_APDU_sortRequest:
381 *oip = &apdu->u.sortRequest->otherInfo;
383 case Z_APDU_scanRequest:
384 *oip = &apdu->u.scanRequest->otherInfo;
386 case Z_APDU_extendedServicesRequest:
387 *oip = &apdu->u.extendedServicesRequest->otherInfo;
389 case Z_APDU_deleteResultSetRequest:
390 *oip = &apdu->u.deleteResultSetRequest->otherInfo;
392 case Z_APDU_initResponse:
393 *oip = &apdu->u.initResponse->otherInfo;
395 case Z_APDU_searchResponse:
396 *oip = &apdu->u.searchResponse->otherInfo;
398 case Z_APDU_presentResponse:
399 *oip = &apdu->u.presentResponse->otherInfo;
401 case Z_APDU_sortResponse:
402 *oip = &apdu->u.sortResponse->otherInfo;
404 case Z_APDU_scanResponse:
405 *oip = &apdu->u.scanResponse->otherInfo;
407 case Z_APDU_extendedServicesResponse:
408 *oip = &apdu->u.extendedServicesResponse->otherInfo;
410 case Z_APDU_deleteResultSetResponse:
411 *oip = &apdu->u.deleteResultSetResponse->otherInfo;
419 void Z_Assoc::set_otherInformationString(
421 const Odr_oid *oid, int categoryValue, const char *str)
423 Z_OtherInformation **otherInformation;
424 get_otherInfoAPDU(apdu, &otherInformation);
425 if (!otherInformation)
427 set_otherInformationString(otherInformation, oid, categoryValue, str);
431 void Z_Assoc::set_otherInformationString (
432 Z_OtherInformation **otherInformation,
433 const Odr_oid *oid, int categoryValue, const char *str)
435 Z_OtherInformationUnit *oi =
436 update_otherInformation(otherInformation, 1, oid, categoryValue, 0);
439 oi->information.characterInfo = odr_strdup(odr_encode(), str);
442 Z_OtherInformationUnit *Z_Assoc::update_otherInformation (
443 Z_OtherInformation **otherInformationP, int createFlag,
444 const Odr_oid *oid, int categoryValue, int deleteFlag)
446 return yaz_oi_update(otherInformationP,
447 (createFlag ? odr_encode() : 0),
448 oid, categoryValue, deleteFlag);
451 Z_ReferenceId* Z_Assoc::getRefID(char* str)
453 Z_ReferenceId* id = NULL;
457 id = (Z_ReferenceId*) odr_malloc(m_p->odr_out, sizeof(*id));
458 id->size = id->len = strlen(str);
459 id->buf = (unsigned char *) str;
467 * c-file-style: "Stroustrup"
468 * indent-tabs-mode: nil
470 * vim: shiftwidth=4 tabstop=8 expandtab