1 /* This file is part of the yazpp toolkit.
2 * Copyright (C) Index Data
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);
210 if (id_from && *id_from)
211 *id_to = odr_create_Odr_oct(m_p->odr_out, (*id_from)->buf,
218 int Z_Assoc::send_Z_PDU(Z_APDU *apdu, int *plen)
220 Z_GDU *gdu = (Z_GDU*) odr_malloc(odr_encode(), sizeof(*gdu));
221 gdu->which = Z_GDU_Z3950;
223 return send_GDU(gdu, plen);
226 int Z_Assoc::send_GDU(Z_GDU *apdu, int *plen)
230 if (encode_GDU(apdu, &buf, &len) > 0)
234 return m_p->PDU_Observable->send_PDU(buf, len);
239 Z_GDU *Z_Assoc::decode_GDU(const char *buf, int len)
243 odr_reset(m_p->odr_in);
244 odr_setbuf(m_p->odr_in, (char*) buf, len, 0);
246 if (!z_GDU(m_p->odr_in, &apdu, 0, 0))
248 const char *element = odr_getelement(m_p->odr_in);
249 yaz_log(YLOG_LOG, "PDU decode failed '%s' near byte %ld. Element %s",
250 odr_errmsg(odr_geterror(m_p->odr_in)),
251 (long) odr_offset(m_p->odr_in),
252 element && *element ? element : "unknown");
253 yaz_log(YLOG_LOG, "Buffer length: %d", (int) len);
256 WRBUF w = wrbuf_alloc();
257 wrbuf_write_escaped(w, buf, len > 1024 ? 1024 : len);
258 yaz_log(YLOG_LOG, "Buffer bytes: %s", wrbuf_cstr(w));
261 yaz_log(YLOG_LOG, "PDU dump:");
262 odr_dumpBER(yaz_log_file(), buf, len);
267 if (m_p->APDU_yazlog)
268 { // use YAZ log FILE
269 FILE *save = m_p->APDU_file;
271 odr_setprint(m_p->odr_print, yaz_log_file());
272 z_GDU(m_p->odr_print, &apdu, 0, "decode");
273 m_p->APDU_file = save;
274 odr_setprint(m_p->odr_print, save);
278 z_GDU(m_p->odr_print, &apdu, 0, "decode");
279 fflush(m_p->APDU_file);
285 int Z_Assoc::encode_GDU(Z_GDU *apdu, char **buf, int *len)
287 const char *element = 0;
288 int r = z_GDU(m_p->odr_out, &apdu, 0, 0);
290 if (!r) // decoding failed. Get the failed element
291 element = odr_getelement(m_p->odr_out);
293 if (m_p->APDU_yazlog || !r)
296 yaz_log(YLOG_LOG, "PDU encode failed. Element %s",
297 element ? element : "unknown");
298 FILE *save = m_p->APDU_file;
299 FILE *yazf = yaz_log_file();
300 odr_setprint(m_p->odr_print, yazf); // use YAZ log FILE
301 z_GDU(m_p->odr_print, &apdu, 0, "encode");
302 m_p->APDU_file = save;
303 odr_setprint(m_p->odr_print, save);
308 fprintf(m_p->APDU_file, "PDU encode failed. Element %s",
309 element ? element : "unknown");
310 z_GDU(m_p->odr_print, &apdu, 0, "encode");
311 fflush(m_p->APDU_file);
313 if (!r) // encoding failed
315 *buf = odr_getbuf(m_p->odr_out, len, 0);
316 odr_reset(m_p->odr_out);
320 const char *Z_Assoc::get_hostname()
322 return m_p->hostname;
325 int Z_Assoc::client(const char *addr)
327 delete [] m_p->hostname;
328 m_p->hostname = new char[strlen(addr)+1];
329 strcpy(m_p->hostname, addr);
330 return m_p->PDU_Observable->connect(this, addr);
333 void Z_Assoc::close()
335 m_p->PDU_Observable->close_session();
338 int Z_Assoc::server(const char *addr)
340 delete [] m_p->hostname;
341 m_p->hostname = new char[strlen(addr)+1];
342 strcpy(m_p->hostname, addr);
343 return m_p->PDU_Observable->listen(this, addr);
346 ODR Z_Assoc::odr_encode()
351 ODR Z_Assoc::odr_decode()
355 ODR Z_Assoc::odr_print()
357 return m_p->odr_print;
360 void Z_Assoc::timeout(int timeout)
362 m_p->PDU_Observable->idleTime(timeout);
365 void Z_Assoc::get_otherInfoAPDU(Z_APDU *apdu, Z_OtherInformation ***oip)
369 case Z_APDU_initRequest:
370 *oip = &apdu->u.initRequest->otherInfo;
372 case Z_APDU_searchRequest:
373 *oip = &apdu->u.searchRequest->otherInfo;
375 case Z_APDU_presentRequest:
376 *oip = &apdu->u.presentRequest->otherInfo;
378 case Z_APDU_sortRequest:
379 *oip = &apdu->u.sortRequest->otherInfo;
381 case Z_APDU_scanRequest:
382 *oip = &apdu->u.scanRequest->otherInfo;
384 case Z_APDU_extendedServicesRequest:
385 *oip = &apdu->u.extendedServicesRequest->otherInfo;
387 case Z_APDU_deleteResultSetRequest:
388 *oip = &apdu->u.deleteResultSetRequest->otherInfo;
390 case Z_APDU_initResponse:
391 *oip = &apdu->u.initResponse->otherInfo;
393 case Z_APDU_searchResponse:
394 *oip = &apdu->u.searchResponse->otherInfo;
396 case Z_APDU_presentResponse:
397 *oip = &apdu->u.presentResponse->otherInfo;
399 case Z_APDU_sortResponse:
400 *oip = &apdu->u.sortResponse->otherInfo;
402 case Z_APDU_scanResponse:
403 *oip = &apdu->u.scanResponse->otherInfo;
405 case Z_APDU_extendedServicesResponse:
406 *oip = &apdu->u.extendedServicesResponse->otherInfo;
408 case Z_APDU_deleteResultSetResponse:
409 *oip = &apdu->u.deleteResultSetResponse->otherInfo;
417 void Z_Assoc::set_otherInformationString(
419 const Odr_oid *oid, int categoryValue, const char *str)
421 Z_OtherInformation **otherInformation;
422 get_otherInfoAPDU(apdu, &otherInformation);
423 if (!otherInformation)
425 set_otherInformationString(otherInformation, oid, categoryValue, str);
429 void Z_Assoc::set_otherInformationString (
430 Z_OtherInformation **otherInformation,
431 const Odr_oid *oid, int categoryValue, const char *str)
433 Z_OtherInformationUnit *oi =
434 update_otherInformation(otherInformation, 1, oid, categoryValue, 0);
437 oi->information.characterInfo = odr_strdup(odr_encode(), str);
440 Z_OtherInformationUnit *Z_Assoc::update_otherInformation (
441 Z_OtherInformation **otherInformationP, int createFlag,
442 const Odr_oid *oid, int categoryValue, int deleteFlag)
444 return yaz_oi_update(otherInformationP,
445 (createFlag ? odr_encode() : 0),
446 oid, categoryValue, deleteFlag);
449 Z_ReferenceId* Z_Assoc::getRefID(char* str)
451 Z_ReferenceId* id = NULL;
454 id = odr_create_Odr_oct(m_p->odr_out,
455 #if YAZ_VERSIONL < 0x50000
465 * c-file-style: "Stroustrup"
466 * indent-tabs-mode: nil
468 * vim: shiftwidth=4 tabstop=8 expandtab