2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: seshigh.c,v 1.25 2004-06-15 10:53:26 adam Exp $
9 * Frontend server logic.
11 * This code receives incoming APDUs, and handles client requests by means
14 * Some of the code is getting quite involved, compared to simpler servers -
15 * primarily because it is asynchronous both in the communication with
16 * the user and the backend. We think the complexity will pay off in
17 * the form of greater flexibility when more asynchronous facilities
20 * Memory management has become somewhat involved. In the simple case, where
21 * only one PDU is pending at a time, it will simply reuse the same memory,
22 * once it has found its working size. When we enable multiple concurrent
23 * operations, perhaps even with multiple parallel calls to the backend, it
24 * will maintain a pool of buffers for encoding and decoding, trying to
25 * minimize memory allocation/deallocation during normal operation.
31 #include <sys/types.h>
34 #define S_ISREG(x) (x & _S_IFREG)
44 #include <yaz/yconfig.h>
45 #include <yaz/xmalloc.h>
46 #include <yaz/comstack.h>
49 #include <yaz/proto.h>
52 #include <yaz/logrpn.h>
53 #include <yaz/statserv.h>
54 #include <yaz/diagbib1.h>
55 #include <yaz/charneg.h>
56 #include <yaz/otherinfo.h>
57 #include <yaz/yaz-util.h>
58 #include <yaz/pquery.h>
61 #include <yaz/backend.h>
63 static void process_gdu_request(association *assoc, request *req);
64 static int process_z_request(association *assoc, request *req, char **msg);
65 void backend_response(IOCHAN i, int event);
66 static int process_gdu_response(association *assoc, request *req, Z_GDU *res);
67 static int process_z_response(association *assoc, request *req, Z_APDU *res);
68 static Z_APDU *process_initRequest(association *assoc, request *reqb);
69 static Z_External *init_diagnostics(ODR odr, int errcode, char *errstring);
70 static Z_APDU *process_searchRequest(association *assoc, request *reqb,
72 static Z_APDU *response_searchRequest(association *assoc, request *reqb,
73 bend_search_rr *bsrr, int *fd);
74 static Z_APDU *process_presentRequest(association *assoc, request *reqb,
76 static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd);
77 static Z_APDU *process_sortRequest(association *assoc, request *reqb, int *fd);
78 static void process_close(association *assoc, request *reqb);
79 void save_referenceId (request *reqb, Z_ReferenceId *refid);
80 static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
82 static Z_APDU *process_segmentRequest (association *assoc, request *reqb);
84 static FILE *apduf = 0; /* for use in static mode */
85 static statserv_options_block *control_block = 0;
87 static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd);
90 * Create and initialize a new association-handle.
91 * channel : iochannel for the current line.
92 * link : communications channel.
93 * Returns: 0 or a new association handle.
95 association *create_association(IOCHAN channel, COMSTACK link)
100 control_block = statserv_getcontrol();
101 if (!(anew = (association *)xmalloc(sizeof(*anew))))
105 anew->client_chan = channel;
106 anew->client_link = link;
107 anew->cs_get_mask = 0;
108 anew->cs_put_mask = 0;
109 anew->cs_accept_mask = 0;
110 if (!(anew->decode = odr_createmem(ODR_DECODE)) ||
111 !(anew->encode = odr_createmem(ODR_ENCODE)))
113 if (*control_block->apdufile)
118 strcpy(filename, control_block->apdufile);
119 if (!(anew->print = odr_createmem(ODR_PRINT)))
121 if (*control_block->apdufile == '@')
123 odr_setprint(anew->print, yaz_log_file());
125 else if (*control_block->apdufile != '-')
127 strcpy(filename, control_block->apdufile);
128 if (!control_block->dynamic)
132 if (!(apduf = fopen(filename, "w")))
134 yaz_log(LOG_WARN|LOG_ERRNO, "%s", filename);
137 setvbuf(apduf, 0, _IONBF, 0);
143 sprintf(filename + strlen(filename), ".%d", getpid());
144 if (!(f = fopen(filename, "w")))
146 yaz_log(LOG_WARN|LOG_ERRNO, "%s", filename);
149 setvbuf(f, 0, _IONBF, 0);
151 odr_setprint(anew->print, f);
156 anew->input_buffer = 0;
157 anew->input_buffer_len = 0;
159 anew->state = ASSOC_NEW;
160 request_initq(&anew->incoming);
161 request_initq(&anew->outgoing);
162 anew->proto = cs_getproto(link);
167 * Free association and release resources.
169 void destroy_association(association *h)
171 statserv_options_block *cb = statserv_getcontrol();
175 odr_destroy(h->decode);
176 odr_destroy(h->encode);
178 odr_destroy(h->print);
180 xfree(h->input_buffer);
182 (*cb->bend_close)(h->backend);
183 while ((req = request_deq(&h->incoming)))
184 request_release(req);
185 while ((req = request_deq(&h->outgoing)))
186 request_release(req);
187 request_delq(&h->incoming);
188 request_delq(&h->outgoing);
190 xmalloc_trav("session closed");
191 if (control_block && control_block->one_shot)
197 static void do_close_req(association *a, int reason, char *message,
201 Z_Close *cls = zget_Close(a->encode);
203 /* Purge request queue */
204 while (request_deq(&a->incoming));
205 while (request_deq(&a->outgoing));
208 yaz_log(LOG_LOG, "Sending Close PDU, reason=%d, message=%s",
209 reason, message ? message : "none");
210 apdu.which = Z_APDU_close;
212 *cls->closeReason = reason;
213 cls->diagnosticInformation = message;
214 process_z_response(a, req, &apdu);
215 iochan_settimeout(a->client_chan, 20);
219 request_release(req);
220 yaz_log(LOG_DEBUG, "v2 client. No Close PDU");
221 iochan_setevent(a->client_chan, EVENT_TIMEOUT); /* force imm close */
223 a->state = ASSOC_DEAD;
226 static void do_close(association *a, int reason, char *message)
228 request *req = request_get(&a->outgoing);
229 do_close_req (a, reason, message, req);
233 * This is where PDUs from the client are read and the further
234 * processing is initiated. Flow of control moves down through the
235 * various process_* functions below, until the encoded result comes back up
236 * to the output handler in here.
238 * h : the I/O channel that has an outstanding event.
239 * event : the current outstanding event.
241 void ir_session(IOCHAN h, int event)
244 association *assoc = (association *)iochan_getdata(h);
245 COMSTACK conn = assoc->client_link;
248 assert(h && conn && assoc);
249 if (event == EVENT_TIMEOUT)
251 if (assoc->state != ASSOC_UP)
253 yaz_log(LOG_LOG, "Final timeout - closing connection.");
255 destroy_association(assoc);
260 yaz_log(LOG_LOG, "Session idle too long. Sending close.");
261 do_close(assoc, Z_Close_lackOfActivity, 0);
265 if (event & assoc->cs_accept_mask)
267 yaz_log (LOG_DEBUG, "ir_session (accept)");
268 if (!cs_accept (conn))
270 yaz_log (LOG_LOG, "accept failed");
271 destroy_association(assoc);
274 iochan_clearflag (h, EVENT_OUTPUT);
275 if (conn->io_pending)
276 { /* cs_accept didn't complete */
277 assoc->cs_accept_mask =
278 ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) |
279 ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0);
281 iochan_setflag (h, assoc->cs_accept_mask);
284 { /* cs_accept completed. Prepare for reading (cs_get) */
285 assoc->cs_accept_mask = 0;
286 assoc->cs_get_mask = EVENT_INPUT;
287 iochan_setflag (h, assoc->cs_get_mask);
291 if ((event & assoc->cs_get_mask) || (event & EVENT_WORK)) /* input */
293 if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask))
295 yaz_log(LOG_DEBUG, "ir_session (input)");
296 /* We aren't speaking to this fellow */
297 if (assoc->state == ASSOC_DEAD)
299 yaz_log(LOG_LOG, "Connection closed - end of session");
301 destroy_association(assoc);
305 assoc->cs_get_mask = EVENT_INPUT;
306 if ((res = cs_get(conn, &assoc->input_buffer,
307 &assoc->input_buffer_len)) <= 0)
309 yaz_log(LOG_LOG, "Connection closed by client");
311 destroy_association(assoc);
315 else if (res == 1) /* incomplete read - wait for more */
317 if (conn->io_pending & CS_WANT_WRITE)
318 assoc->cs_get_mask |= EVENT_OUTPUT;
319 iochan_setflag(h, assoc->cs_get_mask);
322 if (cs_more(conn)) /* more stuff - call us again later, please */
323 iochan_setevent(h, EVENT_INPUT);
325 /* we got a complete PDU. Let's decode it */
326 yaz_log(LOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res,
327 assoc->input_buffer[0] & 0xff,
328 assoc->input_buffer[1] & 0xff,
329 assoc->input_buffer[2] & 0xff);
330 req = request_get(&assoc->incoming); /* get a new request */
331 odr_reset(assoc->decode);
332 odr_setbuf(assoc->decode, assoc->input_buffer, res, 0);
333 if (!z_GDU(assoc->decode, &req->gdu_request, 0, 0))
335 yaz_log(LOG_LOG, "ODR error on incoming PDU: %s [element %s] "
337 odr_errmsg(odr_geterror(assoc->decode)),
338 odr_getelement(assoc->decode),
339 odr_offset(assoc->decode));
340 if (assoc->decode->error != OHTTP)
342 yaz_log(LOG_LOG, "PDU dump:");
343 odr_dumpBER(yaz_log_file(), assoc->input_buffer, res);
344 request_release(req);
345 do_close(assoc, Z_Close_protocolError,"Malformed package");
349 Z_GDU *p = z_get_HTTP_Response(assoc->encode, 400);
350 assoc->state = ASSOC_DEAD;
351 process_gdu_response(assoc, req, p);
355 req->request_mem = odr_extract_mem(assoc->decode);
358 if (!z_GDU(assoc->print, &req->gdu_request, 0, 0))
359 yaz_log(LOG_WARN, "ODR print error: %s",
360 odr_errmsg(odr_geterror(assoc->print)));
361 odr_reset(assoc->print);
363 request_enq(&assoc->incoming, req);
366 /* can we do something yet? */
367 req = request_head(&assoc->incoming);
368 if (req->state == REQUEST_IDLE)
370 request_deq(&assoc->incoming);
371 process_gdu_request(assoc, req);
374 if (event & assoc->cs_put_mask)
376 request *req = request_head(&assoc->outgoing);
378 assoc->cs_put_mask = 0;
379 yaz_log(LOG_DEBUG, "ir_session (output)");
380 req->state = REQUEST_PENDING;
381 switch (res = cs_put(conn, req->response, req->len_response))
384 yaz_log(LOG_LOG, "Connection closed by client");
386 destroy_association(assoc);
389 case 0: /* all sent - release the request structure */
390 yaz_log(LOG_DEBUG, "Wrote PDU, %d bytes", req->len_response);
392 yaz_log(LOG_DEBUG, "HTTP out:\n%.*s", req->len_response,
395 nmem_destroy(req->request_mem);
396 request_deq(&assoc->outgoing);
397 request_release(req);
398 if (!request_head(&assoc->outgoing))
399 { /* restore mask for cs_get operation ... */
400 iochan_clearflag(h, EVENT_OUTPUT|EVENT_INPUT);
401 iochan_setflag(h, assoc->cs_get_mask);
402 if (assoc->state == ASSOC_DEAD)
403 iochan_setevent(assoc->client_chan, EVENT_TIMEOUT);
407 assoc->cs_put_mask = EVENT_OUTPUT;
411 if (conn->io_pending & CS_WANT_WRITE)
412 assoc->cs_put_mask |= EVENT_OUTPUT;
413 if (conn->io_pending & CS_WANT_READ)
414 assoc->cs_put_mask |= EVENT_INPUT;
415 iochan_setflag(h, assoc->cs_put_mask);
418 if (event & EVENT_EXCEPT)
420 yaz_log(LOG_LOG, "ir_session (exception)");
422 destroy_association(assoc);
427 static int process_z_request(association *assoc, request *req, char **msg);
429 static void assoc_init_reset(association *assoc)
432 assoc->init = (bend_initrequest *) xmalloc (sizeof(*assoc->init));
434 assoc->init->stream = assoc->encode;
435 assoc->init->print = assoc->print;
436 assoc->init->auth = 0;
437 assoc->init->referenceId = 0;
438 assoc->init->implementation_version = 0;
439 assoc->init->implementation_id = 0;
440 assoc->init->implementation_name = 0;
441 assoc->init->bend_sort = NULL;
442 assoc->init->bend_search = NULL;
443 assoc->init->bend_present = NULL;
444 assoc->init->bend_esrequest = NULL;
445 assoc->init->bend_delete = NULL;
446 assoc->init->bend_scan = NULL;
447 assoc->init->bend_segment = NULL;
448 assoc->init->bend_fetch = NULL;
449 assoc->init->bend_explain = NULL;
451 assoc->init->charneg_request = NULL;
452 assoc->init->charneg_response = NULL;
454 assoc->init->decode = assoc->decode;
455 assoc->init->peer_name =
456 odr_strdup (assoc->encode, cs_addrstr(assoc->client_link));
459 static int srw_bend_init(association *assoc)
461 const char *encoding = "UTF-8";
463 bend_initresult *binitres;
464 statserv_options_block *cb = statserv_getcontrol();
466 assoc_init_reset(assoc);
468 assoc->maximumRecordSize = 3000000;
469 assoc->preferredMessageSize = 3000000;
471 ce = yaz_set_proposal_charneg(assoc->decode, &encoding, 1, 0, 0, 1);
472 assoc->init->charneg_request = ce->u.charNeg3;
475 if (!(binitres = (*cb->bend_init)(assoc->init)))
477 yaz_log(LOG_WARN, "Bad response from backend.");
480 assoc->backend = binitres->handle;
484 static int srw_bend_fetch(association *assoc, int pos,
485 Z_SRW_searchRetrieveRequest *srw_req,
486 Z_SRW_record *record)
489 ODR o = assoc->encode;
491 rr.setname = "default";
494 rr.request_format = VAL_TEXT_XML;
495 rr.request_format_raw = yaz_oidval_to_z3950oid(assoc->decode,
498 rr.comp = (Z_RecordComposition *)
499 odr_malloc(assoc->decode, sizeof(*rr.comp));
500 rr.comp->which = Z_RecordComp_complex;
501 rr.comp->u.complex = (Z_CompSpec *)
502 odr_malloc(assoc->decode, sizeof(Z_CompSpec));
503 rr.comp->u.complex->selectAlternativeSyntax = (bool_t *)
504 odr_malloc(assoc->encode, sizeof(bool_t));
505 *rr.comp->u.complex->selectAlternativeSyntax = 0;
506 rr.comp->u.complex->num_dbSpecific = 0;
507 rr.comp->u.complex->dbSpecific = 0;
508 rr.comp->u.complex->num_recordSyntax = 0;
509 rr.comp->u.complex->recordSyntax = 0;
511 rr.comp->u.complex->generic = (Z_Specification *)
512 odr_malloc(assoc->decode, sizeof(Z_Specification));
513 rr.comp->u.complex->generic->which = Z_Schema_uri;
514 rr.comp->u.complex->generic->schema.uri = srw_req->recordSchema;
515 rr.comp->u.complex->generic->elementSpec = 0;
517 rr.stream = assoc->encode;
518 rr.print = assoc->print;
524 rr.output_format = VAL_TEXT_XML;
525 rr.output_format_raw = 0;
528 rr.surrogate_flag = 0;
529 rr.schema = srw_req->recordSchema;
531 if (!assoc->init->bend_fetch)
534 (*assoc->init->bend_fetch)(assoc->backend, &rr);
538 record->recordData_buf = rr.record;
539 record->recordData_len = rr.len;
540 record->recordPosition = odr_intdup(o, pos);
542 record->recordSchema = odr_strdup(o, rr.schema);
544 record->recordSchema = 0;
549 static void srw_bend_search(association *assoc, request *req,
550 Z_SRW_searchRetrieveRequest *srw_req,
551 Z_SRW_searchRetrieveResponse *srw_res,
559 yaz_log(LOG_LOG, "Got SRW SearchRetrieveRequest");
560 yaz_log(LOG_DEBUG, "srw_bend_search");
563 yaz_log(LOG_DEBUG, "srw_bend_init");
564 if (!srw_bend_init(assoc))
566 srw_error = 3; /* assume Authentication error */
568 yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
569 &srw_res->num_diagnostics, 1, 0);
574 rr.setname = "default";
577 rr.basenames = &srw_req->database;
580 rr.query = (Z_Query *) odr_malloc (assoc->decode, sizeof(*rr.query));
582 if (srw_req->query_type == Z_SRW_query_type_cql)
584 ext = (Z_External *) odr_malloc(assoc->decode, sizeof(*ext));
585 ext->direct_reference = odr_getoidbystr(assoc->decode,
586 "1.2.840.10003.16.2");
587 ext->indirect_reference = 0;
589 ext->which = Z_External_CQL;
590 ext->u.cql = srw_req->query.cql;
592 rr.query->which = Z_Query_type_104;
593 rr.query->u.type_104 = ext;
595 else if (srw_req->query_type == Z_SRW_query_type_pqf)
597 Z_RPNQuery *RPNquery;
598 YAZ_PQF_Parser pqf_parser;
600 pqf_parser = yaz_pqf_create ();
602 RPNquery = yaz_pqf_parse (pqf_parser, assoc->decode,
608 int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off);
610 yaz_log(LOG_LOG, "%*s^\n", (int)off+4, "");
611 yaz_log(LOG_LOG, "Bad PQF: %s (code %d)\n", pqf_msg, code);
616 rr.query->which = Z_Query_type_1;
617 rr.query->u.type_1 = RPNquery;
619 yaz_pqf_destroy (pqf_parser);
624 if (!srw_error && srw_req->sort_type != Z_SRW_sort_type_none)
627 if (!srw_error && !assoc->init->bend_search)
632 yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %d", srw_error);
633 srw_res->num_diagnostics = 1;
634 srw_res->diagnostics = (Z_SRW_diagnostic *)
635 odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
636 yaz_mk_std_diagnostic(assoc->encode,
637 srw_res->diagnostics, srw_error, 0);
641 rr.stream = assoc->encode;
642 rr.decode = assoc->decode;
643 rr.print = assoc->print;
645 rr.association = assoc;
651 yaz_log_zquery(rr.query);
652 (assoc->init->bend_search)(assoc->backend, &rr);
653 srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits);
656 yaz_log(LOG_DEBUG, "bend_search returned Bib-1 code %d", rr.errcode);
657 if (rr.errcode == 109) /* database unavailable */
662 srw_res->num_diagnostics = 1;
663 srw_res->diagnostics = (Z_SRW_diagnostic *)
664 odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
665 yaz_mk_std_diagnostic(assoc->encode, srw_res->diagnostics,
666 yaz_diag_bib1_to_srw (rr.errcode),
668 yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %s",
669 srw_res->diagnostics[0].uri);
673 int number = srw_req->maximumRecords ? *srw_req->maximumRecords : 0;
674 int start = srw_req->startRecord ? *srw_req->startRecord : 1;
676 yaz_log(LOG_LOG, "Request to pack %d+%d out of %d",
677 start, number, rr.hits);
679 srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits);
686 yaz_log(LOG_LOG, "Request out or range");
691 int packing = Z_SRW_recordPacking_string;
692 if (start + number > rr.hits)
693 number = rr.hits - start + 1;
694 if (srw_req->recordPacking &&
695 !strcmp(srw_req->recordPacking, "xml"))
696 packing = Z_SRW_recordPacking_XML;
697 srw_res->records = (Z_SRW_record *)
698 odr_malloc(assoc->encode,
699 number * sizeof(*srw_res->records));
700 for (i = 0; i<number; i++)
704 srw_res->records[j].recordPacking = packing;
705 srw_res->records[j].recordData_buf = 0;
706 yaz_log(LOG_DEBUG, "srw_bend_fetch %d", i+start);
707 errcode = srw_bend_fetch(assoc, i+start, srw_req,
708 srw_res->records + j);
711 srw_res->num_diagnostics = 1;
712 srw_res->diagnostics = (Z_SRW_diagnostic *)
713 odr_malloc(assoc->encode,
714 sizeof(*srw_res->diagnostics));
716 yaz_mk_std_diagnostic(assoc->encode,
717 srw_res->diagnostics,
718 yaz_diag_bib1_to_srw (errcode),
722 if (srw_res->records[j].recordData_buf)
725 srw_res->num_records = j;
727 srw_res->records = 0;
733 static void srw_bend_explain(association *assoc, request *req,
734 Z_SRW_explainRequest *srw_req,
735 Z_SRW_explainResponse *srw_res,
738 yaz_log(LOG_LOG, "Got SRW ExplainRequest");
742 yaz_log(LOG_DEBUG, "srw_bend_init");
743 if (!srw_bend_init(assoc))
748 if (assoc->init && assoc->init->bend_explain)
752 rr.stream = assoc->encode;
753 rr.decode = assoc->decode;
754 rr.print = assoc->print;
756 rr.database = srw_req->database;
757 rr.schema = "http://explain.z3950.org/dtd/2.0/";
758 (*assoc->init->bend_explain)(assoc->backend, &rr);
761 int packing = Z_SRW_recordPacking_string;
762 if (srw_req->recordPacking &&
763 !strcmp(srw_req->recordPacking, "xml"))
764 packing = Z_SRW_recordPacking_XML;
765 srw_res->record.recordSchema = 0;
766 srw_res->record.recordPacking = packing;
767 srw_res->record.recordData_buf = rr.explain_buf;
768 srw_res->record.recordData_len = strlen(rr.explain_buf);
769 srw_res->record.recordPosition = 0;
775 static void process_http_request(association *assoc, request *req)
777 Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request;
778 ODR o = assoc->encode;
779 int r = 2; /* 2=NOT TAKEN, 1=TAKEN, 0=SOAP TAKEN */
781 Z_SOAP *soap_package = 0;
784 Z_HTTP_Response *hres = 0;
786 char *stylesheet = 0;
787 Z_SRW_diagnostic *diagnostic = 0;
788 int num_diagnostic = 0;
790 if (!strcmp(hreq->path, "/test"))
792 p = z_get_HTTP_Response(o, 200);
793 hres = p->u.HTTP_Response;
794 hres->content_buf = "1234567890\n";
795 hres->content_len = strlen(hres->content_buf);
800 r = yaz_srw_decode(hreq, &sr, &soap_package, assoc->decode, &charset);
801 yaz_log(LOG_DEBUG, "yaz_srw_decode returned %d", r);
803 if (r == 2) /* not taken */
805 r = yaz_sru_decode(hreq, &sr, &soap_package, assoc->decode, &charset,
806 &diagnostic, &num_diagnostic);
807 yaz_log(LOG_DEBUG, "yaz_sru_decode returned %d", r);
809 if (r == 0) /* decode SRW/SRU OK .. */
812 if (sr->which == Z_SRW_searchRetrieve_request)
815 yaz_srw_get(assoc->encode, Z_SRW_searchRetrieve_response);
817 stylesheet = sr->u.request->stylesheet;
820 res->u.response->diagnostics = diagnostic;
821 res->u.response->num_diagnostics = num_diagnostic;
825 srw_bend_search(assoc, req, sr->u.request, res->u.response,
828 if (http_code == 200)
829 soap_package->u.generic->p = res;
831 else if (sr->which == Z_SRW_explain_request)
833 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_explain_response);
834 stylesheet = sr->u.explain_request->stylesheet;
837 res->u.explain_response->diagnostics = diagnostic;
838 res->u.explain_response->num_diagnostics = num_diagnostic;
840 srw_bend_explain(assoc, req, sr->u.explain_request,
841 res->u.explain_response, &http_code);
842 if (http_code == 200)
843 soap_package->u.generic->p = res;
845 else if (sr->which == Z_SRW_scan_request)
847 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_scan_response);
848 stylesheet = sr->u.scan_request->stylesheet;
851 res->u.scan_response->diagnostics = diagnostic;
852 res->u.scan_response->num_diagnostics = num_diagnostic;
854 yaz_add_srw_diagnostic(o,
855 &res->u.scan_response->diagnostics,
856 &res->u.scan_response->num_diagnostics,
858 if (http_code == 200)
859 soap_package->u.generic->p = res;
863 yaz_log(LOG_LOG, "generate soap error");
865 z_soap_error(assoc->encode, soap_package,
866 "SOAP-ENV:Client", "Bad method", 0);
868 if (http_code == 200 || http_code == 500)
870 static Z_SOAP_Handler soap_handlers[3] = {
872 {"http://www.loc.gov/zing/srw/", 0,
873 (Z_SOAP_fun) yaz_srw_codec},
874 {"http://www.loc.gov/zing/srw/v1.0/", 0,
875 (Z_SOAP_fun) yaz_srw_codec},
881 p = z_get_HTTP_Response(o, 200);
882 hres = p->u.HTTP_Response;
883 ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package,
884 &hres->content_buf, &hres->content_len,
885 soap_handlers, charset, stylesheet);
886 hres->code = http_code;
888 strcpy(ctype, "text/xml");
891 strcat(ctype, "; charset=");
892 strcat(ctype, charset);
894 z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
897 p = z_get_HTTP_Response(o, http_code);
901 p = z_get_HTTP_Response(o, 500);
902 hres = p->u.HTTP_Response;
903 if (!strcmp(hreq->version, "1.0"))
905 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
906 if (v && !strcmp(v, "Keep-Alive"))
910 hres->version = "1.0";
914 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
915 if (v && !strcmp(v, "close"))
919 hres->version = "1.1";
923 z_HTTP_header_add(o, &hres->headers, "Connection", "close");
924 assoc->state = ASSOC_DEAD;
925 assoc->cs_get_mask = 0;
930 const char *alive = z_HTTP_header_lookup(hreq->headers, "Keep-Alive");
932 if (alive && isdigit(*alive))
936 if (t < 0 || t > 3600)
938 iochan_settimeout(assoc->client_chan,t);
939 z_HTTP_header_add(o, &hres->headers, "Connection", "Keep-Alive");
941 process_gdu_response(assoc, req, p);
944 static void process_gdu_request(association *assoc, request *req)
946 if (req->gdu_request->which == Z_GDU_Z3950)
949 req->apdu_request = req->gdu_request->u.z3950;
950 if (process_z_request(assoc, req, &msg) < 0)
951 do_close_req(assoc, Z_Close_systemProblem, msg, req);
953 else if (req->gdu_request->which == Z_GDU_HTTP_Request)
954 process_http_request(assoc, req);
957 do_close_req(assoc, Z_Close_systemProblem, "bad protocol packet", req);
962 * Initiate request processing.
964 static int process_z_request(association *assoc, request *req, char **msg)
970 *msg = "Unknown Error";
971 assert(req && req->state == REQUEST_IDLE);
972 if (req->apdu_request->which != Z_APDU_initRequest && !assoc->init)
974 *msg = "Missing InitRequest";
977 switch (req->apdu_request->which)
979 case Z_APDU_initRequest:
980 iochan_settimeout(assoc->client_chan,
981 statserv_getcontrol()->idle_timeout * 60);
982 res = process_initRequest(assoc, req); break;
983 case Z_APDU_searchRequest:
984 res = process_searchRequest(assoc, req, &fd); break;
985 case Z_APDU_presentRequest:
986 res = process_presentRequest(assoc, req, &fd); break;
987 case Z_APDU_scanRequest:
988 if (assoc->init->bend_scan)
989 res = process_scanRequest(assoc, req, &fd);
992 *msg = "Cannot handle Scan APDU";
996 case Z_APDU_extendedServicesRequest:
997 if (assoc->init->bend_esrequest)
998 res = process_ESRequest(assoc, req, &fd);
1001 *msg = "Cannot handle Extended Services APDU";
1005 case Z_APDU_sortRequest:
1006 if (assoc->init->bend_sort)
1007 res = process_sortRequest(assoc, req, &fd);
1010 *msg = "Cannot handle Sort APDU";
1015 process_close(assoc, req);
1017 case Z_APDU_deleteResultSetRequest:
1018 if (assoc->init->bend_delete)
1019 res = process_deleteRequest(assoc, req, &fd);
1022 *msg = "Cannot handle Delete APDU";
1026 case Z_APDU_segmentRequest:
1027 if (assoc->init->bend_segment)
1029 res = process_segmentRequest (assoc, req);
1033 *msg = "Cannot handle Segment APDU";
1038 *msg = "Bad APDU received";
1043 yaz_log(LOG_DEBUG, " result immediately available");
1044 retval = process_z_response(assoc, req, res);
1048 yaz_log(LOG_DEBUG, " result unavailble");
1051 else /* no result yet - one will be provided later */
1055 /* Set up an I/O handler for the fd supplied by the backend */
1057 yaz_log(LOG_DEBUG, " establishing handler for result");
1058 req->state = REQUEST_PENDING;
1059 if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT)))
1061 iochan_setdata(chan, assoc);
1068 * Handle message from the backend.
1070 void backend_response(IOCHAN i, int event)
1072 association *assoc = (association *)iochan_getdata(i);
1073 request *req = request_head(&assoc->incoming);
1077 yaz_log(LOG_DEBUG, "backend_response");
1078 assert(assoc && req && req->state != REQUEST_IDLE);
1079 /* determine what it is we're waiting for */
1080 switch (req->apdu_request->which)
1082 case Z_APDU_searchRequest:
1083 res = response_searchRequest(assoc, req, 0, &fd); break;
1085 case Z_APDU_presentRequest:
1086 res = response_presentRequest(assoc, req, 0, &fd); break;
1087 case Z_APDU_scanRequest:
1088 res = response_scanRequest(assoc, req, 0, &fd); break;
1091 yaz_log(LOG_WARN, "Serious programmer's lapse or bug");
1094 if ((res && process_z_response(assoc, req, res) < 0) || fd < 0)
1096 yaz_log(LOG_LOG, "Fatal error when talking to backend");
1097 do_close(assoc, Z_Close_systemProblem, 0);
1101 else if (!res) /* no result yet - try again later */
1103 yaz_log(LOG_DEBUG, " no result yet");
1104 iochan_setfd(i, fd); /* in case fd has changed */
1109 * Encode response, and transfer the request structure to the outgoing queue.
1111 static int process_gdu_response(association *assoc, request *req, Z_GDU *res)
1113 odr_setbuf(assoc->encode, req->response, req->size_response, 1);
1117 if (!z_GDU(assoc->print, &res, 0, 0))
1118 yaz_log(LOG_WARN, "ODR print error: %s",
1119 odr_errmsg(odr_geterror(assoc->print)));
1120 odr_reset(assoc->print);
1122 if (!z_GDU(assoc->encode, &res, 0, 0))
1124 yaz_log(LOG_WARN, "ODR error when encoding PDU: %s [element %s]",
1125 odr_errmsg(odr_geterror(assoc->decode)),
1126 odr_getelement(assoc->decode));
1127 request_release(req);
1130 req->response = odr_getbuf(assoc->encode, &req->len_response,
1131 &req->size_response);
1132 odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */
1133 odr_reset(assoc->encode);
1134 req->state = REQUEST_IDLE;
1135 request_enq(&assoc->outgoing, req);
1136 /* turn the work over to the ir_session handler */
1137 iochan_setflag(assoc->client_chan, EVENT_OUTPUT);
1138 assoc->cs_put_mask = EVENT_OUTPUT;
1139 /* Is there more work to be done? give that to the input handler too */
1141 if (request_head(&assoc->incoming))
1143 yaz_log (LOG_DEBUG, "more work to be done");
1144 iochan_setevent(assoc->client_chan, EVENT_WORK);
1151 * Encode response, and transfer the request structure to the outgoing queue.
1153 static int process_z_response(association *assoc, request *req, Z_APDU *res)
1155 Z_GDU *gres = (Z_GDU *) odr_malloc(assoc->encode, sizeof(*res));
1156 gres->which = Z_GDU_Z3950;
1157 gres->u.z3950 = res;
1159 return process_gdu_response(assoc, req, gres);
1164 * Handle init request.
1165 * At the moment, we don't check the options
1166 * anywhere else in the code - we just try not to do anything that would
1167 * break a naive client. We'll toss 'em into the association block when
1168 * we need them there.
1170 static Z_APDU *process_initRequest(association *assoc, request *reqb)
1172 statserv_options_block *cb = statserv_getcontrol();
1173 Z_InitRequest *req = reqb->apdu_request->u.initRequest;
1174 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_initResponse);
1175 Z_InitResponse *resp = apdu->u.initResponse;
1176 bend_initresult *binitres;
1180 yaz_log(LOG_LOG, "Got initRequest");
1181 if (req->implementationId)
1182 yaz_log(LOG_LOG, "Id: %s", req->implementationId);
1183 if (req->implementationName)
1184 yaz_log(LOG_LOG, "Name: %s", req->implementationName);
1185 if (req->implementationVersion)
1186 yaz_log(LOG_LOG, "Version: %s", req->implementationVersion);
1188 assoc_init_reset(assoc);
1190 assoc->init->auth = req->idAuthentication;
1191 assoc->init->referenceId = req->referenceId;
1193 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
1195 Z_CharSetandLanguageNegotiation *negotiation =
1196 yaz_get_charneg_record (req->otherInfo);
1198 negotiation->which == Z_CharSetandLanguageNegotiation_proposal)
1199 assoc->init->charneg_request = negotiation;
1203 if (!(binitres = (*cb->bend_init)(assoc->init)))
1205 yaz_log(LOG_WARN, "Bad response from backend.");
1209 assoc->backend = binitres->handle;
1210 if ((assoc->init->bend_sort))
1211 yaz_log (LOG_DEBUG, "Sort handler installed");
1212 if ((assoc->init->bend_search))
1213 yaz_log (LOG_DEBUG, "Search handler installed");
1214 if ((assoc->init->bend_present))
1215 yaz_log (LOG_DEBUG, "Present handler installed");
1216 if ((assoc->init->bend_esrequest))
1217 yaz_log (LOG_DEBUG, "ESRequest handler installed");
1218 if ((assoc->init->bend_delete))
1219 yaz_log (LOG_DEBUG, "Delete handler installed");
1220 if ((assoc->init->bend_scan))
1221 yaz_log (LOG_DEBUG, "Scan handler installed");
1222 if ((assoc->init->bend_segment))
1223 yaz_log (LOG_DEBUG, "Segment handler installed");
1225 resp->referenceId = req->referenceId;
1227 /* let's tell the client what we can do */
1228 if (ODR_MASK_GET(req->options, Z_Options_search))
1230 ODR_MASK_SET(resp->options, Z_Options_search);
1231 strcat(options, "srch");
1233 if (ODR_MASK_GET(req->options, Z_Options_present))
1235 ODR_MASK_SET(resp->options, Z_Options_present);
1236 strcat(options, " prst");
1238 if (ODR_MASK_GET(req->options, Z_Options_delSet) &&
1239 assoc->init->bend_delete)
1241 ODR_MASK_SET(resp->options, Z_Options_delSet);
1242 strcat(options, " del");
1244 if (ODR_MASK_GET(req->options, Z_Options_extendedServices) &&
1245 assoc->init->bend_esrequest)
1247 ODR_MASK_SET(resp->options, Z_Options_extendedServices);
1248 strcat (options, " extendedServices");
1250 if (ODR_MASK_GET(req->options, Z_Options_namedResultSets))
1252 ODR_MASK_SET(resp->options, Z_Options_namedResultSets);
1253 strcat(options, " namedresults");
1255 if (ODR_MASK_GET(req->options, Z_Options_scan) && assoc->init->bend_scan)
1257 ODR_MASK_SET(resp->options, Z_Options_scan);
1258 strcat(options, " scan");
1260 if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations))
1262 ODR_MASK_SET(resp->options, Z_Options_concurrentOperations);
1263 strcat(options, " concurrop");
1265 if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort)
1267 ODR_MASK_SET(resp->options, Z_Options_sort);
1268 strcat(options, " sort");
1271 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)
1272 && assoc->init->charneg_response)
1274 Z_OtherInformation **p;
1275 Z_OtherInformationUnit *p0;
1277 yaz_oi_APDU(apdu, &p);
1279 if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) {
1280 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1282 p0->which = Z_OtherInfo_externallyDefinedInfo;
1283 p0->information.externallyDefinedInfo =
1284 assoc->init->charneg_response;
1286 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1287 strcat(options, " negotiation");
1290 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
1292 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
1293 assoc->version = 1; /* 1 & 2 are equivalent */
1295 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
1297 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
1300 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
1302 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
1306 yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options);
1307 assoc->maximumRecordSize = *req->maximumRecordSize;
1308 if (assoc->maximumRecordSize > control_block->maxrecordsize)
1309 assoc->maximumRecordSize = control_block->maxrecordsize;
1310 assoc->preferredMessageSize = *req->preferredMessageSize;
1311 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
1312 assoc->preferredMessageSize = assoc->maximumRecordSize;
1314 resp->preferredMessageSize = &assoc->preferredMessageSize;
1315 resp->maximumRecordSize = &assoc->maximumRecordSize;
1317 resp->implementationId = odr_prepend(assoc->encode,
1318 assoc->init->implementation_id,
1319 resp->implementationId);
1321 resp->implementationName = odr_prepend(assoc->encode,
1322 assoc->init->implementation_name,
1323 odr_prepend(assoc->encode, "GFS", resp->implementationName));
1325 version = odr_strdup(assoc->encode, "$Revision: 1.25 $");
1326 if (strlen(version) > 10) /* check for unexpanded CVS strings */
1327 version[strlen(version)-2] = '\0';
1328 resp->implementationVersion = odr_prepend(assoc->encode,
1329 assoc->init->implementation_version,
1330 odr_prepend(assoc->encode, &version[11],
1331 resp->implementationVersion));
1333 if (binitres->errcode)
1335 yaz_log(LOG_LOG, "Connection rejected by backend.");
1337 assoc->state = ASSOC_DEAD;
1338 resp->userInformationField = init_diagnostics(assoc->encode,
1340 binitres->errstring);
1343 assoc->state = ASSOC_UP;
1348 * Diagnostic in default format, to be returned as either a surrogate
1349 * or non-surrogate diagnostic in the context of an open session, or
1350 * as User-information when an Init is refused.
1352 static Z_DefaultDiagFormat *justdiag(ODR odr, int error, char *addinfo)
1354 int *err = odr_intdup(odr, error);
1355 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
1356 odr_malloc (odr, sizeof(*dr));
1358 yaz_log(LOG_LOG, "[%d] %s%s%s", error, diagbib1_str(error),
1359 addinfo ? " -- " : "", addinfo ? addinfo : "");
1361 dr->diagnosticSetId =
1362 yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1);
1363 dr->condition = err;
1364 dr->which = Z_DefaultDiagFormat_v2Addinfo;
1365 dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
1370 * Set the specified `errcode' and `errstring' into a UserInfo-1
1371 * external to be returned to the client in accordance with Z35.90
1372 * Implementor Agreement 5 (Returning diagnostics in an InitResponse):
1373 * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html
1375 static Z_External *init_diagnostics(ODR odr, int error, char *addinfo)
1379 Z_OtherInformation *u;
1380 Z_OtherInformationUnit *l;
1381 Z_DiagnosticFormat *d;
1382 Z_DiagnosticFormat_s *e;
1384 x = (Z_External*) odr_malloc(odr, sizeof *x);
1386 x->indirect_reference = 0;
1387 oid.proto = PROTO_Z3950;
1388 oid.oclass = CLASS_USERINFO;
1389 oid.value = VAL_USERINFO1;
1390 x->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1391 x->which = Z_External_userInfo1;
1393 u = odr_malloc(odr, sizeof *u);
1395 u->num_elements = 1;
1396 u->list = (Z_OtherInformationUnit**) odr_malloc(odr, sizeof *u->list);
1397 u->list[0] = (Z_OtherInformationUnit*) odr_malloc(odr, sizeof *u->list[0]);
1400 l->which = Z_OtherInfo_externallyDefinedInfo;
1402 x2 = (Z_External*) odr_malloc(odr, sizeof *x);
1403 l->information.externallyDefinedInfo = x2;
1405 x2->indirect_reference = 0;
1406 oid.oclass = CLASS_DIAGSET;
1407 oid.value = VAL_DIAG1;
1408 x2->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1409 x2->which = Z_External_diag1;
1411 d = (Z_DiagnosticFormat*) odr_malloc(odr, sizeof *d);
1414 d->elements = (Z_DiagnosticFormat_s**) odr_malloc (odr, sizeof *d->elements);
1415 d->elements[0] = (Z_DiagnosticFormat_s*) odr_malloc (odr, sizeof *d->elements[0]);
1418 e->which = Z_DiagnosticFormat_s_defaultDiagRec;
1419 e->u.defaultDiagRec = justdiag(odr, error, addinfo);
1425 * nonsurrogate diagnostic record.
1427 static Z_Records *diagrec(association *assoc, int error, char *addinfo)
1429 Z_Records *rec = (Z_Records *)
1430 odr_malloc (assoc->encode, sizeof(*rec));
1431 rec->which = Z_Records_NSD;
1432 rec->u.nonSurrogateDiagnostic = justdiag(assoc->encode, error, addinfo);
1437 * surrogate diagnostic.
1439 static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname,
1440 int error, char *addinfo)
1442 Z_NamePlusRecord *rec = (Z_NamePlusRecord *)
1443 odr_malloc (assoc->encode, sizeof(*rec));
1444 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1446 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
1447 rec->databaseName = dbname;
1448 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
1449 rec->u.surrogateDiagnostic = drec;
1450 drec->which = Z_DiagRec_defaultFormat;
1451 drec->u.defaultFormat = justdiag(assoc->encode, error, addinfo);
1457 * multiple nonsurrogate diagnostics.
1459 static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo)
1461 Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs));
1462 int *err = odr_intdup(assoc->encode, error);
1463 Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp));
1464 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1465 Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *)
1466 odr_malloc (assoc->encode, sizeof(*rec));
1468 yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : "");
1470 recs->num_diagRecs = 1;
1471 recs->diagRecs = recp;
1473 drec->which = Z_DiagRec_defaultFormat;
1474 drec->u.defaultFormat = rec;
1476 rec->diagnosticSetId =
1477 yaz_oidval_to_z3950oid (assoc->encode, CLASS_DIAGSET, VAL_BIB1);
1478 rec->condition = err;
1480 rec->which = Z_DefaultDiagFormat_v2Addinfo;
1481 rec->u.v2Addinfo = odr_strdup (assoc->encode, addinfo ? addinfo : "");
1485 static Z_Records *pack_records(association *a, char *setname, int start,
1486 int *num, Z_RecordComposition *comp,
1487 int *next, int *pres, oid_value format,
1488 Z_ReferenceId *referenceId,
1491 int recno, total_length = 0, toget = *num, dumped_records = 0;
1492 Z_Records *records =
1493 (Z_Records *) odr_malloc (a->encode, sizeof(*records));
1494 Z_NamePlusRecordList *reclist =
1495 (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist));
1496 Z_NamePlusRecord **list =
1497 (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget);
1499 records->which = Z_Records_DBOSD;
1500 records->u.databaseOrSurDiagnostics = reclist;
1501 reclist->num_records = 0;
1502 reclist->records = list;
1503 *pres = Z_PresentStatus_success;
1507 yaz_log(LOG_LOG, "Request to pack %d+%d+%s", start, toget, setname);
1508 yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize,
1509 a->maximumRecordSize);
1510 for (recno = start; reclist->num_records < toget; recno++)
1513 Z_NamePlusRecord *thisrec;
1514 int this_length = 0;
1516 * we get the number of bytes allocated on the stream before any
1517 * allocation done by the backend - this should give us a reasonable
1518 * idea of the total size of the data so far.
1520 total_length = odr_total(a->encode) - dumped_records;
1526 freq.last_in_set = 0;
1527 freq.setname = setname;
1528 freq.surrogate_flag = 0;
1529 freq.number = recno;
1531 freq.request_format = format;
1532 freq.request_format_raw = oid;
1533 freq.output_format = format;
1534 freq.output_format_raw = 0;
1535 freq.stream = a->encode;
1536 freq.print = a->print;
1537 freq.referenceId = referenceId;
1539 (*a->init->bend_fetch)(a->backend, &freq);
1540 /* backend should be able to signal whether error is system-wide
1541 or only pertaining to current record */
1544 if (!freq.surrogate_flag)
1547 *pres = Z_PresentStatus_failure;
1548 /* for 'present request out of range',
1549 set addinfo to record position if not set */
1550 if (freq.errcode == 13 && freq.errstring == 0)
1552 sprintf (s, "%d", recno);
1555 return diagrec(a, freq.errcode, freq.errstring);
1557 reclist->records[reclist->num_records] =
1558 surrogatediagrec(a, freq.basename, freq.errcode,
1560 reclist->num_records++;
1561 *next = freq.last_in_set ? 0 : recno + 1;
1565 this_length = freq.len;
1567 this_length = odr_total(a->encode) - total_length - dumped_records;
1568 yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d dumped=%d",
1569 this_length, total_length, dumped_records);
1570 if (a->preferredMessageSize > 0 &&
1571 this_length + total_length > a->preferredMessageSize)
1573 /* record is small enough, really */
1574 if (this_length <= a->preferredMessageSize && recno > start)
1576 yaz_log(LOG_DEBUG, " Dropped last normal-sized record");
1577 *pres = Z_PresentStatus_partial_2;
1580 /* record can only be fetched by itself */
1581 if (this_length < a->maximumRecordSize)
1583 yaz_log(LOG_DEBUG, " Record > prefmsgsz");
1586 yaz_log(LOG_DEBUG, " Dropped it");
1587 reclist->records[reclist->num_records] =
1588 surrogatediagrec(a, freq.basename, 16, 0);
1589 reclist->num_records++;
1590 *next = freq.last_in_set ? 0 : recno + 1;
1591 dumped_records += this_length;
1595 else /* too big entirely */
1597 yaz_log(LOG_LOG, "Record > maxrcdsz this=%d max=%d", this_length, a->maximumRecordSize);
1598 reclist->records[reclist->num_records] =
1599 surrogatediagrec(a, freq.basename, 17, 0);
1600 reclist->num_records++;
1601 *next = freq.last_in_set ? 0 : recno + 1;
1602 dumped_records += this_length;
1607 if (!(thisrec = (Z_NamePlusRecord *)
1608 odr_malloc(a->encode, sizeof(*thisrec))))
1610 if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
1611 strlen(freq.basename) + 1)))
1613 strcpy(thisrec->databaseName, freq.basename);
1614 thisrec->which = Z_NamePlusRecord_databaseRecord;
1616 if (freq.output_format_raw)
1618 struct oident *ident = oid_getentbyoid(freq.output_format_raw);
1619 freq.output_format = ident->value;
1621 thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format,
1622 freq.record, freq.len);
1623 if (!thisrec->u.databaseRecord)
1625 reclist->records[reclist->num_records] = thisrec;
1626 reclist->num_records++;
1627 *next = freq.last_in_set ? 0 : recno + 1;
1629 *num = reclist->num_records;
1633 static Z_APDU *process_searchRequest(association *assoc, request *reqb,
1636 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1637 bend_search_rr *bsrr =
1638 (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr));
1640 yaz_log(LOG_LOG, "Got SearchRequest.");
1642 bsrr->request = reqb;
1643 bsrr->association = assoc;
1644 bsrr->referenceId = req->referenceId;
1645 save_referenceId (reqb, bsrr->referenceId);
1647 yaz_log (LOG_LOG, "ResultSet '%s'", req->resultSetName);
1648 if (req->databaseNames)
1651 for (i = 0; i < req->num_databaseNames; i++)
1652 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1654 yaz_log_zquery(req->query);
1656 if (assoc->init->bend_search)
1658 bsrr->setname = req->resultSetName;
1659 bsrr->replace_set = *req->replaceIndicator;
1660 bsrr->num_bases = req->num_databaseNames;
1661 bsrr->basenames = req->databaseNames;
1662 bsrr->query = req->query;
1663 bsrr->stream = assoc->encode;
1664 nmem_transfer(bsrr->stream->mem, reqb->request_mem);
1665 bsrr->decode = assoc->decode;
1666 bsrr->print = assoc->print;
1669 bsrr->errstring = NULL;
1670 bsrr->search_info = NULL;
1671 (assoc->init->bend_search)(assoc->backend, bsrr);
1675 return response_searchRequest(assoc, reqb, bsrr, fd);
1678 int bend_searchresponse(void *handle, bend_search_rr *bsrr) {return 0;}
1681 * Prepare a searchresponse based on the backend results. We probably want
1682 * to look at making the fetching of records nonblocking as well, but
1683 * so far, we'll keep things simple.
1684 * If bsrt is null, that means we're called in response to a communications
1685 * event, and we'll have to get the response for ourselves.
1687 static Z_APDU *response_searchRequest(association *assoc, request *reqb,
1688 bend_search_rr *bsrt, int *fd)
1690 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1691 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1692 Z_SearchResponse *resp = (Z_SearchResponse *)
1693 odr_malloc (assoc->encode, sizeof(*resp));
1694 int *nulint = odr_intdup (assoc->encode, 0);
1695 bool_t *sr = odr_intdup(assoc->encode, 1);
1696 int *next = odr_intdup(assoc->encode, 0);
1697 int *none = odr_intdup(assoc->encode, Z_SearchResponse_none);
1699 apdu->which = Z_APDU_searchResponse;
1700 apdu->u.searchResponse = resp;
1701 resp->referenceId = req->referenceId;
1702 resp->additionalSearchInfo = 0;
1703 resp->otherInfo = 0;
1705 if (!bsrt && !bend_searchresponse(assoc->backend, bsrt))
1707 yaz_log(LOG_FATAL, "Bad result from backend");
1710 else if (bsrt->errcode)
1712 resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring);
1713 resp->resultCount = nulint;
1714 resp->numberOfRecordsReturned = nulint;
1715 resp->nextResultSetPosition = nulint;
1716 resp->searchStatus = nulint;
1717 resp->resultSetStatus = none;
1718 resp->presentStatus = 0;
1722 int *toget = odr_intdup(assoc->encode, 0);
1723 int *presst = odr_intdup(assoc->encode, 0);
1724 Z_RecordComposition comp, *compp = 0;
1726 yaz_log (LOG_LOG, "resultCount: %d", bsrt->hits);
1729 resp->resultCount = &bsrt->hits;
1731 comp.which = Z_RecordComp_simple;
1732 /* how many records does the user agent want, then? */
1733 if (bsrt->hits <= *req->smallSetUpperBound)
1735 *toget = bsrt->hits;
1736 if ((comp.u.simple = req->smallSetElementSetNames))
1739 else if (bsrt->hits < *req->largeSetLowerBound)
1741 *toget = *req->mediumSetPresentNumber;
1742 if (*toget > bsrt->hits)
1743 *toget = bsrt->hits;
1744 if ((comp.u.simple = req->mediumSetElementSetNames))
1750 if (*toget && !resp->records)
1755 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1758 form = prefformat->value;
1759 resp->records = pack_records(assoc, req->resultSetName, 1,
1760 toget, compp, next, presst, form, req->referenceId,
1761 req->preferredRecordSyntax);
1764 resp->numberOfRecordsReturned = toget;
1765 resp->nextResultSetPosition = next;
1766 resp->searchStatus = sr;
1767 resp->resultSetStatus = 0;
1768 resp->presentStatus = presst;
1772 if (*resp->resultCount)
1774 resp->numberOfRecordsReturned = nulint;
1775 resp->nextResultSetPosition = next;
1776 resp->searchStatus = sr;
1777 resp->resultSetStatus = 0;
1778 resp->presentStatus = 0;
1781 resp->additionalSearchInfo = bsrt->search_info;
1786 * Maybe we got a little over-friendly when we designed bend_fetch to
1787 * get only one record at a time. Some backends can optimise multiple-record
1788 * fetches, and at any rate, there is some overhead involved in
1789 * all that selecting and hopping around. Problem is, of course, that the
1790 * frontend can't know ahead of time how many records it'll need to
1791 * fill the negotiated PDU size. Annoying. Segmentation or not, Z/SR
1792 * is downright lousy as a bulk data transfer protocol.
1794 * To start with, we'll do the fetching of records from the backend
1795 * in one operation: To save some trips in and out of the event-handler,
1796 * and to simplify the interface to pack_records. At any rate, asynch
1797 * operation is more fun in operations that have an unpredictable execution
1798 * speed - which is normally more true for search than for present.
1800 static Z_APDU *process_presentRequest(association *assoc, request *reqb,
1803 Z_PresentRequest *req = reqb->apdu_request->u.presentRequest;
1807 Z_PresentResponse *resp;
1811 yaz_log(LOG_LOG, "Got PresentRequest.");
1813 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1816 form = prefformat->value;
1817 resp = (Z_PresentResponse *)odr_malloc (assoc->encode, sizeof(*resp));
1819 resp->presentStatus = odr_intdup(assoc->encode, 0);
1820 if (assoc->init->bend_present)
1822 bend_present_rr *bprr = (bend_present_rr *)
1823 nmem_malloc (reqb->request_mem, sizeof(*bprr));
1824 bprr->setname = req->resultSetId;
1825 bprr->start = *req->resultSetStartPoint;
1826 bprr->number = *req->numberOfRecordsRequested;
1827 bprr->format = form;
1828 bprr->comp = req->recordComposition;
1829 bprr->referenceId = req->referenceId;
1830 bprr->stream = assoc->encode;
1831 bprr->print = assoc->print;
1832 bprr->request = reqb;
1833 bprr->association = assoc;
1835 bprr->errstring = NULL;
1836 (*assoc->init->bend_present)(assoc->backend, bprr);
1842 resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
1843 *resp->presentStatus = Z_PresentStatus_failure;
1846 apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1847 next = odr_intdup(assoc->encode, 0);
1848 num = odr_intdup(assoc->encode, 0);
1850 apdu->which = Z_APDU_presentResponse;
1851 apdu->u.presentResponse = resp;
1852 resp->referenceId = req->referenceId;
1853 resp->otherInfo = 0;
1857 *num = *req->numberOfRecordsRequested;
1859 pack_records(assoc, req->resultSetId, *req->resultSetStartPoint,
1860 num, req->recordComposition, next, resp->presentStatus,
1861 form, req->referenceId, req->preferredRecordSyntax);
1865 resp->numberOfRecordsReturned = num;
1866 resp->nextResultSetPosition = next;
1872 * Scan was implemented rather in a hurry, and with support for only the basic
1873 * elements of the service in the backend API. Suggestions are welcome.
1875 static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd)
1877 Z_ScanRequest *req = reqb->apdu_request->u.scanRequest;
1878 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1879 Z_ScanResponse *res = (Z_ScanResponse *)
1880 odr_malloc (assoc->encode, sizeof(*res));
1881 int *scanStatus = odr_intdup(assoc->encode, Z_Scan_failure);
1882 int *numberOfEntriesReturned = odr_intdup(assoc->encode, 0);
1883 Z_ListEntries *ents = (Z_ListEntries *)
1884 odr_malloc (assoc->encode, sizeof(*ents));
1885 Z_DiagRecs *diagrecs_p = NULL;
1887 bend_scan_rr *bsrr = (bend_scan_rr *)
1888 odr_malloc (assoc->encode, sizeof(*bsrr));
1889 struct scan_entry *save_entries;
1891 yaz_log(LOG_LOG, "Got ScanRequest");
1893 apdu->which = Z_APDU_scanResponse;
1894 apdu->u.scanResponse = res;
1895 res->referenceId = req->referenceId;
1897 /* if step is absent, set it to 0 */
1898 res->stepSize = odr_intdup(assoc->encode, 0);
1900 *res->stepSize = *req->stepSize;
1902 res->scanStatus = scanStatus;
1903 res->numberOfEntriesReturned = numberOfEntriesReturned;
1904 res->positionOfTerm = 0;
1905 res->entries = ents;
1906 ents->num_entries = 0;
1907 ents->entries = NULL;
1908 ents->num_nonsurrogateDiagnostics = 0;
1909 ents->nonsurrogateDiagnostics = NULL;
1910 res->attributeSet = 0;
1913 if (req->databaseNames)
1916 for (i = 0; i < req->num_databaseNames; i++)
1917 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1919 bsrr->num_bases = req->num_databaseNames;
1920 bsrr->basenames = req->databaseNames;
1921 bsrr->num_entries = *req->numberOfTermsRequested;
1922 bsrr->term = req->termListAndStartPoint;
1923 bsrr->referenceId = req->referenceId;
1924 bsrr->stream = assoc->encode;
1925 bsrr->print = assoc->print;
1926 bsrr->step_size = res->stepSize;
1928 /* Note that version 2.0 of YAZ and older did not set entries ..
1929 We do now. And when we do it's easier to extend the scan entry
1930 We know that if the scan handler did set entries, it will
1931 not know of new member display_term.
1933 if (bsrr->num_entries > 0)
1936 bsrr->entries = odr_malloc(assoc->decode, sizeof(*bsrr->entries) *
1938 for (i = 0; i<bsrr->num_entries; i++)
1940 bsrr->entries[i].term = 0;
1941 bsrr->entries[i].occurrences = 0;
1942 bsrr->entries[i].errcode = 0;
1943 bsrr->entries[i].errstring = 0;
1944 bsrr->entries[i].display_term = 0;
1947 save_entries = bsrr->entries; /* save it so we can compare later */
1949 if (req->attributeSet &&
1950 (attset = oid_getentbyoid(req->attributeSet)) &&
1951 (attset->oclass == CLASS_ATTSET || attset->oclass == CLASS_GENERAL))
1952 bsrr->attributeset = attset->value;
1954 bsrr->attributeset = VAL_NONE;
1955 log_scan_term (req->termListAndStartPoint, bsrr->attributeset);
1956 bsrr->term_position = req->preferredPositionInResponse ?
1957 *req->preferredPositionInResponse : 1;
1958 ((int (*)(void *, bend_scan_rr *))
1959 (*assoc->init->bend_scan))(assoc->backend, bsrr);
1961 diagrecs_p = diagrecs(assoc, bsrr->errcode, bsrr->errstring);
1965 Z_Entry **tab = (Z_Entry **)
1966 odr_malloc (assoc->encode, sizeof(*tab) * bsrr->num_entries);
1968 if (bsrr->status == BEND_SCAN_PARTIAL)
1969 *scanStatus = Z_Scan_partial_5;
1971 *scanStatus = Z_Scan_success;
1972 ents->entries = tab;
1973 ents->num_entries = bsrr->num_entries;
1974 res->numberOfEntriesReturned = &ents->num_entries;
1975 res->positionOfTerm = &bsrr->term_position;
1976 for (i = 0; i < bsrr->num_entries; i++)
1982 tab[i] = e = (Z_Entry *)odr_malloc(assoc->encode, sizeof(*e));
1983 if (bsrr->entries[i].occurrences >= 0)
1985 e->which = Z_Entry_termInfo;
1986 e->u.termInfo = t = (Z_TermInfo *)
1987 odr_malloc(assoc->encode, sizeof(*t));
1988 t->suggestedAttributes = 0;
1990 if (save_entries == bsrr->entries &&
1991 bsrr->entries[i].display_term)
1993 /* the entries was NOT set by the handler. So it's
1994 safe to test for new member display_term. It is
1997 t->displayTerm = odr_strdup(assoc->encode,
1998 bsrr->entries[i].display_term);
2000 t->alternativeTerm = 0;
2001 t->byAttributes = 0;
2002 t->otherTermInfo = 0;
2003 t->globalOccurrences = &bsrr->entries[i].occurrences;
2004 t->term = (Z_Term *)
2005 odr_malloc(assoc->encode, sizeof(*t->term));
2006 t->term->which = Z_Term_general;
2007 t->term->u.general = o =
2008 (Odr_oct *)odr_malloc(assoc->encode, sizeof(Odr_oct));
2009 o->buf = (unsigned char *)
2010 odr_malloc(assoc->encode, o->len = o->size =
2011 strlen(bsrr->entries[i].term));
2012 memcpy(o->buf, bsrr->entries[i].term, o->len);
2013 yaz_log(LOG_DEBUG, " term #%d: '%s' (%d)", i,
2014 bsrr->entries[i].term, bsrr->entries[i].occurrences);
2018 Z_DiagRecs *drecs = diagrecs (assoc,
2019 bsrr->entries[i].errcode,
2020 bsrr->entries[i].errstring);
2021 assert (drecs->num_diagRecs == 1);
2022 e->which = Z_Entry_surrogateDiagnostic;
2023 assert (drecs->diagRecs[0]);
2024 e->u.surrogateDiagnostic = drecs->diagRecs[0];
2030 ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs;
2031 ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs;
2036 static Z_APDU *process_sortRequest(association *assoc, request *reqb,
2039 Z_SortRequest *req = reqb->apdu_request->u.sortRequest;
2040 Z_SortResponse *res = (Z_SortResponse *)
2041 odr_malloc (assoc->encode, sizeof(*res));
2042 bend_sort_rr *bsrr = (bend_sort_rr *)
2043 odr_malloc (assoc->encode, sizeof(*bsrr));
2045 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2047 yaz_log(LOG_LOG, "Got SortRequest.");
2049 bsrr->num_input_setnames = req->num_inputResultSetNames;
2050 bsrr->input_setnames = req->inputResultSetNames;
2051 bsrr->referenceId = req->referenceId;
2052 bsrr->output_setname = req->sortedResultSetName;
2053 bsrr->sort_sequence = req->sortSequence;
2054 bsrr->stream = assoc->encode;
2055 bsrr->print = assoc->print;
2057 bsrr->sort_status = Z_SortResponse_failure;
2059 bsrr->errstring = 0;
2061 (*assoc->init->bend_sort)(assoc->backend, bsrr);
2063 res->referenceId = bsrr->referenceId;
2064 res->sortStatus = odr_intdup(assoc->encode, bsrr->sort_status);
2065 res->resultSetStatus = 0;
2068 Z_DiagRecs *dr = diagrecs (assoc, bsrr->errcode, bsrr->errstring);
2069 res->diagnostics = dr->diagRecs;
2070 res->num_diagnostics = dr->num_diagRecs;
2074 res->num_diagnostics = 0;
2075 res->diagnostics = 0;
2077 res->resultCount = 0;
2080 apdu->which = Z_APDU_sortResponse;
2081 apdu->u.sortResponse = res;
2085 static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
2088 Z_DeleteResultSetRequest *req =
2089 reqb->apdu_request->u.deleteResultSetRequest;
2090 Z_DeleteResultSetResponse *res = (Z_DeleteResultSetResponse *)
2091 odr_malloc (assoc->encode, sizeof(*res));
2092 bend_delete_rr *bdrr = (bend_delete_rr *)
2093 odr_malloc (assoc->encode, sizeof(*bdrr));
2094 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2096 yaz_log(LOG_LOG, "Got DeleteRequest.");
2098 bdrr->num_setnames = req->num_resultSetList;
2099 bdrr->setnames = req->resultSetList;
2100 bdrr->stream = assoc->encode;
2101 bdrr->print = assoc->print;
2102 bdrr->function = *req->deleteFunction;
2103 bdrr->referenceId = req->referenceId;
2105 if (bdrr->num_setnames > 0)
2108 bdrr->statuses = (int*)
2109 odr_malloc(assoc->encode, sizeof(*bdrr->statuses) *
2110 bdrr->num_setnames);
2111 for (i = 0; i < bdrr->num_setnames; i++)
2112 bdrr->statuses[i] = 0;
2114 (*assoc->init->bend_delete)(assoc->backend, bdrr);
2116 res->referenceId = req->referenceId;
2118 res->deleteOperationStatus = odr_intdup(assoc->encode,bdrr->delete_status);
2120 res->deleteListStatuses = 0;
2121 if (bdrr->num_setnames > 0)
2124 res->deleteListStatuses = (Z_ListStatuses *)
2125 odr_malloc(assoc->encode, sizeof(*res->deleteListStatuses));
2126 res->deleteListStatuses->num = bdrr->num_setnames;
2127 res->deleteListStatuses->elements =
2129 odr_malloc (assoc->encode,
2130 sizeof(*res->deleteListStatuses->elements) *
2131 bdrr->num_setnames);
2132 for (i = 0; i<bdrr->num_setnames; i++)
2134 res->deleteListStatuses->elements[i] =
2136 odr_malloc (assoc->encode,
2137 sizeof(**res->deleteListStatuses->elements));
2138 res->deleteListStatuses->elements[i]->status = bdrr->statuses+i;
2139 res->deleteListStatuses->elements[i]->id =
2140 odr_strdup (assoc->encode, bdrr->setnames[i]);
2144 res->numberNotDeleted = 0;
2145 res->bulkStatuses = 0;
2146 res->deleteMessage = 0;
2149 apdu->which = Z_APDU_deleteResultSetResponse;
2150 apdu->u.deleteResultSetResponse = res;
2154 static void process_close(association *assoc, request *reqb)
2156 Z_Close *req = reqb->apdu_request->u.close;
2157 static char *reasons[] =
2164 "securityViolation",
2171 yaz_log(LOG_LOG, "Got Close, reason %s, message %s",
2172 reasons[*req->closeReason], req->diagnosticInformation ?
2173 req->diagnosticInformation : "NULL");
2174 if (assoc->version < 3) /* to make do_force respond with close */
2176 do_close_req(assoc, Z_Close_finished,
2177 "Association terminated by client", reqb);
2180 void save_referenceId (request *reqb, Z_ReferenceId *refid)
2184 reqb->len_refid = refid->len;
2185 reqb->refid = (char *)nmem_malloc (reqb->request_mem, refid->len);
2186 memcpy (reqb->refid, refid->buf, refid->len);
2190 reqb->len_refid = 0;
2195 void bend_request_send (bend_association a, bend_request req, Z_APDU *res)
2197 process_z_response (a, req, res);
2200 bend_request bend_request_mk (bend_association a)
2202 request *nreq = request_get (&a->outgoing);
2203 nreq->request_mem = nmem_create ();
2207 Z_ReferenceId *bend_request_getid (ODR odr, bend_request req)
2212 id = (Odr_oct *)odr_malloc (odr, sizeof(*odr));
2213 id->buf = (unsigned char *)odr_malloc (odr, req->len_refid);
2214 id->len = id->size = req->len_refid;
2215 memcpy (id->buf, req->refid, req->len_refid);
2219 void bend_request_destroy (bend_request *req)
2221 nmem_destroy((*req)->request_mem);
2222 request_release(*req);
2226 int bend_backend_respond (bend_association a, bend_request req)
2230 r = process_z_request (a, req, &msg);
2232 yaz_log (LOG_WARN, "%s", msg);
2236 void bend_request_setdata(bend_request r, void *p)
2241 void *bend_request_getdata(bend_request r)
2243 return r->clientData;
2246 static Z_APDU *process_segmentRequest (association *assoc, request *reqb)
2248 bend_segment_rr req;
2250 req.segment = reqb->apdu_request->u.segmentRequest;
2251 req.stream = assoc->encode;
2252 req.decode = assoc->decode;
2253 req.print = assoc->print;
2254 req.association = assoc;
2256 (*assoc->init->bend_segment)(assoc->backend, &req);
2261 static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd)
2263 bend_esrequest_rr esrequest;
2265 Z_ExtendedServicesRequest *req =
2266 reqb->apdu_request->u.extendedServicesRequest;
2267 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_extendedServicesResponse);
2269 Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse;
2271 yaz_log(LOG_DEBUG,"inside Process esRequest");
2273 esrequest.esr = reqb->apdu_request->u.extendedServicesRequest;
2274 esrequest.stream = assoc->encode;
2275 esrequest.decode = assoc->decode;
2276 esrequest.print = assoc->print;
2277 esrequest.errcode = 0;
2278 esrequest.errstring = NULL;
2279 esrequest.request = reqb;
2280 esrequest.association = assoc;
2281 esrequest.taskPackage = 0;
2282 esrequest.referenceId = req->referenceId;
2284 (*assoc->init->bend_esrequest)(assoc->backend, &esrequest);
2286 /* If the response is being delayed, return NULL */
2287 if (esrequest.request == NULL)
2290 resp->referenceId = req->referenceId;
2292 if (esrequest.errcode == -1)
2294 /* Backend service indicates request will be processed */
2295 yaz_log(LOG_DEBUG,"Request could be processed...Accepted !");
2296 *resp->operationStatus = Z_ExtendedServicesResponse_accepted;
2298 else if (esrequest.errcode == 0)
2300 /* Backend service indicates request will be processed */
2301 yaz_log(LOG_DEBUG,"Request could be processed...Done !");
2302 *resp->operationStatus = Z_ExtendedServicesResponse_done;
2306 Z_DiagRecs *diagRecs = diagrecs (assoc, esrequest.errcode,
2307 esrequest.errstring);
2309 /* Backend indicates error, request will not be processed */
2310 yaz_log(LOG_DEBUG,"Request could not be processed...failure !");
2311 *resp->operationStatus = Z_ExtendedServicesResponse_failure;
2312 resp->num_diagnostics = diagRecs->num_diagRecs;
2313 resp->diagnostics = diagRecs->diagRecs;
2315 /* Do something with the members of bend_extendedservice */
2316 if (esrequest.taskPackage)
2317 resp->taskPackage = z_ext_record (assoc->encode, VAL_EXTENDED,
2318 (const char *) esrequest.taskPackage,
2320 yaz_log(LOG_DEBUG,"Send the result apdu");