2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: seshigh.c,v 1.27 2004-09-10 11:28:58 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);
655 yaz_log(LOG_DEBUG, "bend_search returned Bib-1 code %d", rr.errcode);
656 if (rr.errcode == 109) /* database unavailable */
661 srw_res->num_diagnostics = 1;
662 srw_res->diagnostics = (Z_SRW_diagnostic *)
663 odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
664 yaz_mk_std_diagnostic(assoc->encode, srw_res->diagnostics,
665 yaz_diag_bib1_to_srw (rr.errcode),
667 yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %s",
668 srw_res->diagnostics[0].uri);
672 int number = srw_req->maximumRecords ? *srw_req->maximumRecords : 0;
673 int start = srw_req->startRecord ? *srw_req->startRecord : 1;
675 yaz_log(LOG_LOG, "Request to pack %d+%d out of %d",
676 start, number, rr.hits);
678 srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits);
685 yaz_log(LOG_LOG, "Request out or range");
690 int packing = Z_SRW_recordPacking_string;
691 if (start + number > rr.hits)
692 number = rr.hits - start + 1;
693 if (srw_req->recordPacking &&
694 !strcmp(srw_req->recordPacking, "xml"))
695 packing = Z_SRW_recordPacking_XML;
696 srw_res->records = (Z_SRW_record *)
697 odr_malloc(assoc->encode,
698 number * sizeof(*srw_res->records));
699 for (i = 0; i<number; i++)
703 srw_res->records[j].recordPacking = packing;
704 srw_res->records[j].recordData_buf = 0;
705 yaz_log(LOG_DEBUG, "srw_bend_fetch %d", i+start);
706 errcode = srw_bend_fetch(assoc, i+start, srw_req,
707 srw_res->records + j);
710 srw_res->num_diagnostics = 1;
711 srw_res->diagnostics = (Z_SRW_diagnostic *)
712 odr_malloc(assoc->encode,
713 sizeof(*srw_res->diagnostics));
715 yaz_mk_std_diagnostic(assoc->encode,
716 srw_res->diagnostics,
717 yaz_diag_bib1_to_srw (errcode),
721 if (srw_res->records[j].recordData_buf)
724 srw_res->num_records = j;
726 srw_res->records = 0;
732 static void srw_bend_explain(association *assoc, request *req,
733 Z_SRW_explainRequest *srw_req,
734 Z_SRW_explainResponse *srw_res,
737 yaz_log(LOG_LOG, "Got SRW ExplainRequest");
741 yaz_log(LOG_DEBUG, "srw_bend_init");
742 if (!srw_bend_init(assoc))
747 if (assoc->init && assoc->init->bend_explain)
751 rr.stream = assoc->encode;
752 rr.decode = assoc->decode;
753 rr.print = assoc->print;
755 rr.database = srw_req->database;
756 rr.schema = "http://explain.z3950.org/dtd/2.0/";
757 (*assoc->init->bend_explain)(assoc->backend, &rr);
760 int packing = Z_SRW_recordPacking_string;
761 if (srw_req->recordPacking &&
762 !strcmp(srw_req->recordPacking, "xml"))
763 packing = Z_SRW_recordPacking_XML;
764 srw_res->record.recordSchema = 0;
765 srw_res->record.recordPacking = packing;
766 srw_res->record.recordData_buf = rr.explain_buf;
767 srw_res->record.recordData_len = strlen(rr.explain_buf);
768 srw_res->record.recordPosition = 0;
774 static void process_http_request(association *assoc, request *req)
776 Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request;
777 ODR o = assoc->encode;
778 int r = 2; /* 2=NOT TAKEN, 1=TAKEN, 0=SOAP TAKEN */
780 Z_SOAP *soap_package = 0;
783 Z_HTTP_Response *hres = 0;
785 char *stylesheet = 0;
786 Z_SRW_diagnostic *diagnostic = 0;
787 int num_diagnostic = 0;
789 if (!strcmp(hreq->path, "/test"))
791 p = z_get_HTTP_Response(o, 200);
792 hres = p->u.HTTP_Response;
793 hres->content_buf = "1234567890\n";
794 hres->content_len = strlen(hres->content_buf);
799 r = yaz_srw_decode(hreq, &sr, &soap_package, assoc->decode, &charset);
800 yaz_log(LOG_DEBUG, "yaz_srw_decode returned %d", r);
802 if (r == 2) /* not taken */
804 r = yaz_sru_decode(hreq, &sr, &soap_package, assoc->decode, &charset,
805 &diagnostic, &num_diagnostic);
806 yaz_log(LOG_DEBUG, "yaz_sru_decode returned %d", r);
808 if (r == 0) /* decode SRW/SRU OK .. */
811 if (sr->which == Z_SRW_searchRetrieve_request)
814 yaz_srw_get(assoc->encode, Z_SRW_searchRetrieve_response);
816 stylesheet = sr->u.request->stylesheet;
819 res->u.response->diagnostics = diagnostic;
820 res->u.response->num_diagnostics = num_diagnostic;
824 srw_bend_search(assoc, req, sr->u.request, res->u.response,
827 if (http_code == 200)
828 soap_package->u.generic->p = res;
830 else if (sr->which == Z_SRW_explain_request)
832 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_explain_response);
833 stylesheet = sr->u.explain_request->stylesheet;
836 res->u.explain_response->diagnostics = diagnostic;
837 res->u.explain_response->num_diagnostics = num_diagnostic;
839 srw_bend_explain(assoc, req, sr->u.explain_request,
840 res->u.explain_response, &http_code);
841 if (http_code == 200)
842 soap_package->u.generic->p = res;
844 else if (sr->which == Z_SRW_scan_request)
846 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_scan_response);
847 stylesheet = sr->u.scan_request->stylesheet;
850 res->u.scan_response->diagnostics = diagnostic;
851 res->u.scan_response->num_diagnostics = num_diagnostic;
853 yaz_add_srw_diagnostic(o,
854 &res->u.scan_response->diagnostics,
855 &res->u.scan_response->num_diagnostics,
857 if (http_code == 200)
858 soap_package->u.generic->p = res;
862 yaz_log(LOG_LOG, "generate soap error");
864 z_soap_error(assoc->encode, soap_package,
865 "SOAP-ENV:Client", "Bad method", 0);
867 if (http_code == 200 || http_code == 500)
869 static Z_SOAP_Handler soap_handlers[3] = {
871 {"http://www.loc.gov/zing/srw/", 0,
872 (Z_SOAP_fun) yaz_srw_codec},
873 {"http://www.loc.gov/zing/srw/v1.0/", 0,
874 (Z_SOAP_fun) yaz_srw_codec},
880 p = z_get_HTTP_Response(o, 200);
881 hres = p->u.HTTP_Response;
882 ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package,
883 &hres->content_buf, &hres->content_len,
884 soap_handlers, charset, stylesheet);
885 hres->code = http_code;
887 strcpy(ctype, "text/xml");
890 strcat(ctype, "; charset=");
891 strcat(ctype, charset);
893 z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
896 p = z_get_HTTP_Response(o, http_code);
900 p = z_get_HTTP_Response(o, 500);
901 hres = p->u.HTTP_Response;
902 if (!strcmp(hreq->version, "1.0"))
904 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
905 if (v && !strcmp(v, "Keep-Alive"))
909 hres->version = "1.0";
913 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
914 if (v && !strcmp(v, "close"))
918 hres->version = "1.1";
922 z_HTTP_header_add(o, &hres->headers, "Connection", "close");
923 assoc->state = ASSOC_DEAD;
924 assoc->cs_get_mask = 0;
929 const char *alive = z_HTTP_header_lookup(hreq->headers, "Keep-Alive");
931 if (alive && isdigit(*alive))
935 if (t < 0 || t > 3600)
937 iochan_settimeout(assoc->client_chan,t);
938 z_HTTP_header_add(o, &hres->headers, "Connection", "Keep-Alive");
940 process_gdu_response(assoc, req, p);
943 static void process_gdu_request(association *assoc, request *req)
945 if (req->gdu_request->which == Z_GDU_Z3950)
948 req->apdu_request = req->gdu_request->u.z3950;
949 if (process_z_request(assoc, req, &msg) < 0)
950 do_close_req(assoc, Z_Close_systemProblem, msg, req);
952 else if (req->gdu_request->which == Z_GDU_HTTP_Request)
953 process_http_request(assoc, req);
956 do_close_req(assoc, Z_Close_systemProblem, "bad protocol packet", req);
961 * Initiate request processing.
963 static int process_z_request(association *assoc, request *req, char **msg)
969 *msg = "Unknown Error";
970 assert(req && req->state == REQUEST_IDLE);
971 if (req->apdu_request->which != Z_APDU_initRequest && !assoc->init)
973 *msg = "Missing InitRequest";
976 switch (req->apdu_request->which)
978 case Z_APDU_initRequest:
979 iochan_settimeout(assoc->client_chan,
980 statserv_getcontrol()->idle_timeout * 60);
981 res = process_initRequest(assoc, req); break;
982 case Z_APDU_searchRequest:
983 res = process_searchRequest(assoc, req, &fd); break;
984 case Z_APDU_presentRequest:
985 res = process_presentRequest(assoc, req, &fd); break;
986 case Z_APDU_scanRequest:
987 if (assoc->init->bend_scan)
988 res = process_scanRequest(assoc, req, &fd);
991 *msg = "Cannot handle Scan APDU";
995 case Z_APDU_extendedServicesRequest:
996 if (assoc->init->bend_esrequest)
997 res = process_ESRequest(assoc, req, &fd);
1000 *msg = "Cannot handle Extended Services APDU";
1004 case Z_APDU_sortRequest:
1005 if (assoc->init->bend_sort)
1006 res = process_sortRequest(assoc, req, &fd);
1009 *msg = "Cannot handle Sort APDU";
1014 process_close(assoc, req);
1016 case Z_APDU_deleteResultSetRequest:
1017 if (assoc->init->bend_delete)
1018 res = process_deleteRequest(assoc, req, &fd);
1021 *msg = "Cannot handle Delete APDU";
1025 case Z_APDU_segmentRequest:
1026 if (assoc->init->bend_segment)
1028 res = process_segmentRequest (assoc, req);
1032 *msg = "Cannot handle Segment APDU";
1036 case Z_APDU_triggerResourceControlRequest:
1039 *msg = "Bad APDU received";
1044 yaz_log(LOG_DEBUG, " result immediately available");
1045 retval = process_z_response(assoc, req, res);
1049 yaz_log(LOG_DEBUG, " result unavailble");
1052 else /* no result yet - one will be provided later */
1056 /* Set up an I/O handler for the fd supplied by the backend */
1058 yaz_log(LOG_DEBUG, " establishing handler for result");
1059 req->state = REQUEST_PENDING;
1060 if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT)))
1062 iochan_setdata(chan, assoc);
1069 * Handle message from the backend.
1071 void backend_response(IOCHAN i, int event)
1073 association *assoc = (association *)iochan_getdata(i);
1074 request *req = request_head(&assoc->incoming);
1078 yaz_log(LOG_DEBUG, "backend_response");
1079 assert(assoc && req && req->state != REQUEST_IDLE);
1080 /* determine what it is we're waiting for */
1081 switch (req->apdu_request->which)
1083 case Z_APDU_searchRequest:
1084 res = response_searchRequest(assoc, req, 0, &fd); break;
1086 case Z_APDU_presentRequest:
1087 res = response_presentRequest(assoc, req, 0, &fd); break;
1088 case Z_APDU_scanRequest:
1089 res = response_scanRequest(assoc, req, 0, &fd); break;
1092 yaz_log(LOG_WARN, "Serious programmer's lapse or bug");
1095 if ((res && process_z_response(assoc, req, res) < 0) || fd < 0)
1097 yaz_log(LOG_LOG, "Fatal error when talking to backend");
1098 do_close(assoc, Z_Close_systemProblem, 0);
1102 else if (!res) /* no result yet - try again later */
1104 yaz_log(LOG_DEBUG, " no result yet");
1105 iochan_setfd(i, fd); /* in case fd has changed */
1110 * Encode response, and transfer the request structure to the outgoing queue.
1112 static int process_gdu_response(association *assoc, request *req, Z_GDU *res)
1114 odr_setbuf(assoc->encode, req->response, req->size_response, 1);
1118 if (!z_GDU(assoc->print, &res, 0, 0))
1119 yaz_log(LOG_WARN, "ODR print error: %s",
1120 odr_errmsg(odr_geterror(assoc->print)));
1121 odr_reset(assoc->print);
1123 if (!z_GDU(assoc->encode, &res, 0, 0))
1125 yaz_log(LOG_WARN, "ODR error when encoding PDU: %s [element %s]",
1126 odr_errmsg(odr_geterror(assoc->decode)),
1127 odr_getelement(assoc->decode));
1128 request_release(req);
1131 req->response = odr_getbuf(assoc->encode, &req->len_response,
1132 &req->size_response);
1133 odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */
1134 odr_reset(assoc->encode);
1135 req->state = REQUEST_IDLE;
1136 request_enq(&assoc->outgoing, req);
1137 /* turn the work over to the ir_session handler */
1138 iochan_setflag(assoc->client_chan, EVENT_OUTPUT);
1139 assoc->cs_put_mask = EVENT_OUTPUT;
1140 /* Is there more work to be done? give that to the input handler too */
1142 if (request_head(&assoc->incoming))
1144 yaz_log (LOG_DEBUG, "more work to be done");
1145 iochan_setevent(assoc->client_chan, EVENT_WORK);
1152 * Encode response, and transfer the request structure to the outgoing queue.
1154 static int process_z_response(association *assoc, request *req, Z_APDU *res)
1156 Z_GDU *gres = (Z_GDU *) odr_malloc(assoc->encode, sizeof(*res));
1157 gres->which = Z_GDU_Z3950;
1158 gres->u.z3950 = res;
1160 return process_gdu_response(assoc, req, gres);
1165 * Handle init request.
1166 * At the moment, we don't check the options
1167 * anywhere else in the code - we just try not to do anything that would
1168 * break a naive client. We'll toss 'em into the association block when
1169 * we need them there.
1171 static Z_APDU *process_initRequest(association *assoc, request *reqb)
1173 statserv_options_block *cb = statserv_getcontrol();
1174 Z_InitRequest *req = reqb->apdu_request->u.initRequest;
1175 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_initResponse);
1176 Z_InitResponse *resp = apdu->u.initResponse;
1177 bend_initresult *binitres;
1181 yaz_log(LOG_LOG, "Got initRequest");
1182 if (req->implementationId)
1183 yaz_log(LOG_LOG, "Id: %s", req->implementationId);
1184 if (req->implementationName)
1185 yaz_log(LOG_LOG, "Name: %s", req->implementationName);
1186 if (req->implementationVersion)
1187 yaz_log(LOG_LOG, "Version: %s", req->implementationVersion);
1189 assoc_init_reset(assoc);
1191 assoc->init->auth = req->idAuthentication;
1192 assoc->init->referenceId = req->referenceId;
1194 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
1196 Z_CharSetandLanguageNegotiation *negotiation =
1197 yaz_get_charneg_record (req->otherInfo);
1199 negotiation->which == Z_CharSetandLanguageNegotiation_proposal)
1200 assoc->init->charneg_request = negotiation;
1204 if (!(binitres = (*cb->bend_init)(assoc->init)))
1206 yaz_log(LOG_WARN, "Bad response from backend.");
1210 assoc->backend = binitres->handle;
1211 if ((assoc->init->bend_sort))
1212 yaz_log (LOG_DEBUG, "Sort handler installed");
1213 if ((assoc->init->bend_search))
1214 yaz_log (LOG_DEBUG, "Search handler installed");
1215 if ((assoc->init->bend_present))
1216 yaz_log (LOG_DEBUG, "Present handler installed");
1217 if ((assoc->init->bend_esrequest))
1218 yaz_log (LOG_DEBUG, "ESRequest handler installed");
1219 if ((assoc->init->bend_delete))
1220 yaz_log (LOG_DEBUG, "Delete handler installed");
1221 if ((assoc->init->bend_scan))
1222 yaz_log (LOG_DEBUG, "Scan handler installed");
1223 if ((assoc->init->bend_segment))
1224 yaz_log (LOG_DEBUG, "Segment handler installed");
1226 resp->referenceId = req->referenceId;
1228 /* let's tell the client what we can do */
1229 if (ODR_MASK_GET(req->options, Z_Options_search))
1231 ODR_MASK_SET(resp->options, Z_Options_search);
1232 strcat(options, "srch");
1234 if (ODR_MASK_GET(req->options, Z_Options_present))
1236 ODR_MASK_SET(resp->options, Z_Options_present);
1237 strcat(options, " prst");
1239 if (ODR_MASK_GET(req->options, Z_Options_delSet) &&
1240 assoc->init->bend_delete)
1242 ODR_MASK_SET(resp->options, Z_Options_delSet);
1243 strcat(options, " del");
1245 if (ODR_MASK_GET(req->options, Z_Options_extendedServices) &&
1246 assoc->init->bend_esrequest)
1248 ODR_MASK_SET(resp->options, Z_Options_extendedServices);
1249 strcat (options, " extendedServices");
1251 if (ODR_MASK_GET(req->options, Z_Options_namedResultSets))
1253 ODR_MASK_SET(resp->options, Z_Options_namedResultSets);
1254 strcat(options, " namedresults");
1256 if (ODR_MASK_GET(req->options, Z_Options_scan) && assoc->init->bend_scan)
1258 ODR_MASK_SET(resp->options, Z_Options_scan);
1259 strcat(options, " scan");
1261 if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations))
1263 ODR_MASK_SET(resp->options, Z_Options_concurrentOperations);
1264 strcat(options, " concurrop");
1266 if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort)
1268 ODR_MASK_SET(resp->options, Z_Options_sort);
1269 strcat(options, " sort");
1272 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)
1273 && assoc->init->charneg_response)
1275 Z_OtherInformation **p;
1276 Z_OtherInformationUnit *p0;
1278 yaz_oi_APDU(apdu, &p);
1280 if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) {
1281 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1283 p0->which = Z_OtherInfo_externallyDefinedInfo;
1284 p0->information.externallyDefinedInfo =
1285 assoc->init->charneg_response;
1287 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1288 strcat(options, " negotiation");
1291 ODR_MASK_SET(resp->options, Z_Options_triggerResourceCtrl);
1293 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
1295 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
1296 assoc->version = 1; /* 1 & 2 are equivalent */
1298 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
1300 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
1303 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
1305 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
1309 yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options);
1310 assoc->maximumRecordSize = *req->maximumRecordSize;
1311 if (assoc->maximumRecordSize > control_block->maxrecordsize)
1312 assoc->maximumRecordSize = control_block->maxrecordsize;
1313 assoc->preferredMessageSize = *req->preferredMessageSize;
1314 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
1315 assoc->preferredMessageSize = assoc->maximumRecordSize;
1317 resp->preferredMessageSize = &assoc->preferredMessageSize;
1318 resp->maximumRecordSize = &assoc->maximumRecordSize;
1320 resp->implementationId = odr_prepend(assoc->encode,
1321 assoc->init->implementation_id,
1322 resp->implementationId);
1324 resp->implementationName = odr_prepend(assoc->encode,
1325 assoc->init->implementation_name,
1326 odr_prepend(assoc->encode, "GFS", resp->implementationName));
1328 version = odr_strdup(assoc->encode, "$Revision: 1.27 $");
1329 if (strlen(version) > 10) /* check for unexpanded CVS strings */
1330 version[strlen(version)-2] = '\0';
1331 resp->implementationVersion = odr_prepend(assoc->encode,
1332 assoc->init->implementation_version,
1333 odr_prepend(assoc->encode, &version[11],
1334 resp->implementationVersion));
1336 if (binitres->errcode)
1338 yaz_log(LOG_LOG, "Connection rejected by backend.");
1340 assoc->state = ASSOC_DEAD;
1341 resp->userInformationField = init_diagnostics(assoc->encode,
1343 binitres->errstring);
1346 assoc->state = ASSOC_UP;
1351 * Diagnostic in default format, to be returned as either a surrogate
1352 * or non-surrogate diagnostic in the context of an open session, or
1353 * as User-information when an Init is refused.
1355 static Z_DefaultDiagFormat *justdiag(ODR odr, int error, char *addinfo)
1357 int *err = odr_intdup(odr, error);
1358 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
1359 odr_malloc (odr, sizeof(*dr));
1361 yaz_log(LOG_LOG, "[%d] %s%s%s", error, diagbib1_str(error),
1362 addinfo ? " -- " : "", addinfo ? addinfo : "");
1364 dr->diagnosticSetId =
1365 yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1);
1366 dr->condition = err;
1367 dr->which = Z_DefaultDiagFormat_v2Addinfo;
1368 dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
1373 * Set the specified `errcode' and `errstring' into a UserInfo-1
1374 * external to be returned to the client in accordance with Z35.90
1375 * Implementor Agreement 5 (Returning diagnostics in an InitResponse):
1376 * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html
1378 static Z_External *init_diagnostics(ODR odr, int error, char *addinfo)
1382 Z_OtherInformation *u;
1383 Z_OtherInformationUnit *l;
1384 Z_DiagnosticFormat *d;
1385 Z_DiagnosticFormat_s *e;
1387 x = (Z_External*) odr_malloc(odr, sizeof *x);
1389 x->indirect_reference = 0;
1390 oid.proto = PROTO_Z3950;
1391 oid.oclass = CLASS_USERINFO;
1392 oid.value = VAL_USERINFO1;
1393 x->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1394 x->which = Z_External_userInfo1;
1396 u = odr_malloc(odr, sizeof *u);
1398 u->num_elements = 1;
1399 u->list = (Z_OtherInformationUnit**) odr_malloc(odr, sizeof *u->list);
1400 u->list[0] = (Z_OtherInformationUnit*) odr_malloc(odr, sizeof *u->list[0]);
1403 l->which = Z_OtherInfo_externallyDefinedInfo;
1405 x2 = (Z_External*) odr_malloc(odr, sizeof *x);
1406 l->information.externallyDefinedInfo = x2;
1408 x2->indirect_reference = 0;
1409 oid.oclass = CLASS_DIAGSET;
1410 oid.value = VAL_DIAG1;
1411 x2->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1412 x2->which = Z_External_diag1;
1414 d = (Z_DiagnosticFormat*) odr_malloc(odr, sizeof *d);
1417 d->elements = (Z_DiagnosticFormat_s**) odr_malloc (odr, sizeof *d->elements);
1418 d->elements[0] = (Z_DiagnosticFormat_s*) odr_malloc (odr, sizeof *d->elements[0]);
1421 e->which = Z_DiagnosticFormat_s_defaultDiagRec;
1422 e->u.defaultDiagRec = justdiag(odr, error, addinfo);
1428 * nonsurrogate diagnostic record.
1430 static Z_Records *diagrec(association *assoc, int error, char *addinfo)
1432 Z_Records *rec = (Z_Records *)
1433 odr_malloc (assoc->encode, sizeof(*rec));
1434 rec->which = Z_Records_NSD;
1435 rec->u.nonSurrogateDiagnostic = justdiag(assoc->encode, error, addinfo);
1440 * surrogate diagnostic.
1442 static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname,
1443 int error, char *addinfo)
1445 Z_NamePlusRecord *rec = (Z_NamePlusRecord *)
1446 odr_malloc (assoc->encode, sizeof(*rec));
1447 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1449 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
1450 rec->databaseName = dbname;
1451 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
1452 rec->u.surrogateDiagnostic = drec;
1453 drec->which = Z_DiagRec_defaultFormat;
1454 drec->u.defaultFormat = justdiag(assoc->encode, error, addinfo);
1460 * multiple nonsurrogate diagnostics.
1462 static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo)
1464 Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs));
1465 int *err = odr_intdup(assoc->encode, error);
1466 Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp));
1467 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1468 Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *)
1469 odr_malloc (assoc->encode, sizeof(*rec));
1471 yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : "");
1473 recs->num_diagRecs = 1;
1474 recs->diagRecs = recp;
1476 drec->which = Z_DiagRec_defaultFormat;
1477 drec->u.defaultFormat = rec;
1479 rec->diagnosticSetId =
1480 yaz_oidval_to_z3950oid (assoc->encode, CLASS_DIAGSET, VAL_BIB1);
1481 rec->condition = err;
1483 rec->which = Z_DefaultDiagFormat_v2Addinfo;
1484 rec->u.v2Addinfo = odr_strdup (assoc->encode, addinfo ? addinfo : "");
1488 static Z_Records *pack_records(association *a, char *setname, int start,
1489 int *num, Z_RecordComposition *comp,
1490 int *next, int *pres, oid_value format,
1491 Z_ReferenceId *referenceId,
1494 int recno, total_length = 0, toget = *num, dumped_records = 0;
1495 Z_Records *records =
1496 (Z_Records *) odr_malloc (a->encode, sizeof(*records));
1497 Z_NamePlusRecordList *reclist =
1498 (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist));
1499 Z_NamePlusRecord **list =
1500 (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget);
1502 records->which = Z_Records_DBOSD;
1503 records->u.databaseOrSurDiagnostics = reclist;
1504 reclist->num_records = 0;
1505 reclist->records = list;
1506 *pres = Z_PresentStatus_success;
1510 yaz_log(LOG_LOG, "Request to pack %d+%d+%s", start, toget, setname);
1511 yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize,
1512 a->maximumRecordSize);
1513 for (recno = start; reclist->num_records < toget; recno++)
1516 Z_NamePlusRecord *thisrec;
1517 int this_length = 0;
1519 * we get the number of bytes allocated on the stream before any
1520 * allocation done by the backend - this should give us a reasonable
1521 * idea of the total size of the data so far.
1523 total_length = odr_total(a->encode) - dumped_records;
1529 freq.last_in_set = 0;
1530 freq.setname = setname;
1531 freq.surrogate_flag = 0;
1532 freq.number = recno;
1534 freq.request_format = format;
1535 freq.request_format_raw = oid;
1536 freq.output_format = format;
1537 freq.output_format_raw = 0;
1538 freq.stream = a->encode;
1539 freq.print = a->print;
1540 freq.referenceId = referenceId;
1542 (*a->init->bend_fetch)(a->backend, &freq);
1543 /* backend should be able to signal whether error is system-wide
1544 or only pertaining to current record */
1547 if (!freq.surrogate_flag)
1550 *pres = Z_PresentStatus_failure;
1551 /* for 'present request out of range',
1552 set addinfo to record position if not set */
1553 if (freq.errcode == 13 && freq.errstring == 0)
1555 sprintf (s, "%d", recno);
1558 return diagrec(a, freq.errcode, freq.errstring);
1560 reclist->records[reclist->num_records] =
1561 surrogatediagrec(a, freq.basename, freq.errcode,
1563 reclist->num_records++;
1564 *next = freq.last_in_set ? 0 : recno + 1;
1568 this_length = freq.len;
1570 this_length = odr_total(a->encode) - total_length - dumped_records;
1571 yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d dumped=%d",
1572 this_length, total_length, dumped_records);
1573 if (a->preferredMessageSize > 0 &&
1574 this_length + total_length > a->preferredMessageSize)
1576 /* record is small enough, really */
1577 if (this_length <= a->preferredMessageSize && recno > start)
1579 yaz_log(LOG_DEBUG, " Dropped last normal-sized record");
1580 *pres = Z_PresentStatus_partial_2;
1583 /* record can only be fetched by itself */
1584 if (this_length < a->maximumRecordSize)
1586 yaz_log(LOG_DEBUG, " Record > prefmsgsz");
1589 yaz_log(LOG_DEBUG, " Dropped it");
1590 reclist->records[reclist->num_records] =
1591 surrogatediagrec(a, freq.basename, 16, 0);
1592 reclist->num_records++;
1593 *next = freq.last_in_set ? 0 : recno + 1;
1594 dumped_records += this_length;
1598 else /* too big entirely */
1600 yaz_log(LOG_LOG, "Record > maxrcdsz this=%d max=%d", this_length, a->maximumRecordSize);
1601 reclist->records[reclist->num_records] =
1602 surrogatediagrec(a, freq.basename, 17, 0);
1603 reclist->num_records++;
1604 *next = freq.last_in_set ? 0 : recno + 1;
1605 dumped_records += this_length;
1610 if (!(thisrec = (Z_NamePlusRecord *)
1611 odr_malloc(a->encode, sizeof(*thisrec))))
1613 if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
1614 strlen(freq.basename) + 1)))
1616 strcpy(thisrec->databaseName, freq.basename);
1617 thisrec->which = Z_NamePlusRecord_databaseRecord;
1619 if (freq.output_format_raw)
1621 struct oident *ident = oid_getentbyoid(freq.output_format_raw);
1622 freq.output_format = ident->value;
1624 thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format,
1625 freq.record, freq.len);
1626 if (!thisrec->u.databaseRecord)
1628 reclist->records[reclist->num_records] = thisrec;
1629 reclist->num_records++;
1630 *next = freq.last_in_set ? 0 : recno + 1;
1632 *num = reclist->num_records;
1636 static Z_APDU *process_searchRequest(association *assoc, request *reqb,
1639 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1640 bend_search_rr *bsrr =
1641 (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr));
1643 yaz_log(LOG_LOG, "Got SearchRequest.");
1645 bsrr->request = reqb;
1646 bsrr->association = assoc;
1647 bsrr->referenceId = req->referenceId;
1648 save_referenceId (reqb, bsrr->referenceId);
1650 yaz_log (LOG_LOG, "ResultSet '%s'", req->resultSetName);
1651 if (req->databaseNames)
1654 for (i = 0; i < req->num_databaseNames; i++)
1655 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1657 yaz_log_zquery(req->query);
1659 if (assoc->init->bend_search)
1661 bsrr->setname = req->resultSetName;
1662 bsrr->replace_set = *req->replaceIndicator;
1663 bsrr->num_bases = req->num_databaseNames;
1664 bsrr->basenames = req->databaseNames;
1665 bsrr->query = req->query;
1666 bsrr->stream = assoc->encode;
1667 nmem_transfer(bsrr->stream->mem, reqb->request_mem);
1668 bsrr->decode = assoc->decode;
1669 bsrr->print = assoc->print;
1672 bsrr->errstring = NULL;
1673 bsrr->search_info = NULL;
1674 (assoc->init->bend_search)(assoc->backend, bsrr);
1678 return response_searchRequest(assoc, reqb, bsrr, fd);
1681 int bend_searchresponse(void *handle, bend_search_rr *bsrr) {return 0;}
1684 * Prepare a searchresponse based on the backend results. We probably want
1685 * to look at making the fetching of records nonblocking as well, but
1686 * so far, we'll keep things simple.
1687 * If bsrt is null, that means we're called in response to a communications
1688 * event, and we'll have to get the response for ourselves.
1690 static Z_APDU *response_searchRequest(association *assoc, request *reqb,
1691 bend_search_rr *bsrt, int *fd)
1693 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1694 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1695 Z_SearchResponse *resp = (Z_SearchResponse *)
1696 odr_malloc (assoc->encode, sizeof(*resp));
1697 int *nulint = odr_intdup (assoc->encode, 0);
1698 bool_t *sr = odr_intdup(assoc->encode, 1);
1699 int *next = odr_intdup(assoc->encode, 0);
1700 int *none = odr_intdup(assoc->encode, Z_SearchResponse_none);
1702 apdu->which = Z_APDU_searchResponse;
1703 apdu->u.searchResponse = resp;
1704 resp->referenceId = req->referenceId;
1705 resp->additionalSearchInfo = 0;
1706 resp->otherInfo = 0;
1708 if (!bsrt && !bend_searchresponse(assoc->backend, bsrt))
1710 yaz_log(LOG_FATAL, "Bad result from backend");
1713 else if (bsrt->errcode)
1715 resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring);
1716 resp->resultCount = nulint;
1717 resp->numberOfRecordsReturned = nulint;
1718 resp->nextResultSetPosition = nulint;
1719 resp->searchStatus = nulint;
1720 resp->resultSetStatus = none;
1721 resp->presentStatus = 0;
1725 int *toget = odr_intdup(assoc->encode, 0);
1726 int *presst = odr_intdup(assoc->encode, 0);
1727 Z_RecordComposition comp, *compp = 0;
1729 yaz_log (LOG_LOG, "resultCount: %d", bsrt->hits);
1732 resp->resultCount = &bsrt->hits;
1734 comp.which = Z_RecordComp_simple;
1735 /* how many records does the user agent want, then? */
1736 if (bsrt->hits <= *req->smallSetUpperBound)
1738 *toget = bsrt->hits;
1739 if ((comp.u.simple = req->smallSetElementSetNames))
1742 else if (bsrt->hits < *req->largeSetLowerBound)
1744 *toget = *req->mediumSetPresentNumber;
1745 if (*toget > bsrt->hits)
1746 *toget = bsrt->hits;
1747 if ((comp.u.simple = req->mediumSetElementSetNames))
1753 if (*toget && !resp->records)
1758 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1761 form = prefformat->value;
1762 resp->records = pack_records(assoc, req->resultSetName, 1,
1763 toget, compp, next, presst, form, req->referenceId,
1764 req->preferredRecordSyntax);
1767 resp->numberOfRecordsReturned = toget;
1768 resp->nextResultSetPosition = next;
1769 resp->searchStatus = sr;
1770 resp->resultSetStatus = 0;
1771 resp->presentStatus = presst;
1775 if (*resp->resultCount)
1777 resp->numberOfRecordsReturned = nulint;
1778 resp->nextResultSetPosition = next;
1779 resp->searchStatus = sr;
1780 resp->resultSetStatus = 0;
1781 resp->presentStatus = 0;
1784 resp->additionalSearchInfo = bsrt->search_info;
1789 * Maybe we got a little over-friendly when we designed bend_fetch to
1790 * get only one record at a time. Some backends can optimise multiple-record
1791 * fetches, and at any rate, there is some overhead involved in
1792 * all that selecting and hopping around. Problem is, of course, that the
1793 * frontend can't know ahead of time how many records it'll need to
1794 * fill the negotiated PDU size. Annoying. Segmentation or not, Z/SR
1795 * is downright lousy as a bulk data transfer protocol.
1797 * To start with, we'll do the fetching of records from the backend
1798 * in one operation: To save some trips in and out of the event-handler,
1799 * and to simplify the interface to pack_records. At any rate, asynch
1800 * operation is more fun in operations that have an unpredictable execution
1801 * speed - which is normally more true for search than for present.
1803 static Z_APDU *process_presentRequest(association *assoc, request *reqb,
1806 Z_PresentRequest *req = reqb->apdu_request->u.presentRequest;
1810 Z_PresentResponse *resp;
1814 yaz_log(LOG_LOG, "Got PresentRequest.");
1816 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1819 form = prefformat->value;
1820 resp = (Z_PresentResponse *)odr_malloc (assoc->encode, sizeof(*resp));
1822 resp->presentStatus = odr_intdup(assoc->encode, 0);
1823 if (assoc->init->bend_present)
1825 bend_present_rr *bprr = (bend_present_rr *)
1826 nmem_malloc (reqb->request_mem, sizeof(*bprr));
1827 bprr->setname = req->resultSetId;
1828 bprr->start = *req->resultSetStartPoint;
1829 bprr->number = *req->numberOfRecordsRequested;
1830 bprr->format = form;
1831 bprr->comp = req->recordComposition;
1832 bprr->referenceId = req->referenceId;
1833 bprr->stream = assoc->encode;
1834 bprr->print = assoc->print;
1835 bprr->request = reqb;
1836 bprr->association = assoc;
1838 bprr->errstring = NULL;
1839 (*assoc->init->bend_present)(assoc->backend, bprr);
1845 resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
1846 *resp->presentStatus = Z_PresentStatus_failure;
1849 apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1850 next = odr_intdup(assoc->encode, 0);
1851 num = odr_intdup(assoc->encode, 0);
1853 apdu->which = Z_APDU_presentResponse;
1854 apdu->u.presentResponse = resp;
1855 resp->referenceId = req->referenceId;
1856 resp->otherInfo = 0;
1860 *num = *req->numberOfRecordsRequested;
1862 pack_records(assoc, req->resultSetId, *req->resultSetStartPoint,
1863 num, req->recordComposition, next, resp->presentStatus,
1864 form, req->referenceId, req->preferredRecordSyntax);
1868 resp->numberOfRecordsReturned = num;
1869 resp->nextResultSetPosition = next;
1875 * Scan was implemented rather in a hurry, and with support for only the basic
1876 * elements of the service in the backend API. Suggestions are welcome.
1878 static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd)
1880 Z_ScanRequest *req = reqb->apdu_request->u.scanRequest;
1881 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1882 Z_ScanResponse *res = (Z_ScanResponse *)
1883 odr_malloc (assoc->encode, sizeof(*res));
1884 int *scanStatus = odr_intdup(assoc->encode, Z_Scan_failure);
1885 int *numberOfEntriesReturned = odr_intdup(assoc->encode, 0);
1886 Z_ListEntries *ents = (Z_ListEntries *)
1887 odr_malloc (assoc->encode, sizeof(*ents));
1888 Z_DiagRecs *diagrecs_p = NULL;
1890 bend_scan_rr *bsrr = (bend_scan_rr *)
1891 odr_malloc (assoc->encode, sizeof(*bsrr));
1892 struct scan_entry *save_entries;
1894 yaz_log(LOG_LOG, "Got ScanRequest");
1896 apdu->which = Z_APDU_scanResponse;
1897 apdu->u.scanResponse = res;
1898 res->referenceId = req->referenceId;
1900 /* if step is absent, set it to 0 */
1901 res->stepSize = odr_intdup(assoc->encode, 0);
1903 *res->stepSize = *req->stepSize;
1905 res->scanStatus = scanStatus;
1906 res->numberOfEntriesReturned = numberOfEntriesReturned;
1907 res->positionOfTerm = 0;
1908 res->entries = ents;
1909 ents->num_entries = 0;
1910 ents->entries = NULL;
1911 ents->num_nonsurrogateDiagnostics = 0;
1912 ents->nonsurrogateDiagnostics = NULL;
1913 res->attributeSet = 0;
1916 if (req->databaseNames)
1919 for (i = 0; i < req->num_databaseNames; i++)
1920 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1922 bsrr->num_bases = req->num_databaseNames;
1923 bsrr->basenames = req->databaseNames;
1924 bsrr->num_entries = *req->numberOfTermsRequested;
1925 bsrr->term = req->termListAndStartPoint;
1926 bsrr->referenceId = req->referenceId;
1927 bsrr->stream = assoc->encode;
1928 bsrr->print = assoc->print;
1929 bsrr->step_size = res->stepSize;
1931 /* Note that version 2.0 of YAZ and older did not set entries ..
1932 We do now. And when we do it's easier to extend the scan entry
1933 We know that if the scan handler did set entries, it will
1934 not know of new member display_term.
1936 if (bsrr->num_entries > 0)
1939 bsrr->entries = odr_malloc(assoc->decode, sizeof(*bsrr->entries) *
1941 for (i = 0; i<bsrr->num_entries; i++)
1943 bsrr->entries[i].term = 0;
1944 bsrr->entries[i].occurrences = 0;
1945 bsrr->entries[i].errcode = 0;
1946 bsrr->entries[i].errstring = 0;
1947 bsrr->entries[i].display_term = 0;
1950 save_entries = bsrr->entries; /* save it so we can compare later */
1952 if (req->attributeSet &&
1953 (attset = oid_getentbyoid(req->attributeSet)) &&
1954 (attset->oclass == CLASS_ATTSET || attset->oclass == CLASS_GENERAL))
1955 bsrr->attributeset = attset->value;
1957 bsrr->attributeset = VAL_NONE;
1958 log_scan_term (req->termListAndStartPoint, bsrr->attributeset);
1959 bsrr->term_position = req->preferredPositionInResponse ?
1960 *req->preferredPositionInResponse : 1;
1961 ((int (*)(void *, bend_scan_rr *))
1962 (*assoc->init->bend_scan))(assoc->backend, bsrr);
1964 diagrecs_p = diagrecs(assoc, bsrr->errcode, bsrr->errstring);
1968 Z_Entry **tab = (Z_Entry **)
1969 odr_malloc (assoc->encode, sizeof(*tab) * bsrr->num_entries);
1971 if (bsrr->status == BEND_SCAN_PARTIAL)
1972 *scanStatus = Z_Scan_partial_5;
1974 *scanStatus = Z_Scan_success;
1975 ents->entries = tab;
1976 ents->num_entries = bsrr->num_entries;
1977 res->numberOfEntriesReturned = &ents->num_entries;
1978 res->positionOfTerm = &bsrr->term_position;
1979 for (i = 0; i < bsrr->num_entries; i++)
1985 tab[i] = e = (Z_Entry *)odr_malloc(assoc->encode, sizeof(*e));
1986 if (bsrr->entries[i].occurrences >= 0)
1988 e->which = Z_Entry_termInfo;
1989 e->u.termInfo = t = (Z_TermInfo *)
1990 odr_malloc(assoc->encode, sizeof(*t));
1991 t->suggestedAttributes = 0;
1993 if (save_entries == bsrr->entries &&
1994 bsrr->entries[i].display_term)
1996 /* the entries was NOT set by the handler. So it's
1997 safe to test for new member display_term. It is
2000 t->displayTerm = odr_strdup(assoc->encode,
2001 bsrr->entries[i].display_term);
2003 t->alternativeTerm = 0;
2004 t->byAttributes = 0;
2005 t->otherTermInfo = 0;
2006 t->globalOccurrences = &bsrr->entries[i].occurrences;
2007 t->term = (Z_Term *)
2008 odr_malloc(assoc->encode, sizeof(*t->term));
2009 t->term->which = Z_Term_general;
2010 t->term->u.general = o =
2011 (Odr_oct *)odr_malloc(assoc->encode, sizeof(Odr_oct));
2012 o->buf = (unsigned char *)
2013 odr_malloc(assoc->encode, o->len = o->size =
2014 strlen(bsrr->entries[i].term));
2015 memcpy(o->buf, bsrr->entries[i].term, o->len);
2016 yaz_log(LOG_DEBUG, " term #%d: '%s' (%d)", i,
2017 bsrr->entries[i].term, bsrr->entries[i].occurrences);
2021 Z_DiagRecs *drecs = diagrecs (assoc,
2022 bsrr->entries[i].errcode,
2023 bsrr->entries[i].errstring);
2024 assert (drecs->num_diagRecs == 1);
2025 e->which = Z_Entry_surrogateDiagnostic;
2026 assert (drecs->diagRecs[0]);
2027 e->u.surrogateDiagnostic = drecs->diagRecs[0];
2033 ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs;
2034 ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs;
2039 static Z_APDU *process_sortRequest(association *assoc, request *reqb,
2042 Z_SortRequest *req = reqb->apdu_request->u.sortRequest;
2043 Z_SortResponse *res = (Z_SortResponse *)
2044 odr_malloc (assoc->encode, sizeof(*res));
2045 bend_sort_rr *bsrr = (bend_sort_rr *)
2046 odr_malloc (assoc->encode, sizeof(*bsrr));
2048 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2050 yaz_log(LOG_LOG, "Got SortRequest.");
2052 bsrr->num_input_setnames = req->num_inputResultSetNames;
2053 bsrr->input_setnames = req->inputResultSetNames;
2054 bsrr->referenceId = req->referenceId;
2055 bsrr->output_setname = req->sortedResultSetName;
2056 bsrr->sort_sequence = req->sortSequence;
2057 bsrr->stream = assoc->encode;
2058 bsrr->print = assoc->print;
2060 bsrr->sort_status = Z_SortResponse_failure;
2062 bsrr->errstring = 0;
2064 (*assoc->init->bend_sort)(assoc->backend, bsrr);
2066 res->referenceId = bsrr->referenceId;
2067 res->sortStatus = odr_intdup(assoc->encode, bsrr->sort_status);
2068 res->resultSetStatus = 0;
2071 Z_DiagRecs *dr = diagrecs (assoc, bsrr->errcode, bsrr->errstring);
2072 res->diagnostics = dr->diagRecs;
2073 res->num_diagnostics = dr->num_diagRecs;
2077 res->num_diagnostics = 0;
2078 res->diagnostics = 0;
2080 res->resultCount = 0;
2083 apdu->which = Z_APDU_sortResponse;
2084 apdu->u.sortResponse = res;
2088 static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
2091 Z_DeleteResultSetRequest *req =
2092 reqb->apdu_request->u.deleteResultSetRequest;
2093 Z_DeleteResultSetResponse *res = (Z_DeleteResultSetResponse *)
2094 odr_malloc (assoc->encode, sizeof(*res));
2095 bend_delete_rr *bdrr = (bend_delete_rr *)
2096 odr_malloc (assoc->encode, sizeof(*bdrr));
2097 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2099 yaz_log(LOG_LOG, "Got DeleteRequest.");
2101 bdrr->num_setnames = req->num_resultSetList;
2102 bdrr->setnames = req->resultSetList;
2103 bdrr->stream = assoc->encode;
2104 bdrr->print = assoc->print;
2105 bdrr->function = *req->deleteFunction;
2106 bdrr->referenceId = req->referenceId;
2108 if (bdrr->num_setnames > 0)
2111 bdrr->statuses = (int*)
2112 odr_malloc(assoc->encode, sizeof(*bdrr->statuses) *
2113 bdrr->num_setnames);
2114 for (i = 0; i < bdrr->num_setnames; i++)
2115 bdrr->statuses[i] = 0;
2117 (*assoc->init->bend_delete)(assoc->backend, bdrr);
2119 res->referenceId = req->referenceId;
2121 res->deleteOperationStatus = odr_intdup(assoc->encode,bdrr->delete_status);
2123 res->deleteListStatuses = 0;
2124 if (bdrr->num_setnames > 0)
2127 res->deleteListStatuses = (Z_ListStatuses *)
2128 odr_malloc(assoc->encode, sizeof(*res->deleteListStatuses));
2129 res->deleteListStatuses->num = bdrr->num_setnames;
2130 res->deleteListStatuses->elements =
2132 odr_malloc (assoc->encode,
2133 sizeof(*res->deleteListStatuses->elements) *
2134 bdrr->num_setnames);
2135 for (i = 0; i<bdrr->num_setnames; i++)
2137 res->deleteListStatuses->elements[i] =
2139 odr_malloc (assoc->encode,
2140 sizeof(**res->deleteListStatuses->elements));
2141 res->deleteListStatuses->elements[i]->status = bdrr->statuses+i;
2142 res->deleteListStatuses->elements[i]->id =
2143 odr_strdup (assoc->encode, bdrr->setnames[i]);
2147 res->numberNotDeleted = 0;
2148 res->bulkStatuses = 0;
2149 res->deleteMessage = 0;
2152 apdu->which = Z_APDU_deleteResultSetResponse;
2153 apdu->u.deleteResultSetResponse = res;
2157 static void process_close(association *assoc, request *reqb)
2159 Z_Close *req = reqb->apdu_request->u.close;
2160 static char *reasons[] =
2167 "securityViolation",
2174 yaz_log(LOG_LOG, "Got Close, reason %s, message %s",
2175 reasons[*req->closeReason], req->diagnosticInformation ?
2176 req->diagnosticInformation : "NULL");
2177 if (assoc->version < 3) /* to make do_force respond with close */
2179 do_close_req(assoc, Z_Close_finished,
2180 "Association terminated by client", reqb);
2183 void save_referenceId (request *reqb, Z_ReferenceId *refid)
2187 reqb->len_refid = refid->len;
2188 reqb->refid = (char *)nmem_malloc (reqb->request_mem, refid->len);
2189 memcpy (reqb->refid, refid->buf, refid->len);
2193 reqb->len_refid = 0;
2198 void bend_request_send (bend_association a, bend_request req, Z_APDU *res)
2200 process_z_response (a, req, res);
2203 bend_request bend_request_mk (bend_association a)
2205 request *nreq = request_get (&a->outgoing);
2206 nreq->request_mem = nmem_create ();
2210 Z_ReferenceId *bend_request_getid (ODR odr, bend_request req)
2215 id = (Odr_oct *)odr_malloc (odr, sizeof(*odr));
2216 id->buf = (unsigned char *)odr_malloc (odr, req->len_refid);
2217 id->len = id->size = req->len_refid;
2218 memcpy (id->buf, req->refid, req->len_refid);
2222 void bend_request_destroy (bend_request *req)
2224 nmem_destroy((*req)->request_mem);
2225 request_release(*req);
2229 int bend_backend_respond (bend_association a, bend_request req)
2233 r = process_z_request (a, req, &msg);
2235 yaz_log (LOG_WARN, "%s", msg);
2239 void bend_request_setdata(bend_request r, void *p)
2244 void *bend_request_getdata(bend_request r)
2246 return r->clientData;
2249 static Z_APDU *process_segmentRequest (association *assoc, request *reqb)
2251 bend_segment_rr req;
2253 req.segment = reqb->apdu_request->u.segmentRequest;
2254 req.stream = assoc->encode;
2255 req.decode = assoc->decode;
2256 req.print = assoc->print;
2257 req.association = assoc;
2259 (*assoc->init->bend_segment)(assoc->backend, &req);
2264 static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd)
2266 bend_esrequest_rr esrequest;
2268 Z_ExtendedServicesRequest *req =
2269 reqb->apdu_request->u.extendedServicesRequest;
2270 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_extendedServicesResponse);
2272 Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse;
2274 yaz_log(LOG_DEBUG,"inside Process esRequest");
2276 esrequest.esr = reqb->apdu_request->u.extendedServicesRequest;
2277 esrequest.stream = assoc->encode;
2278 esrequest.decode = assoc->decode;
2279 esrequest.print = assoc->print;
2280 esrequest.errcode = 0;
2281 esrequest.errstring = NULL;
2282 esrequest.request = reqb;
2283 esrequest.association = assoc;
2284 esrequest.taskPackage = 0;
2285 esrequest.referenceId = req->referenceId;
2287 (*assoc->init->bend_esrequest)(assoc->backend, &esrequest);
2289 /* If the response is being delayed, return NULL */
2290 if (esrequest.request == NULL)
2293 resp->referenceId = req->referenceId;
2295 if (esrequest.errcode == -1)
2297 /* Backend service indicates request will be processed */
2298 yaz_log(LOG_DEBUG,"Request could be processed...Accepted !");
2299 *resp->operationStatus = Z_ExtendedServicesResponse_accepted;
2301 else if (esrequest.errcode == 0)
2303 /* Backend service indicates request will be processed */
2304 yaz_log(LOG_DEBUG,"Request could be processed...Done !");
2305 *resp->operationStatus = Z_ExtendedServicesResponse_done;
2309 Z_DiagRecs *diagRecs = diagrecs (assoc, esrequest.errcode,
2310 esrequest.errstring);
2312 /* Backend indicates error, request will not be processed */
2313 yaz_log(LOG_DEBUG,"Request could not be processed...failure !");
2314 *resp->operationStatus = Z_ExtendedServicesResponse_failure;
2315 resp->num_diagnostics = diagRecs->num_diagRecs;
2316 resp->diagnostics = diagRecs->diagRecs;
2318 /* Do something with the members of bend_extendedservice */
2319 if (esrequest.taskPackage)
2320 resp->taskPackage = z_ext_record (assoc->encode, VAL_EXTENDED,
2321 (const char *) esrequest.taskPackage,
2323 yaz_log(LOG_DEBUG,"Send the result apdu");