2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: seshigh.c,v 1.26 2004-08-02 10:06:34 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";
1037 case Z_APDU_triggerResourceControlRequest:
1040 *msg = "Bad APDU received";
1045 yaz_log(LOG_DEBUG, " result immediately available");
1046 retval = process_z_response(assoc, req, res);
1050 yaz_log(LOG_DEBUG, " result unavailble");
1053 else /* no result yet - one will be provided later */
1057 /* Set up an I/O handler for the fd supplied by the backend */
1059 yaz_log(LOG_DEBUG, " establishing handler for result");
1060 req->state = REQUEST_PENDING;
1061 if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT)))
1063 iochan_setdata(chan, assoc);
1070 * Handle message from the backend.
1072 void backend_response(IOCHAN i, int event)
1074 association *assoc = (association *)iochan_getdata(i);
1075 request *req = request_head(&assoc->incoming);
1079 yaz_log(LOG_DEBUG, "backend_response");
1080 assert(assoc && req && req->state != REQUEST_IDLE);
1081 /* determine what it is we're waiting for */
1082 switch (req->apdu_request->which)
1084 case Z_APDU_searchRequest:
1085 res = response_searchRequest(assoc, req, 0, &fd); break;
1087 case Z_APDU_presentRequest:
1088 res = response_presentRequest(assoc, req, 0, &fd); break;
1089 case Z_APDU_scanRequest:
1090 res = response_scanRequest(assoc, req, 0, &fd); break;
1093 yaz_log(LOG_WARN, "Serious programmer's lapse or bug");
1096 if ((res && process_z_response(assoc, req, res) < 0) || fd < 0)
1098 yaz_log(LOG_LOG, "Fatal error when talking to backend");
1099 do_close(assoc, Z_Close_systemProblem, 0);
1103 else if (!res) /* no result yet - try again later */
1105 yaz_log(LOG_DEBUG, " no result yet");
1106 iochan_setfd(i, fd); /* in case fd has changed */
1111 * Encode response, and transfer the request structure to the outgoing queue.
1113 static int process_gdu_response(association *assoc, request *req, Z_GDU *res)
1115 odr_setbuf(assoc->encode, req->response, req->size_response, 1);
1119 if (!z_GDU(assoc->print, &res, 0, 0))
1120 yaz_log(LOG_WARN, "ODR print error: %s",
1121 odr_errmsg(odr_geterror(assoc->print)));
1122 odr_reset(assoc->print);
1124 if (!z_GDU(assoc->encode, &res, 0, 0))
1126 yaz_log(LOG_WARN, "ODR error when encoding PDU: %s [element %s]",
1127 odr_errmsg(odr_geterror(assoc->decode)),
1128 odr_getelement(assoc->decode));
1129 request_release(req);
1132 req->response = odr_getbuf(assoc->encode, &req->len_response,
1133 &req->size_response);
1134 odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */
1135 odr_reset(assoc->encode);
1136 req->state = REQUEST_IDLE;
1137 request_enq(&assoc->outgoing, req);
1138 /* turn the work over to the ir_session handler */
1139 iochan_setflag(assoc->client_chan, EVENT_OUTPUT);
1140 assoc->cs_put_mask = EVENT_OUTPUT;
1141 /* Is there more work to be done? give that to the input handler too */
1143 if (request_head(&assoc->incoming))
1145 yaz_log (LOG_DEBUG, "more work to be done");
1146 iochan_setevent(assoc->client_chan, EVENT_WORK);
1153 * Encode response, and transfer the request structure to the outgoing queue.
1155 static int process_z_response(association *assoc, request *req, Z_APDU *res)
1157 Z_GDU *gres = (Z_GDU *) odr_malloc(assoc->encode, sizeof(*res));
1158 gres->which = Z_GDU_Z3950;
1159 gres->u.z3950 = res;
1161 return process_gdu_response(assoc, req, gres);
1166 * Handle init request.
1167 * At the moment, we don't check the options
1168 * anywhere else in the code - we just try not to do anything that would
1169 * break a naive client. We'll toss 'em into the association block when
1170 * we need them there.
1172 static Z_APDU *process_initRequest(association *assoc, request *reqb)
1174 statserv_options_block *cb = statserv_getcontrol();
1175 Z_InitRequest *req = reqb->apdu_request->u.initRequest;
1176 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_initResponse);
1177 Z_InitResponse *resp = apdu->u.initResponse;
1178 bend_initresult *binitres;
1182 yaz_log(LOG_LOG, "Got initRequest");
1183 if (req->implementationId)
1184 yaz_log(LOG_LOG, "Id: %s", req->implementationId);
1185 if (req->implementationName)
1186 yaz_log(LOG_LOG, "Name: %s", req->implementationName);
1187 if (req->implementationVersion)
1188 yaz_log(LOG_LOG, "Version: %s", req->implementationVersion);
1190 assoc_init_reset(assoc);
1192 assoc->init->auth = req->idAuthentication;
1193 assoc->init->referenceId = req->referenceId;
1195 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
1197 Z_CharSetandLanguageNegotiation *negotiation =
1198 yaz_get_charneg_record (req->otherInfo);
1200 negotiation->which == Z_CharSetandLanguageNegotiation_proposal)
1201 assoc->init->charneg_request = negotiation;
1205 if (!(binitres = (*cb->bend_init)(assoc->init)))
1207 yaz_log(LOG_WARN, "Bad response from backend.");
1211 assoc->backend = binitres->handle;
1212 if ((assoc->init->bend_sort))
1213 yaz_log (LOG_DEBUG, "Sort handler installed");
1214 if ((assoc->init->bend_search))
1215 yaz_log (LOG_DEBUG, "Search handler installed");
1216 if ((assoc->init->bend_present))
1217 yaz_log (LOG_DEBUG, "Present handler installed");
1218 if ((assoc->init->bend_esrequest))
1219 yaz_log (LOG_DEBUG, "ESRequest handler installed");
1220 if ((assoc->init->bend_delete))
1221 yaz_log (LOG_DEBUG, "Delete handler installed");
1222 if ((assoc->init->bend_scan))
1223 yaz_log (LOG_DEBUG, "Scan handler installed");
1224 if ((assoc->init->bend_segment))
1225 yaz_log (LOG_DEBUG, "Segment handler installed");
1227 resp->referenceId = req->referenceId;
1229 /* let's tell the client what we can do */
1230 if (ODR_MASK_GET(req->options, Z_Options_search))
1232 ODR_MASK_SET(resp->options, Z_Options_search);
1233 strcat(options, "srch");
1235 if (ODR_MASK_GET(req->options, Z_Options_present))
1237 ODR_MASK_SET(resp->options, Z_Options_present);
1238 strcat(options, " prst");
1240 if (ODR_MASK_GET(req->options, Z_Options_delSet) &&
1241 assoc->init->bend_delete)
1243 ODR_MASK_SET(resp->options, Z_Options_delSet);
1244 strcat(options, " del");
1246 if (ODR_MASK_GET(req->options, Z_Options_extendedServices) &&
1247 assoc->init->bend_esrequest)
1249 ODR_MASK_SET(resp->options, Z_Options_extendedServices);
1250 strcat (options, " extendedServices");
1252 if (ODR_MASK_GET(req->options, Z_Options_namedResultSets))
1254 ODR_MASK_SET(resp->options, Z_Options_namedResultSets);
1255 strcat(options, " namedresults");
1257 if (ODR_MASK_GET(req->options, Z_Options_scan) && assoc->init->bend_scan)
1259 ODR_MASK_SET(resp->options, Z_Options_scan);
1260 strcat(options, " scan");
1262 if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations))
1264 ODR_MASK_SET(resp->options, Z_Options_concurrentOperations);
1265 strcat(options, " concurrop");
1267 if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort)
1269 ODR_MASK_SET(resp->options, Z_Options_sort);
1270 strcat(options, " sort");
1273 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)
1274 && assoc->init->charneg_response)
1276 Z_OtherInformation **p;
1277 Z_OtherInformationUnit *p0;
1279 yaz_oi_APDU(apdu, &p);
1281 if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) {
1282 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1284 p0->which = Z_OtherInfo_externallyDefinedInfo;
1285 p0->information.externallyDefinedInfo =
1286 assoc->init->charneg_response;
1288 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1289 strcat(options, " negotiation");
1292 ODR_MASK_SET(resp->options, Z_Options_triggerResourceCtrl);
1294 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
1296 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
1297 assoc->version = 1; /* 1 & 2 are equivalent */
1299 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
1301 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
1304 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
1306 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
1310 yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options);
1311 assoc->maximumRecordSize = *req->maximumRecordSize;
1312 if (assoc->maximumRecordSize > control_block->maxrecordsize)
1313 assoc->maximumRecordSize = control_block->maxrecordsize;
1314 assoc->preferredMessageSize = *req->preferredMessageSize;
1315 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
1316 assoc->preferredMessageSize = assoc->maximumRecordSize;
1318 resp->preferredMessageSize = &assoc->preferredMessageSize;
1319 resp->maximumRecordSize = &assoc->maximumRecordSize;
1321 resp->implementationId = odr_prepend(assoc->encode,
1322 assoc->init->implementation_id,
1323 resp->implementationId);
1325 resp->implementationName = odr_prepend(assoc->encode,
1326 assoc->init->implementation_name,
1327 odr_prepend(assoc->encode, "GFS", resp->implementationName));
1329 version = odr_strdup(assoc->encode, "$Revision: 1.26 $");
1330 if (strlen(version) > 10) /* check for unexpanded CVS strings */
1331 version[strlen(version)-2] = '\0';
1332 resp->implementationVersion = odr_prepend(assoc->encode,
1333 assoc->init->implementation_version,
1334 odr_prepend(assoc->encode, &version[11],
1335 resp->implementationVersion));
1337 if (binitres->errcode)
1339 yaz_log(LOG_LOG, "Connection rejected by backend.");
1341 assoc->state = ASSOC_DEAD;
1342 resp->userInformationField = init_diagnostics(assoc->encode,
1344 binitres->errstring);
1347 assoc->state = ASSOC_UP;
1352 * Diagnostic in default format, to be returned as either a surrogate
1353 * or non-surrogate diagnostic in the context of an open session, or
1354 * as User-information when an Init is refused.
1356 static Z_DefaultDiagFormat *justdiag(ODR odr, int error, char *addinfo)
1358 int *err = odr_intdup(odr, error);
1359 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
1360 odr_malloc (odr, sizeof(*dr));
1362 yaz_log(LOG_LOG, "[%d] %s%s%s", error, diagbib1_str(error),
1363 addinfo ? " -- " : "", addinfo ? addinfo : "");
1365 dr->diagnosticSetId =
1366 yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1);
1367 dr->condition = err;
1368 dr->which = Z_DefaultDiagFormat_v2Addinfo;
1369 dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
1374 * Set the specified `errcode' and `errstring' into a UserInfo-1
1375 * external to be returned to the client in accordance with Z35.90
1376 * Implementor Agreement 5 (Returning diagnostics in an InitResponse):
1377 * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html
1379 static Z_External *init_diagnostics(ODR odr, int error, char *addinfo)
1383 Z_OtherInformation *u;
1384 Z_OtherInformationUnit *l;
1385 Z_DiagnosticFormat *d;
1386 Z_DiagnosticFormat_s *e;
1388 x = (Z_External*) odr_malloc(odr, sizeof *x);
1390 x->indirect_reference = 0;
1391 oid.proto = PROTO_Z3950;
1392 oid.oclass = CLASS_USERINFO;
1393 oid.value = VAL_USERINFO1;
1394 x->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1395 x->which = Z_External_userInfo1;
1397 u = odr_malloc(odr, sizeof *u);
1399 u->num_elements = 1;
1400 u->list = (Z_OtherInformationUnit**) odr_malloc(odr, sizeof *u->list);
1401 u->list[0] = (Z_OtherInformationUnit*) odr_malloc(odr, sizeof *u->list[0]);
1404 l->which = Z_OtherInfo_externallyDefinedInfo;
1406 x2 = (Z_External*) odr_malloc(odr, sizeof *x);
1407 l->information.externallyDefinedInfo = x2;
1409 x2->indirect_reference = 0;
1410 oid.oclass = CLASS_DIAGSET;
1411 oid.value = VAL_DIAG1;
1412 x2->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1413 x2->which = Z_External_diag1;
1415 d = (Z_DiagnosticFormat*) odr_malloc(odr, sizeof *d);
1418 d->elements = (Z_DiagnosticFormat_s**) odr_malloc (odr, sizeof *d->elements);
1419 d->elements[0] = (Z_DiagnosticFormat_s*) odr_malloc (odr, sizeof *d->elements[0]);
1422 e->which = Z_DiagnosticFormat_s_defaultDiagRec;
1423 e->u.defaultDiagRec = justdiag(odr, error, addinfo);
1429 * nonsurrogate diagnostic record.
1431 static Z_Records *diagrec(association *assoc, int error, char *addinfo)
1433 Z_Records *rec = (Z_Records *)
1434 odr_malloc (assoc->encode, sizeof(*rec));
1435 rec->which = Z_Records_NSD;
1436 rec->u.nonSurrogateDiagnostic = justdiag(assoc->encode, error, addinfo);
1441 * surrogate diagnostic.
1443 static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname,
1444 int error, char *addinfo)
1446 Z_NamePlusRecord *rec = (Z_NamePlusRecord *)
1447 odr_malloc (assoc->encode, sizeof(*rec));
1448 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1450 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
1451 rec->databaseName = dbname;
1452 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
1453 rec->u.surrogateDiagnostic = drec;
1454 drec->which = Z_DiagRec_defaultFormat;
1455 drec->u.defaultFormat = justdiag(assoc->encode, error, addinfo);
1461 * multiple nonsurrogate diagnostics.
1463 static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo)
1465 Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs));
1466 int *err = odr_intdup(assoc->encode, error);
1467 Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp));
1468 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1469 Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *)
1470 odr_malloc (assoc->encode, sizeof(*rec));
1472 yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : "");
1474 recs->num_diagRecs = 1;
1475 recs->diagRecs = recp;
1477 drec->which = Z_DiagRec_defaultFormat;
1478 drec->u.defaultFormat = rec;
1480 rec->diagnosticSetId =
1481 yaz_oidval_to_z3950oid (assoc->encode, CLASS_DIAGSET, VAL_BIB1);
1482 rec->condition = err;
1484 rec->which = Z_DefaultDiagFormat_v2Addinfo;
1485 rec->u.v2Addinfo = odr_strdup (assoc->encode, addinfo ? addinfo : "");
1489 static Z_Records *pack_records(association *a, char *setname, int start,
1490 int *num, Z_RecordComposition *comp,
1491 int *next, int *pres, oid_value format,
1492 Z_ReferenceId *referenceId,
1495 int recno, total_length = 0, toget = *num, dumped_records = 0;
1496 Z_Records *records =
1497 (Z_Records *) odr_malloc (a->encode, sizeof(*records));
1498 Z_NamePlusRecordList *reclist =
1499 (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist));
1500 Z_NamePlusRecord **list =
1501 (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget);
1503 records->which = Z_Records_DBOSD;
1504 records->u.databaseOrSurDiagnostics = reclist;
1505 reclist->num_records = 0;
1506 reclist->records = list;
1507 *pres = Z_PresentStatus_success;
1511 yaz_log(LOG_LOG, "Request to pack %d+%d+%s", start, toget, setname);
1512 yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize,
1513 a->maximumRecordSize);
1514 for (recno = start; reclist->num_records < toget; recno++)
1517 Z_NamePlusRecord *thisrec;
1518 int this_length = 0;
1520 * we get the number of bytes allocated on the stream before any
1521 * allocation done by the backend - this should give us a reasonable
1522 * idea of the total size of the data so far.
1524 total_length = odr_total(a->encode) - dumped_records;
1530 freq.last_in_set = 0;
1531 freq.setname = setname;
1532 freq.surrogate_flag = 0;
1533 freq.number = recno;
1535 freq.request_format = format;
1536 freq.request_format_raw = oid;
1537 freq.output_format = format;
1538 freq.output_format_raw = 0;
1539 freq.stream = a->encode;
1540 freq.print = a->print;
1541 freq.referenceId = referenceId;
1543 (*a->init->bend_fetch)(a->backend, &freq);
1544 /* backend should be able to signal whether error is system-wide
1545 or only pertaining to current record */
1548 if (!freq.surrogate_flag)
1551 *pres = Z_PresentStatus_failure;
1552 /* for 'present request out of range',
1553 set addinfo to record position if not set */
1554 if (freq.errcode == 13 && freq.errstring == 0)
1556 sprintf (s, "%d", recno);
1559 return diagrec(a, freq.errcode, freq.errstring);
1561 reclist->records[reclist->num_records] =
1562 surrogatediagrec(a, freq.basename, freq.errcode,
1564 reclist->num_records++;
1565 *next = freq.last_in_set ? 0 : recno + 1;
1569 this_length = freq.len;
1571 this_length = odr_total(a->encode) - total_length - dumped_records;
1572 yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d dumped=%d",
1573 this_length, total_length, dumped_records);
1574 if (a->preferredMessageSize > 0 &&
1575 this_length + total_length > a->preferredMessageSize)
1577 /* record is small enough, really */
1578 if (this_length <= a->preferredMessageSize && recno > start)
1580 yaz_log(LOG_DEBUG, " Dropped last normal-sized record");
1581 *pres = Z_PresentStatus_partial_2;
1584 /* record can only be fetched by itself */
1585 if (this_length < a->maximumRecordSize)
1587 yaz_log(LOG_DEBUG, " Record > prefmsgsz");
1590 yaz_log(LOG_DEBUG, " Dropped it");
1591 reclist->records[reclist->num_records] =
1592 surrogatediagrec(a, freq.basename, 16, 0);
1593 reclist->num_records++;
1594 *next = freq.last_in_set ? 0 : recno + 1;
1595 dumped_records += this_length;
1599 else /* too big entirely */
1601 yaz_log(LOG_LOG, "Record > maxrcdsz this=%d max=%d", this_length, a->maximumRecordSize);
1602 reclist->records[reclist->num_records] =
1603 surrogatediagrec(a, freq.basename, 17, 0);
1604 reclist->num_records++;
1605 *next = freq.last_in_set ? 0 : recno + 1;
1606 dumped_records += this_length;
1611 if (!(thisrec = (Z_NamePlusRecord *)
1612 odr_malloc(a->encode, sizeof(*thisrec))))
1614 if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
1615 strlen(freq.basename) + 1)))
1617 strcpy(thisrec->databaseName, freq.basename);
1618 thisrec->which = Z_NamePlusRecord_databaseRecord;
1620 if (freq.output_format_raw)
1622 struct oident *ident = oid_getentbyoid(freq.output_format_raw);
1623 freq.output_format = ident->value;
1625 thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format,
1626 freq.record, freq.len);
1627 if (!thisrec->u.databaseRecord)
1629 reclist->records[reclist->num_records] = thisrec;
1630 reclist->num_records++;
1631 *next = freq.last_in_set ? 0 : recno + 1;
1633 *num = reclist->num_records;
1637 static Z_APDU *process_searchRequest(association *assoc, request *reqb,
1640 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1641 bend_search_rr *bsrr =
1642 (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr));
1644 yaz_log(LOG_LOG, "Got SearchRequest.");
1646 bsrr->request = reqb;
1647 bsrr->association = assoc;
1648 bsrr->referenceId = req->referenceId;
1649 save_referenceId (reqb, bsrr->referenceId);
1651 yaz_log (LOG_LOG, "ResultSet '%s'", req->resultSetName);
1652 if (req->databaseNames)
1655 for (i = 0; i < req->num_databaseNames; i++)
1656 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1658 yaz_log_zquery(req->query);
1660 if (assoc->init->bend_search)
1662 bsrr->setname = req->resultSetName;
1663 bsrr->replace_set = *req->replaceIndicator;
1664 bsrr->num_bases = req->num_databaseNames;
1665 bsrr->basenames = req->databaseNames;
1666 bsrr->query = req->query;
1667 bsrr->stream = assoc->encode;
1668 nmem_transfer(bsrr->stream->mem, reqb->request_mem);
1669 bsrr->decode = assoc->decode;
1670 bsrr->print = assoc->print;
1673 bsrr->errstring = NULL;
1674 bsrr->search_info = NULL;
1675 (assoc->init->bend_search)(assoc->backend, bsrr);
1679 return response_searchRequest(assoc, reqb, bsrr, fd);
1682 int bend_searchresponse(void *handle, bend_search_rr *bsrr) {return 0;}
1685 * Prepare a searchresponse based on the backend results. We probably want
1686 * to look at making the fetching of records nonblocking as well, but
1687 * so far, we'll keep things simple.
1688 * If bsrt is null, that means we're called in response to a communications
1689 * event, and we'll have to get the response for ourselves.
1691 static Z_APDU *response_searchRequest(association *assoc, request *reqb,
1692 bend_search_rr *bsrt, int *fd)
1694 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1695 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1696 Z_SearchResponse *resp = (Z_SearchResponse *)
1697 odr_malloc (assoc->encode, sizeof(*resp));
1698 int *nulint = odr_intdup (assoc->encode, 0);
1699 bool_t *sr = odr_intdup(assoc->encode, 1);
1700 int *next = odr_intdup(assoc->encode, 0);
1701 int *none = odr_intdup(assoc->encode, Z_SearchResponse_none);
1703 apdu->which = Z_APDU_searchResponse;
1704 apdu->u.searchResponse = resp;
1705 resp->referenceId = req->referenceId;
1706 resp->additionalSearchInfo = 0;
1707 resp->otherInfo = 0;
1709 if (!bsrt && !bend_searchresponse(assoc->backend, bsrt))
1711 yaz_log(LOG_FATAL, "Bad result from backend");
1714 else if (bsrt->errcode)
1716 resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring);
1717 resp->resultCount = nulint;
1718 resp->numberOfRecordsReturned = nulint;
1719 resp->nextResultSetPosition = nulint;
1720 resp->searchStatus = nulint;
1721 resp->resultSetStatus = none;
1722 resp->presentStatus = 0;
1726 int *toget = odr_intdup(assoc->encode, 0);
1727 int *presst = odr_intdup(assoc->encode, 0);
1728 Z_RecordComposition comp, *compp = 0;
1730 yaz_log (LOG_LOG, "resultCount: %d", bsrt->hits);
1733 resp->resultCount = &bsrt->hits;
1735 comp.which = Z_RecordComp_simple;
1736 /* how many records does the user agent want, then? */
1737 if (bsrt->hits <= *req->smallSetUpperBound)
1739 *toget = bsrt->hits;
1740 if ((comp.u.simple = req->smallSetElementSetNames))
1743 else if (bsrt->hits < *req->largeSetLowerBound)
1745 *toget = *req->mediumSetPresentNumber;
1746 if (*toget > bsrt->hits)
1747 *toget = bsrt->hits;
1748 if ((comp.u.simple = req->mediumSetElementSetNames))
1754 if (*toget && !resp->records)
1759 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1762 form = prefformat->value;
1763 resp->records = pack_records(assoc, req->resultSetName, 1,
1764 toget, compp, next, presst, form, req->referenceId,
1765 req->preferredRecordSyntax);
1768 resp->numberOfRecordsReturned = toget;
1769 resp->nextResultSetPosition = next;
1770 resp->searchStatus = sr;
1771 resp->resultSetStatus = 0;
1772 resp->presentStatus = presst;
1776 if (*resp->resultCount)
1778 resp->numberOfRecordsReturned = nulint;
1779 resp->nextResultSetPosition = next;
1780 resp->searchStatus = sr;
1781 resp->resultSetStatus = 0;
1782 resp->presentStatus = 0;
1785 resp->additionalSearchInfo = bsrt->search_info;
1790 * Maybe we got a little over-friendly when we designed bend_fetch to
1791 * get only one record at a time. Some backends can optimise multiple-record
1792 * fetches, and at any rate, there is some overhead involved in
1793 * all that selecting and hopping around. Problem is, of course, that the
1794 * frontend can't know ahead of time how many records it'll need to
1795 * fill the negotiated PDU size. Annoying. Segmentation or not, Z/SR
1796 * is downright lousy as a bulk data transfer protocol.
1798 * To start with, we'll do the fetching of records from the backend
1799 * in one operation: To save some trips in and out of the event-handler,
1800 * and to simplify the interface to pack_records. At any rate, asynch
1801 * operation is more fun in operations that have an unpredictable execution
1802 * speed - which is normally more true for search than for present.
1804 static Z_APDU *process_presentRequest(association *assoc, request *reqb,
1807 Z_PresentRequest *req = reqb->apdu_request->u.presentRequest;
1811 Z_PresentResponse *resp;
1815 yaz_log(LOG_LOG, "Got PresentRequest.");
1817 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1820 form = prefformat->value;
1821 resp = (Z_PresentResponse *)odr_malloc (assoc->encode, sizeof(*resp));
1823 resp->presentStatus = odr_intdup(assoc->encode, 0);
1824 if (assoc->init->bend_present)
1826 bend_present_rr *bprr = (bend_present_rr *)
1827 nmem_malloc (reqb->request_mem, sizeof(*bprr));
1828 bprr->setname = req->resultSetId;
1829 bprr->start = *req->resultSetStartPoint;
1830 bprr->number = *req->numberOfRecordsRequested;
1831 bprr->format = form;
1832 bprr->comp = req->recordComposition;
1833 bprr->referenceId = req->referenceId;
1834 bprr->stream = assoc->encode;
1835 bprr->print = assoc->print;
1836 bprr->request = reqb;
1837 bprr->association = assoc;
1839 bprr->errstring = NULL;
1840 (*assoc->init->bend_present)(assoc->backend, bprr);
1846 resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
1847 *resp->presentStatus = Z_PresentStatus_failure;
1850 apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1851 next = odr_intdup(assoc->encode, 0);
1852 num = odr_intdup(assoc->encode, 0);
1854 apdu->which = Z_APDU_presentResponse;
1855 apdu->u.presentResponse = resp;
1856 resp->referenceId = req->referenceId;
1857 resp->otherInfo = 0;
1861 *num = *req->numberOfRecordsRequested;
1863 pack_records(assoc, req->resultSetId, *req->resultSetStartPoint,
1864 num, req->recordComposition, next, resp->presentStatus,
1865 form, req->referenceId, req->preferredRecordSyntax);
1869 resp->numberOfRecordsReturned = num;
1870 resp->nextResultSetPosition = next;
1876 * Scan was implemented rather in a hurry, and with support for only the basic
1877 * elements of the service in the backend API. Suggestions are welcome.
1879 static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd)
1881 Z_ScanRequest *req = reqb->apdu_request->u.scanRequest;
1882 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1883 Z_ScanResponse *res = (Z_ScanResponse *)
1884 odr_malloc (assoc->encode, sizeof(*res));
1885 int *scanStatus = odr_intdup(assoc->encode, Z_Scan_failure);
1886 int *numberOfEntriesReturned = odr_intdup(assoc->encode, 0);
1887 Z_ListEntries *ents = (Z_ListEntries *)
1888 odr_malloc (assoc->encode, sizeof(*ents));
1889 Z_DiagRecs *diagrecs_p = NULL;
1891 bend_scan_rr *bsrr = (bend_scan_rr *)
1892 odr_malloc (assoc->encode, sizeof(*bsrr));
1893 struct scan_entry *save_entries;
1895 yaz_log(LOG_LOG, "Got ScanRequest");
1897 apdu->which = Z_APDU_scanResponse;
1898 apdu->u.scanResponse = res;
1899 res->referenceId = req->referenceId;
1901 /* if step is absent, set it to 0 */
1902 res->stepSize = odr_intdup(assoc->encode, 0);
1904 *res->stepSize = *req->stepSize;
1906 res->scanStatus = scanStatus;
1907 res->numberOfEntriesReturned = numberOfEntriesReturned;
1908 res->positionOfTerm = 0;
1909 res->entries = ents;
1910 ents->num_entries = 0;
1911 ents->entries = NULL;
1912 ents->num_nonsurrogateDiagnostics = 0;
1913 ents->nonsurrogateDiagnostics = NULL;
1914 res->attributeSet = 0;
1917 if (req->databaseNames)
1920 for (i = 0; i < req->num_databaseNames; i++)
1921 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1923 bsrr->num_bases = req->num_databaseNames;
1924 bsrr->basenames = req->databaseNames;
1925 bsrr->num_entries = *req->numberOfTermsRequested;
1926 bsrr->term = req->termListAndStartPoint;
1927 bsrr->referenceId = req->referenceId;
1928 bsrr->stream = assoc->encode;
1929 bsrr->print = assoc->print;
1930 bsrr->step_size = res->stepSize;
1932 /* Note that version 2.0 of YAZ and older did not set entries ..
1933 We do now. And when we do it's easier to extend the scan entry
1934 We know that if the scan handler did set entries, it will
1935 not know of new member display_term.
1937 if (bsrr->num_entries > 0)
1940 bsrr->entries = odr_malloc(assoc->decode, sizeof(*bsrr->entries) *
1942 for (i = 0; i<bsrr->num_entries; i++)
1944 bsrr->entries[i].term = 0;
1945 bsrr->entries[i].occurrences = 0;
1946 bsrr->entries[i].errcode = 0;
1947 bsrr->entries[i].errstring = 0;
1948 bsrr->entries[i].display_term = 0;
1951 save_entries = bsrr->entries; /* save it so we can compare later */
1953 if (req->attributeSet &&
1954 (attset = oid_getentbyoid(req->attributeSet)) &&
1955 (attset->oclass == CLASS_ATTSET || attset->oclass == CLASS_GENERAL))
1956 bsrr->attributeset = attset->value;
1958 bsrr->attributeset = VAL_NONE;
1959 log_scan_term (req->termListAndStartPoint, bsrr->attributeset);
1960 bsrr->term_position = req->preferredPositionInResponse ?
1961 *req->preferredPositionInResponse : 1;
1962 ((int (*)(void *, bend_scan_rr *))
1963 (*assoc->init->bend_scan))(assoc->backend, bsrr);
1965 diagrecs_p = diagrecs(assoc, bsrr->errcode, bsrr->errstring);
1969 Z_Entry **tab = (Z_Entry **)
1970 odr_malloc (assoc->encode, sizeof(*tab) * bsrr->num_entries);
1972 if (bsrr->status == BEND_SCAN_PARTIAL)
1973 *scanStatus = Z_Scan_partial_5;
1975 *scanStatus = Z_Scan_success;
1976 ents->entries = tab;
1977 ents->num_entries = bsrr->num_entries;
1978 res->numberOfEntriesReturned = &ents->num_entries;
1979 res->positionOfTerm = &bsrr->term_position;
1980 for (i = 0; i < bsrr->num_entries; i++)
1986 tab[i] = e = (Z_Entry *)odr_malloc(assoc->encode, sizeof(*e));
1987 if (bsrr->entries[i].occurrences >= 0)
1989 e->which = Z_Entry_termInfo;
1990 e->u.termInfo = t = (Z_TermInfo *)
1991 odr_malloc(assoc->encode, sizeof(*t));
1992 t->suggestedAttributes = 0;
1994 if (save_entries == bsrr->entries &&
1995 bsrr->entries[i].display_term)
1997 /* the entries was NOT set by the handler. So it's
1998 safe to test for new member display_term. It is
2001 t->displayTerm = odr_strdup(assoc->encode,
2002 bsrr->entries[i].display_term);
2004 t->alternativeTerm = 0;
2005 t->byAttributes = 0;
2006 t->otherTermInfo = 0;
2007 t->globalOccurrences = &bsrr->entries[i].occurrences;
2008 t->term = (Z_Term *)
2009 odr_malloc(assoc->encode, sizeof(*t->term));
2010 t->term->which = Z_Term_general;
2011 t->term->u.general = o =
2012 (Odr_oct *)odr_malloc(assoc->encode, sizeof(Odr_oct));
2013 o->buf = (unsigned char *)
2014 odr_malloc(assoc->encode, o->len = o->size =
2015 strlen(bsrr->entries[i].term));
2016 memcpy(o->buf, bsrr->entries[i].term, o->len);
2017 yaz_log(LOG_DEBUG, " term #%d: '%s' (%d)", i,
2018 bsrr->entries[i].term, bsrr->entries[i].occurrences);
2022 Z_DiagRecs *drecs = diagrecs (assoc,
2023 bsrr->entries[i].errcode,
2024 bsrr->entries[i].errstring);
2025 assert (drecs->num_diagRecs == 1);
2026 e->which = Z_Entry_surrogateDiagnostic;
2027 assert (drecs->diagRecs[0]);
2028 e->u.surrogateDiagnostic = drecs->diagRecs[0];
2034 ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs;
2035 ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs;
2040 static Z_APDU *process_sortRequest(association *assoc, request *reqb,
2043 Z_SortRequest *req = reqb->apdu_request->u.sortRequest;
2044 Z_SortResponse *res = (Z_SortResponse *)
2045 odr_malloc (assoc->encode, sizeof(*res));
2046 bend_sort_rr *bsrr = (bend_sort_rr *)
2047 odr_malloc (assoc->encode, sizeof(*bsrr));
2049 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2051 yaz_log(LOG_LOG, "Got SortRequest.");
2053 bsrr->num_input_setnames = req->num_inputResultSetNames;
2054 bsrr->input_setnames = req->inputResultSetNames;
2055 bsrr->referenceId = req->referenceId;
2056 bsrr->output_setname = req->sortedResultSetName;
2057 bsrr->sort_sequence = req->sortSequence;
2058 bsrr->stream = assoc->encode;
2059 bsrr->print = assoc->print;
2061 bsrr->sort_status = Z_SortResponse_failure;
2063 bsrr->errstring = 0;
2065 (*assoc->init->bend_sort)(assoc->backend, bsrr);
2067 res->referenceId = bsrr->referenceId;
2068 res->sortStatus = odr_intdup(assoc->encode, bsrr->sort_status);
2069 res->resultSetStatus = 0;
2072 Z_DiagRecs *dr = diagrecs (assoc, bsrr->errcode, bsrr->errstring);
2073 res->diagnostics = dr->diagRecs;
2074 res->num_diagnostics = dr->num_diagRecs;
2078 res->num_diagnostics = 0;
2079 res->diagnostics = 0;
2081 res->resultCount = 0;
2084 apdu->which = Z_APDU_sortResponse;
2085 apdu->u.sortResponse = res;
2089 static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
2092 Z_DeleteResultSetRequest *req =
2093 reqb->apdu_request->u.deleteResultSetRequest;
2094 Z_DeleteResultSetResponse *res = (Z_DeleteResultSetResponse *)
2095 odr_malloc (assoc->encode, sizeof(*res));
2096 bend_delete_rr *bdrr = (bend_delete_rr *)
2097 odr_malloc (assoc->encode, sizeof(*bdrr));
2098 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2100 yaz_log(LOG_LOG, "Got DeleteRequest.");
2102 bdrr->num_setnames = req->num_resultSetList;
2103 bdrr->setnames = req->resultSetList;
2104 bdrr->stream = assoc->encode;
2105 bdrr->print = assoc->print;
2106 bdrr->function = *req->deleteFunction;
2107 bdrr->referenceId = req->referenceId;
2109 if (bdrr->num_setnames > 0)
2112 bdrr->statuses = (int*)
2113 odr_malloc(assoc->encode, sizeof(*bdrr->statuses) *
2114 bdrr->num_setnames);
2115 for (i = 0; i < bdrr->num_setnames; i++)
2116 bdrr->statuses[i] = 0;
2118 (*assoc->init->bend_delete)(assoc->backend, bdrr);
2120 res->referenceId = req->referenceId;
2122 res->deleteOperationStatus = odr_intdup(assoc->encode,bdrr->delete_status);
2124 res->deleteListStatuses = 0;
2125 if (bdrr->num_setnames > 0)
2128 res->deleteListStatuses = (Z_ListStatuses *)
2129 odr_malloc(assoc->encode, sizeof(*res->deleteListStatuses));
2130 res->deleteListStatuses->num = bdrr->num_setnames;
2131 res->deleteListStatuses->elements =
2133 odr_malloc (assoc->encode,
2134 sizeof(*res->deleteListStatuses->elements) *
2135 bdrr->num_setnames);
2136 for (i = 0; i<bdrr->num_setnames; i++)
2138 res->deleteListStatuses->elements[i] =
2140 odr_malloc (assoc->encode,
2141 sizeof(**res->deleteListStatuses->elements));
2142 res->deleteListStatuses->elements[i]->status = bdrr->statuses+i;
2143 res->deleteListStatuses->elements[i]->id =
2144 odr_strdup (assoc->encode, bdrr->setnames[i]);
2148 res->numberNotDeleted = 0;
2149 res->bulkStatuses = 0;
2150 res->deleteMessage = 0;
2153 apdu->which = Z_APDU_deleteResultSetResponse;
2154 apdu->u.deleteResultSetResponse = res;
2158 static void process_close(association *assoc, request *reqb)
2160 Z_Close *req = reqb->apdu_request->u.close;
2161 static char *reasons[] =
2168 "securityViolation",
2175 yaz_log(LOG_LOG, "Got Close, reason %s, message %s",
2176 reasons[*req->closeReason], req->diagnosticInformation ?
2177 req->diagnosticInformation : "NULL");
2178 if (assoc->version < 3) /* to make do_force respond with close */
2180 do_close_req(assoc, Z_Close_finished,
2181 "Association terminated by client", reqb);
2184 void save_referenceId (request *reqb, Z_ReferenceId *refid)
2188 reqb->len_refid = refid->len;
2189 reqb->refid = (char *)nmem_malloc (reqb->request_mem, refid->len);
2190 memcpy (reqb->refid, refid->buf, refid->len);
2194 reqb->len_refid = 0;
2199 void bend_request_send (bend_association a, bend_request req, Z_APDU *res)
2201 process_z_response (a, req, res);
2204 bend_request bend_request_mk (bend_association a)
2206 request *nreq = request_get (&a->outgoing);
2207 nreq->request_mem = nmem_create ();
2211 Z_ReferenceId *bend_request_getid (ODR odr, bend_request req)
2216 id = (Odr_oct *)odr_malloc (odr, sizeof(*odr));
2217 id->buf = (unsigned char *)odr_malloc (odr, req->len_refid);
2218 id->len = id->size = req->len_refid;
2219 memcpy (id->buf, req->refid, req->len_refid);
2223 void bend_request_destroy (bend_request *req)
2225 nmem_destroy((*req)->request_mem);
2226 request_release(*req);
2230 int bend_backend_respond (bend_association a, bend_request req)
2234 r = process_z_request (a, req, &msg);
2236 yaz_log (LOG_WARN, "%s", msg);
2240 void bend_request_setdata(bend_request r, void *p)
2245 void *bend_request_getdata(bend_request r)
2247 return r->clientData;
2250 static Z_APDU *process_segmentRequest (association *assoc, request *reqb)
2252 bend_segment_rr req;
2254 req.segment = reqb->apdu_request->u.segmentRequest;
2255 req.stream = assoc->encode;
2256 req.decode = assoc->decode;
2257 req.print = assoc->print;
2258 req.association = assoc;
2260 (*assoc->init->bend_segment)(assoc->backend, &req);
2265 static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd)
2267 bend_esrequest_rr esrequest;
2269 Z_ExtendedServicesRequest *req =
2270 reqb->apdu_request->u.extendedServicesRequest;
2271 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_extendedServicesResponse);
2273 Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse;
2275 yaz_log(LOG_DEBUG,"inside Process esRequest");
2277 esrequest.esr = reqb->apdu_request->u.extendedServicesRequest;
2278 esrequest.stream = assoc->encode;
2279 esrequest.decode = assoc->decode;
2280 esrequest.print = assoc->print;
2281 esrequest.errcode = 0;
2282 esrequest.errstring = NULL;
2283 esrequest.request = reqb;
2284 esrequest.association = assoc;
2285 esrequest.taskPackage = 0;
2286 esrequest.referenceId = req->referenceId;
2288 (*assoc->init->bend_esrequest)(assoc->backend, &esrequest);
2290 /* If the response is being delayed, return NULL */
2291 if (esrequest.request == NULL)
2294 resp->referenceId = req->referenceId;
2296 if (esrequest.errcode == -1)
2298 /* Backend service indicates request will be processed */
2299 yaz_log(LOG_DEBUG,"Request could be processed...Accepted !");
2300 *resp->operationStatus = Z_ExtendedServicesResponse_accepted;
2302 else if (esrequest.errcode == 0)
2304 /* Backend service indicates request will be processed */
2305 yaz_log(LOG_DEBUG,"Request could be processed...Done !");
2306 *resp->operationStatus = Z_ExtendedServicesResponse_done;
2310 Z_DiagRecs *diagRecs = diagrecs (assoc, esrequest.errcode,
2311 esrequest.errstring);
2313 /* Backend indicates error, request will not be processed */
2314 yaz_log(LOG_DEBUG,"Request could not be processed...failure !");
2315 *resp->operationStatus = Z_ExtendedServicesResponse_failure;
2316 resp->num_diagnostics = diagRecs->num_diagRecs;
2317 resp->diagnostics = diagRecs->diagRecs;
2319 /* Do something with the members of bend_extendedservice */
2320 if (esrequest.taskPackage)
2321 resp->taskPackage = z_ext_record (assoc->encode, VAL_EXTENDED,
2322 (const char *) esrequest.taskPackage,
2324 yaz_log(LOG_DEBUG,"Send the result apdu");