2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: seshigh.c,v 1.32 2004-10-09 08:21:38 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));
514 /* schema uri = recordSchema (or NULL if recordSchema is not given) */
515 rr.comp->u.complex->generic->which = Z_Schema_uri;
516 rr.comp->u.complex->generic->schema.uri = srw_req->recordSchema;
518 /* ESN = recordSchema if recordSchema is present */
519 rr.comp->u.complex->generic->elementSpec = 0;
520 if (srw_req->recordSchema)
522 rr.comp->u.complex->generic->elementSpec =
523 (Z_ElementSpec *) odr_malloc(assoc->encode, sizeof(Z_ElementSpec));
524 rr.comp->u.complex->generic->elementSpec->which =
525 Z_ElementSpec_elementSetName;
526 rr.comp->u.complex->generic->elementSpec->u.elementSetName =
527 srw_req->recordSchema;
530 rr.stream = assoc->encode;
531 rr.print = assoc->print;
537 rr.output_format = VAL_TEXT_XML;
538 rr.output_format_raw = 0;
541 rr.surrogate_flag = 0;
542 rr.schema = srw_req->recordSchema;
544 if (!assoc->init->bend_fetch)
547 (*assoc->init->bend_fetch)(assoc->backend, &rr);
549 if (rr.errcode && rr.surrogate_flag)
551 int code = yaz_diag_bib1_to_srw(rr.errcode);
552 const char *message = yaz_diag_srw_str(code);
555 len += strlen(message);
557 len += strlen(rr.errstring);
559 record->recordData_buf = odr_malloc(o, len);
561 sprintf(record->recordData_buf, "<diagnostic "
562 "xmlns=\"http://www.loc.gov/zing/srw/diagnostic/\">\n"
563 " <uri>info:srw/diagnostic/1/%d</uri>\n", code);
565 sprintf(record->recordData_buf + strlen(record->recordData_buf),
566 " <details>%s</details>\n", rr.errstring);
568 sprintf(record->recordData_buf + strlen(record->recordData_buf),
569 " <message>%s</message>\n", message);
570 sprintf(record->recordData_buf + strlen(record->recordData_buf),
572 record->recordData_len = strlen(record->recordData_buf);
573 record->recordPosition = odr_intdup(o, pos);
574 record->recordSchema = "info:srw/schema/1/diagnostics-v1.1";
577 else if (rr.len >= 0)
579 record->recordData_buf = rr.record;
580 record->recordData_len = rr.len;
581 record->recordPosition = odr_intdup(o, pos);
583 record->recordSchema = odr_strdup(o, rr.schema);
585 record->recordSchema = 0;
590 static void srw_bend_search(association *assoc, request *req,
591 Z_SRW_searchRetrieveRequest *srw_req,
592 Z_SRW_searchRetrieveResponse *srw_res,
600 yaz_log(LOG_LOG, "Got SRW SearchRetrieveRequest");
601 yaz_log(LOG_DEBUG, "srw_bend_search");
604 yaz_log(LOG_DEBUG, "srw_bend_init");
605 if (!srw_bend_init(assoc))
607 srw_error = 3; /* assume Authentication error */
609 yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
610 &srw_res->num_diagnostics, 1, 0);
615 rr.setname = "default";
618 rr.basenames = &srw_req->database;
621 rr.query = (Z_Query *) odr_malloc (assoc->decode, sizeof(*rr.query));
623 if (srw_req->query_type == Z_SRW_query_type_cql)
625 ext = (Z_External *) odr_malloc(assoc->decode, sizeof(*ext));
626 ext->direct_reference = odr_getoidbystr(assoc->decode,
627 "1.2.840.10003.16.2");
628 ext->indirect_reference = 0;
630 ext->which = Z_External_CQL;
631 ext->u.cql = srw_req->query.cql;
633 rr.query->which = Z_Query_type_104;
634 rr.query->u.type_104 = ext;
636 else if (srw_req->query_type == Z_SRW_query_type_pqf)
638 Z_RPNQuery *RPNquery;
639 YAZ_PQF_Parser pqf_parser;
641 pqf_parser = yaz_pqf_create ();
643 RPNquery = yaz_pqf_parse (pqf_parser, assoc->decode,
649 int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off);
651 yaz_log(LOG_LOG, "%*s^\n", (int)off+4, "");
652 yaz_log(LOG_LOG, "Bad PQF: %s (code %d)\n", pqf_msg, code);
657 rr.query->which = Z_Query_type_1;
658 rr.query->u.type_1 = RPNquery;
660 yaz_pqf_destroy (pqf_parser);
665 if (!srw_error && srw_req->sort_type != Z_SRW_sort_type_none)
668 if (!srw_error && !assoc->init->bend_search)
673 yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %d", srw_error);
674 srw_res->num_diagnostics = 1;
675 srw_res->diagnostics = (Z_SRW_diagnostic *)
676 odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
677 yaz_mk_std_diagnostic(assoc->encode,
678 srw_res->diagnostics, srw_error, 0);
682 rr.stream = assoc->encode;
683 rr.decode = assoc->decode;
684 rr.print = assoc->print;
686 rr.association = assoc;
692 yaz_log_zquery(rr.query);
693 (assoc->init->bend_search)(assoc->backend, &rr);
696 yaz_log(LOG_DEBUG, "bend_search returned Bib-1 code %d", rr.errcode);
697 if (rr.errcode == 109) /* database unavailable */
702 srw_res->num_diagnostics = 1;
703 srw_res->diagnostics = (Z_SRW_diagnostic *)
704 odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
705 yaz_mk_std_diagnostic(assoc->encode, srw_res->diagnostics,
706 yaz_diag_bib1_to_srw (rr.errcode),
708 yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %s",
709 srw_res->diagnostics[0].uri);
713 int number = srw_req->maximumRecords ? *srw_req->maximumRecords : 0;
714 int start = srw_req->startRecord ? *srw_req->startRecord : 1;
716 yaz_log(LOG_LOG, "Request to pack %d+%d out of %d",
717 start, number, rr.hits);
719 srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits);
726 srw_res->num_diagnostics = 1;
727 srw_res->diagnostics = (Z_SRW_diagnostic *)
728 odr_malloc(assoc->encode,
729 sizeof(*srw_res->diagnostics));
730 yaz_mk_std_diagnostic(assoc->encode, srw_res->diagnostics,
736 int packing = Z_SRW_recordPacking_string;
737 if (start + number > rr.hits)
738 number = rr.hits - start + 1;
739 if (srw_req->recordPacking &&
740 !strcmp(srw_req->recordPacking, "xml"))
741 packing = Z_SRW_recordPacking_XML;
742 srw_res->records = (Z_SRW_record *)
743 odr_malloc(assoc->encode,
744 number * sizeof(*srw_res->records));
745 for (i = 0; i<number; i++)
749 srw_res->records[j].recordPacking = packing;
750 srw_res->records[j].recordData_buf = 0;
751 yaz_log(LOG_DEBUG, "srw_bend_fetch %d", i+start);
752 errcode = srw_bend_fetch(assoc, i+start, srw_req,
753 srw_res->records + j);
756 srw_res->num_diagnostics = 1;
757 srw_res->diagnostics = (Z_SRW_diagnostic *)
758 odr_malloc(assoc->encode,
759 sizeof(*srw_res->diagnostics));
761 yaz_mk_std_diagnostic(assoc->encode,
762 srw_res->diagnostics,
763 yaz_diag_bib1_to_srw (errcode),
767 if (srw_res->records[j].recordData_buf)
770 srw_res->num_records = j;
772 srw_res->records = 0;
778 static void srw_bend_explain(association *assoc, request *req,
779 Z_SRW_explainRequest *srw_req,
780 Z_SRW_explainResponse *srw_res,
783 yaz_log(LOG_LOG, "Got SRW ExplainRequest");
787 yaz_log(LOG_DEBUG, "srw_bend_init");
788 if (!srw_bend_init(assoc))
793 if (assoc->init && assoc->init->bend_explain)
797 rr.stream = assoc->encode;
798 rr.decode = assoc->decode;
799 rr.print = assoc->print;
801 rr.database = srw_req->database;
802 rr.schema = "http://explain.z3950.org/dtd/2.0/";
803 (*assoc->init->bend_explain)(assoc->backend, &rr);
806 int packing = Z_SRW_recordPacking_string;
807 if (srw_req->recordPacking &&
808 !strcmp(srw_req->recordPacking, "xml"))
809 packing = Z_SRW_recordPacking_XML;
810 srw_res->record.recordSchema = rr.schema;
811 srw_res->record.recordPacking = packing;
812 srw_res->record.recordData_buf = rr.explain_buf;
813 srw_res->record.recordData_len = strlen(rr.explain_buf);
814 srw_res->record.recordPosition = 0;
820 static void process_http_request(association *assoc, request *req)
822 Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request;
823 ODR o = assoc->encode;
824 int r = 2; /* 2=NOT TAKEN, 1=TAKEN, 0=SOAP TAKEN */
826 Z_SOAP *soap_package = 0;
829 Z_HTTP_Response *hres = 0;
831 char *stylesheet = 0;
832 Z_SRW_diagnostic *diagnostic = 0;
833 int num_diagnostic = 0;
835 if (!strcmp(hreq->path, "/test"))
837 p = z_get_HTTP_Response(o, 200);
838 hres = p->u.HTTP_Response;
839 hres->content_buf = "1234567890\n";
840 hres->content_len = strlen(hres->content_buf);
845 r = yaz_srw_decode(hreq, &sr, &soap_package, assoc->decode, &charset);
846 yaz_log(LOG_DEBUG, "yaz_srw_decode returned %d", r);
848 if (r == 2) /* not taken */
850 r = yaz_sru_decode(hreq, &sr, &soap_package, assoc->decode, &charset,
851 &diagnostic, &num_diagnostic);
852 yaz_log(LOG_DEBUG, "yaz_sru_decode returned %d", r);
854 if (r == 0) /* decode SRW/SRU OK .. */
857 if (sr->which == Z_SRW_searchRetrieve_request)
860 yaz_srw_get(assoc->encode, Z_SRW_searchRetrieve_response);
862 stylesheet = sr->u.request->stylesheet;
865 res->u.response->diagnostics = diagnostic;
866 res->u.response->num_diagnostics = num_diagnostic;
870 srw_bend_search(assoc, req, sr->u.request, res->u.response,
873 if (http_code == 200)
874 soap_package->u.generic->p = res;
876 else if (sr->which == Z_SRW_explain_request)
878 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_explain_response);
879 stylesheet = sr->u.explain_request->stylesheet;
882 res->u.explain_response->diagnostics = diagnostic;
883 res->u.explain_response->num_diagnostics = num_diagnostic;
885 srw_bend_explain(assoc, req, sr->u.explain_request,
886 res->u.explain_response, &http_code);
887 if (http_code == 200)
888 soap_package->u.generic->p = res;
890 else if (sr->which == Z_SRW_scan_request)
892 Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_scan_response);
893 stylesheet = sr->u.scan_request->stylesheet;
896 res->u.scan_response->diagnostics = diagnostic;
897 res->u.scan_response->num_diagnostics = num_diagnostic;
899 yaz_add_srw_diagnostic(o,
900 &res->u.scan_response->diagnostics,
901 &res->u.scan_response->num_diagnostics,
903 if (http_code == 200)
904 soap_package->u.generic->p = res;
908 yaz_log(LOG_LOG, "generate soap error");
910 z_soap_error(assoc->encode, soap_package,
911 "SOAP-ENV:Client", "Bad method", 0);
913 if (http_code == 200 || http_code == 500)
915 static Z_SOAP_Handler soap_handlers[3] = {
917 {"http://www.loc.gov/zing/srw/", 0,
918 (Z_SOAP_fun) yaz_srw_codec},
919 {"http://www.loc.gov/zing/srw/v1.0/", 0,
920 (Z_SOAP_fun) yaz_srw_codec},
926 p = z_get_HTTP_Response(o, 200);
927 hres = p->u.HTTP_Response;
928 ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package,
929 &hres->content_buf, &hres->content_len,
930 soap_handlers, charset, stylesheet);
931 hres->code = http_code;
933 strcpy(ctype, "text/xml");
936 strcat(ctype, "; charset=");
937 strcat(ctype, charset);
939 z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
942 p = z_get_HTTP_Response(o, http_code);
946 p = z_get_HTTP_Response(o, 500);
947 hres = p->u.HTTP_Response;
948 if (!strcmp(hreq->version, "1.0"))
950 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
951 if (v && !strcmp(v, "Keep-Alive"))
955 hres->version = "1.0";
959 const char *v = z_HTTP_header_lookup(hreq->headers, "Connection");
960 if (v && !strcmp(v, "close"))
964 hres->version = "1.1";
968 z_HTTP_header_add(o, &hres->headers, "Connection", "close");
969 assoc->state = ASSOC_DEAD;
970 assoc->cs_get_mask = 0;
975 const char *alive = z_HTTP_header_lookup(hreq->headers, "Keep-Alive");
977 if (alive && isdigit(*alive))
981 if (t < 0 || t > 3600)
983 iochan_settimeout(assoc->client_chan,t);
984 z_HTTP_header_add(o, &hres->headers, "Connection", "Keep-Alive");
986 process_gdu_response(assoc, req, p);
989 static void process_gdu_request(association *assoc, request *req)
991 if (req->gdu_request->which == Z_GDU_Z3950)
994 req->apdu_request = req->gdu_request->u.z3950;
995 if (process_z_request(assoc, req, &msg) < 0)
996 do_close_req(assoc, Z_Close_systemProblem, msg, req);
998 else if (req->gdu_request->which == Z_GDU_HTTP_Request)
999 process_http_request(assoc, req);
1002 do_close_req(assoc, Z_Close_systemProblem, "bad protocol packet", req);
1007 * Initiate request processing.
1009 static int process_z_request(association *assoc, request *req, char **msg)
1015 *msg = "Unknown Error";
1016 assert(req && req->state == REQUEST_IDLE);
1017 if (req->apdu_request->which != Z_APDU_initRequest && !assoc->init)
1019 *msg = "Missing InitRequest";
1022 switch (req->apdu_request->which)
1024 case Z_APDU_initRequest:
1025 iochan_settimeout(assoc->client_chan,
1026 statserv_getcontrol()->idle_timeout * 60);
1027 res = process_initRequest(assoc, req); break;
1028 case Z_APDU_searchRequest:
1029 res = process_searchRequest(assoc, req, &fd); break;
1030 case Z_APDU_presentRequest:
1031 res = process_presentRequest(assoc, req, &fd); break;
1032 case Z_APDU_scanRequest:
1033 if (assoc->init->bend_scan)
1034 res = process_scanRequest(assoc, req, &fd);
1037 *msg = "Cannot handle Scan APDU";
1041 case Z_APDU_extendedServicesRequest:
1042 if (assoc->init->bend_esrequest)
1043 res = process_ESRequest(assoc, req, &fd);
1046 *msg = "Cannot handle Extended Services APDU";
1050 case Z_APDU_sortRequest:
1051 if (assoc->init->bend_sort)
1052 res = process_sortRequest(assoc, req, &fd);
1055 *msg = "Cannot handle Sort APDU";
1060 process_close(assoc, req);
1062 case Z_APDU_deleteResultSetRequest:
1063 if (assoc->init->bend_delete)
1064 res = process_deleteRequest(assoc, req, &fd);
1067 *msg = "Cannot handle Delete APDU";
1071 case Z_APDU_segmentRequest:
1072 if (assoc->init->bend_segment)
1074 res = process_segmentRequest (assoc, req);
1078 *msg = "Cannot handle Segment APDU";
1082 case Z_APDU_triggerResourceControlRequest:
1085 *msg = "Bad APDU received";
1090 yaz_log(LOG_DEBUG, " result immediately available");
1091 retval = process_z_response(assoc, req, res);
1095 yaz_log(LOG_DEBUG, " result unavailble");
1098 else /* no result yet - one will be provided later */
1102 /* Set up an I/O handler for the fd supplied by the backend */
1104 yaz_log(LOG_DEBUG, " establishing handler for result");
1105 req->state = REQUEST_PENDING;
1106 if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT)))
1108 iochan_setdata(chan, assoc);
1115 * Handle message from the backend.
1117 void backend_response(IOCHAN i, int event)
1119 association *assoc = (association *)iochan_getdata(i);
1120 request *req = request_head(&assoc->incoming);
1124 yaz_log(LOG_DEBUG, "backend_response");
1125 assert(assoc && req && req->state != REQUEST_IDLE);
1126 /* determine what it is we're waiting for */
1127 switch (req->apdu_request->which)
1129 case Z_APDU_searchRequest:
1130 res = response_searchRequest(assoc, req, 0, &fd); break;
1132 case Z_APDU_presentRequest:
1133 res = response_presentRequest(assoc, req, 0, &fd); break;
1134 case Z_APDU_scanRequest:
1135 res = response_scanRequest(assoc, req, 0, &fd); break;
1138 yaz_log(LOG_WARN, "Serious programmer's lapse or bug");
1141 if ((res && process_z_response(assoc, req, res) < 0) || fd < 0)
1143 yaz_log(LOG_LOG, "Fatal error when talking to backend");
1144 do_close(assoc, Z_Close_systemProblem, 0);
1148 else if (!res) /* no result yet - try again later */
1150 yaz_log(LOG_DEBUG, " no result yet");
1151 iochan_setfd(i, fd); /* in case fd has changed */
1156 * Encode response, and transfer the request structure to the outgoing queue.
1158 static int process_gdu_response(association *assoc, request *req, Z_GDU *res)
1160 odr_setbuf(assoc->encode, req->response, req->size_response, 1);
1164 if (!z_GDU(assoc->print, &res, 0, 0))
1165 yaz_log(LOG_WARN, "ODR print error: %s",
1166 odr_errmsg(odr_geterror(assoc->print)));
1167 odr_reset(assoc->print);
1169 if (!z_GDU(assoc->encode, &res, 0, 0))
1171 yaz_log(LOG_WARN, "ODR error when encoding PDU: %s [element %s]",
1172 odr_errmsg(odr_geterror(assoc->decode)),
1173 odr_getelement(assoc->decode));
1174 request_release(req);
1177 req->response = odr_getbuf(assoc->encode, &req->len_response,
1178 &req->size_response);
1179 odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */
1180 odr_reset(assoc->encode);
1181 req->state = REQUEST_IDLE;
1182 request_enq(&assoc->outgoing, req);
1183 /* turn the work over to the ir_session handler */
1184 iochan_setflag(assoc->client_chan, EVENT_OUTPUT);
1185 assoc->cs_put_mask = EVENT_OUTPUT;
1186 /* Is there more work to be done? give that to the input handler too */
1188 if (request_head(&assoc->incoming))
1190 yaz_log (LOG_DEBUG, "more work to be done");
1191 iochan_setevent(assoc->client_chan, EVENT_WORK);
1198 * Encode response, and transfer the request structure to the outgoing queue.
1200 static int process_z_response(association *assoc, request *req, Z_APDU *res)
1202 Z_GDU *gres = (Z_GDU *) odr_malloc(assoc->encode, sizeof(*res));
1203 gres->which = Z_GDU_Z3950;
1204 gres->u.z3950 = res;
1206 return process_gdu_response(assoc, req, gres);
1211 * Handle init request.
1212 * At the moment, we don't check the options
1213 * anywhere else in the code - we just try not to do anything that would
1214 * break a naive client. We'll toss 'em into the association block when
1215 * we need them there.
1217 static Z_APDU *process_initRequest(association *assoc, request *reqb)
1219 statserv_options_block *cb = statserv_getcontrol();
1220 Z_InitRequest *req = reqb->apdu_request->u.initRequest;
1221 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_initResponse);
1222 Z_InitResponse *resp = apdu->u.initResponse;
1223 bend_initresult *binitres;
1227 yaz_log(LOG_LOG, "Got initRequest");
1228 if (req->implementationId)
1229 yaz_log(LOG_LOG, "Id: %s", req->implementationId);
1230 if (req->implementationName)
1231 yaz_log(LOG_LOG, "Name: %s", req->implementationName);
1232 if (req->implementationVersion)
1233 yaz_log(LOG_LOG, "Version: %s", req->implementationVersion);
1235 assoc_init_reset(assoc);
1237 assoc->init->auth = req->idAuthentication;
1238 assoc->init->referenceId = req->referenceId;
1240 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
1242 Z_CharSetandLanguageNegotiation *negotiation =
1243 yaz_get_charneg_record (req->otherInfo);
1245 negotiation->which == Z_CharSetandLanguageNegotiation_proposal)
1246 assoc->init->charneg_request = negotiation;
1250 if (!(binitres = (*cb->bend_init)(assoc->init)))
1252 yaz_log(LOG_WARN, "Bad response from backend.");
1256 assoc->backend = binitres->handle;
1257 if ((assoc->init->bend_sort))
1258 yaz_log (LOG_DEBUG, "Sort handler installed");
1259 if ((assoc->init->bend_search))
1260 yaz_log (LOG_DEBUG, "Search handler installed");
1261 if ((assoc->init->bend_present))
1262 yaz_log (LOG_DEBUG, "Present handler installed");
1263 if ((assoc->init->bend_esrequest))
1264 yaz_log (LOG_DEBUG, "ESRequest handler installed");
1265 if ((assoc->init->bend_delete))
1266 yaz_log (LOG_DEBUG, "Delete handler installed");
1267 if ((assoc->init->bend_scan))
1268 yaz_log (LOG_DEBUG, "Scan handler installed");
1269 if ((assoc->init->bend_segment))
1270 yaz_log (LOG_DEBUG, "Segment handler installed");
1272 resp->referenceId = req->referenceId;
1274 /* let's tell the client what we can do */
1275 if (ODR_MASK_GET(req->options, Z_Options_search))
1277 ODR_MASK_SET(resp->options, Z_Options_search);
1278 strcat(options, "srch");
1280 if (ODR_MASK_GET(req->options, Z_Options_present))
1282 ODR_MASK_SET(resp->options, Z_Options_present);
1283 strcat(options, " prst");
1285 if (ODR_MASK_GET(req->options, Z_Options_delSet) &&
1286 assoc->init->bend_delete)
1288 ODR_MASK_SET(resp->options, Z_Options_delSet);
1289 strcat(options, " del");
1291 if (ODR_MASK_GET(req->options, Z_Options_extendedServices) &&
1292 assoc->init->bend_esrequest)
1294 ODR_MASK_SET(resp->options, Z_Options_extendedServices);
1295 strcat (options, " extendedServices");
1297 if (ODR_MASK_GET(req->options, Z_Options_namedResultSets))
1299 ODR_MASK_SET(resp->options, Z_Options_namedResultSets);
1300 strcat(options, " namedresults");
1302 if (ODR_MASK_GET(req->options, Z_Options_scan) && assoc->init->bend_scan)
1304 ODR_MASK_SET(resp->options, Z_Options_scan);
1305 strcat(options, " scan");
1307 if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations))
1309 ODR_MASK_SET(resp->options, Z_Options_concurrentOperations);
1310 strcat(options, " concurrop");
1312 if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort)
1314 ODR_MASK_SET(resp->options, Z_Options_sort);
1315 strcat(options, " sort");
1318 if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)
1319 && assoc->init->charneg_response)
1321 Z_OtherInformation **p;
1322 Z_OtherInformationUnit *p0;
1324 yaz_oi_APDU(apdu, &p);
1326 if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) {
1327 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1329 p0->which = Z_OtherInfo_externallyDefinedInfo;
1330 p0->information.externallyDefinedInfo =
1331 assoc->init->charneg_response;
1333 ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
1334 strcat(options, " negotiation");
1337 ODR_MASK_SET(resp->options, Z_Options_triggerResourceCtrl);
1339 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
1341 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
1342 assoc->version = 1; /* 1 & 2 are equivalent */
1344 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2))
1346 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2);
1349 if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3))
1351 ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
1355 yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options);
1356 assoc->maximumRecordSize = *req->maximumRecordSize;
1357 if (assoc->maximumRecordSize > control_block->maxrecordsize)
1358 assoc->maximumRecordSize = control_block->maxrecordsize;
1359 assoc->preferredMessageSize = *req->preferredMessageSize;
1360 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
1361 assoc->preferredMessageSize = assoc->maximumRecordSize;
1363 resp->preferredMessageSize = &assoc->preferredMessageSize;
1364 resp->maximumRecordSize = &assoc->maximumRecordSize;
1366 resp->implementationId = odr_prepend(assoc->encode,
1367 assoc->init->implementation_id,
1368 resp->implementationId);
1370 resp->implementationName = odr_prepend(assoc->encode,
1371 assoc->init->implementation_name,
1372 odr_prepend(assoc->encode, "GFS", resp->implementationName));
1374 version = odr_strdup(assoc->encode, "$Revision: 1.32 $");
1375 if (strlen(version) > 10) /* check for unexpanded CVS strings */
1376 version[strlen(version)-2] = '\0';
1377 resp->implementationVersion = odr_prepend(assoc->encode,
1378 assoc->init->implementation_version,
1379 odr_prepend(assoc->encode, &version[11],
1380 resp->implementationVersion));
1382 if (binitres->errcode)
1384 yaz_log(LOG_LOG, "Connection rejected by backend.");
1386 assoc->state = ASSOC_DEAD;
1387 resp->userInformationField = init_diagnostics(assoc->encode,
1389 binitres->errstring);
1392 assoc->state = ASSOC_UP;
1397 * Diagnostic in default format, to be returned as either a surrogate
1398 * or non-surrogate diagnostic in the context of an open session, or
1399 * as User-information when an Init is refused.
1401 static Z_DefaultDiagFormat *justdiag(ODR odr, int error, char *addinfo)
1403 int *err = odr_intdup(odr, error);
1404 Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
1405 odr_malloc (odr, sizeof(*dr));
1407 yaz_log(LOG_LOG, "[%d] %s%s%s", error, diagbib1_str(error),
1408 addinfo ? " -- " : "", addinfo ? addinfo : "");
1410 dr->diagnosticSetId =
1411 yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1);
1412 dr->condition = err;
1413 dr->which = Z_DefaultDiagFormat_v2Addinfo;
1414 dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : "");
1419 * Set the specified `errcode' and `errstring' into a UserInfo-1
1420 * external to be returned to the client in accordance with Z35.90
1421 * Implementor Agreement 5 (Returning diagnostics in an InitResponse):
1422 * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html
1424 static Z_External *init_diagnostics(ODR odr, int error, char *addinfo)
1428 Z_OtherInformation *u;
1429 Z_OtherInformationUnit *l;
1430 Z_DiagnosticFormat *d;
1431 Z_DiagnosticFormat_s *e;
1433 x = (Z_External*) odr_malloc(odr, sizeof *x);
1435 x->indirect_reference = 0;
1436 oid.proto = PROTO_Z3950;
1437 oid.oclass = CLASS_USERINFO;
1438 oid.value = VAL_USERINFO1;
1439 x->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1440 x->which = Z_External_userInfo1;
1442 u = odr_malloc(odr, sizeof *u);
1444 u->num_elements = 1;
1445 u->list = (Z_OtherInformationUnit**) odr_malloc(odr, sizeof *u->list);
1446 u->list[0] = (Z_OtherInformationUnit*) odr_malloc(odr, sizeof *u->list[0]);
1449 l->which = Z_OtherInfo_externallyDefinedInfo;
1451 x2 = (Z_External*) odr_malloc(odr, sizeof *x);
1452 l->information.externallyDefinedInfo = x2;
1454 x2->indirect_reference = 0;
1455 oid.oclass = CLASS_DIAGSET;
1456 oid.value = VAL_DIAG1;
1457 x2->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid));
1458 x2->which = Z_External_diag1;
1460 d = (Z_DiagnosticFormat*) odr_malloc(odr, sizeof *d);
1463 d->elements = (Z_DiagnosticFormat_s**) odr_malloc (odr, sizeof *d->elements);
1464 d->elements[0] = (Z_DiagnosticFormat_s*) odr_malloc (odr, sizeof *d->elements[0]);
1467 e->which = Z_DiagnosticFormat_s_defaultDiagRec;
1468 e->u.defaultDiagRec = justdiag(odr, error, addinfo);
1474 * nonsurrogate diagnostic record.
1476 static Z_Records *diagrec(association *assoc, int error, char *addinfo)
1478 Z_Records *rec = (Z_Records *)
1479 odr_malloc (assoc->encode, sizeof(*rec));
1480 rec->which = Z_Records_NSD;
1481 rec->u.nonSurrogateDiagnostic = justdiag(assoc->encode, error, addinfo);
1486 * surrogate diagnostic.
1488 static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname,
1489 int error, char *addinfo)
1491 Z_NamePlusRecord *rec = (Z_NamePlusRecord *)
1492 odr_malloc (assoc->encode, sizeof(*rec));
1493 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1495 yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
1496 rec->databaseName = dbname;
1497 rec->which = Z_NamePlusRecord_surrogateDiagnostic;
1498 rec->u.surrogateDiagnostic = drec;
1499 drec->which = Z_DiagRec_defaultFormat;
1500 drec->u.defaultFormat = justdiag(assoc->encode, error, addinfo);
1506 * multiple nonsurrogate diagnostics.
1508 static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo)
1510 Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs));
1511 int *err = odr_intdup(assoc->encode, error);
1512 Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp));
1513 Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
1514 Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *)
1515 odr_malloc (assoc->encode, sizeof(*rec));
1517 yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : "");
1519 recs->num_diagRecs = 1;
1520 recs->diagRecs = recp;
1522 drec->which = Z_DiagRec_defaultFormat;
1523 drec->u.defaultFormat = rec;
1525 rec->diagnosticSetId =
1526 yaz_oidval_to_z3950oid (assoc->encode, CLASS_DIAGSET, VAL_BIB1);
1527 rec->condition = err;
1529 rec->which = Z_DefaultDiagFormat_v2Addinfo;
1530 rec->u.v2Addinfo = odr_strdup (assoc->encode, addinfo ? addinfo : "");
1534 static Z_Records *pack_records(association *a, char *setname, int start,
1535 int *num, Z_RecordComposition *comp,
1536 int *next, int *pres, oid_value format,
1537 Z_ReferenceId *referenceId,
1540 int recno, total_length = 0, toget = *num, dumped_records = 0;
1541 Z_Records *records =
1542 (Z_Records *) odr_malloc (a->encode, sizeof(*records));
1543 Z_NamePlusRecordList *reclist =
1544 (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist));
1545 Z_NamePlusRecord **list =
1546 (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget);
1548 records->which = Z_Records_DBOSD;
1549 records->u.databaseOrSurDiagnostics = reclist;
1550 reclist->num_records = 0;
1551 reclist->records = list;
1552 *pres = Z_PresentStatus_success;
1556 yaz_log(LOG_LOG, "Request to pack %d+%d+%s", start, toget, setname);
1557 yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize,
1558 a->maximumRecordSize);
1559 for (recno = start; reclist->num_records < toget; recno++)
1562 Z_NamePlusRecord *thisrec;
1563 int this_length = 0;
1565 * we get the number of bytes allocated on the stream before any
1566 * allocation done by the backend - this should give us a reasonable
1567 * idea of the total size of the data so far.
1569 total_length = odr_total(a->encode) - dumped_records;
1575 freq.last_in_set = 0;
1576 freq.setname = setname;
1577 freq.surrogate_flag = 0;
1578 freq.number = recno;
1580 freq.request_format = format;
1581 freq.request_format_raw = oid;
1582 freq.output_format = format;
1583 freq.output_format_raw = 0;
1584 freq.stream = a->encode;
1585 freq.print = a->print;
1586 freq.referenceId = referenceId;
1588 (*a->init->bend_fetch)(a->backend, &freq);
1589 /* backend should be able to signal whether error is system-wide
1590 or only pertaining to current record */
1593 if (!freq.surrogate_flag)
1596 *pres = Z_PresentStatus_failure;
1597 /* for 'present request out of range',
1598 set addinfo to record position if not set */
1599 if (freq.errcode == 13 && freq.errstring == 0)
1601 sprintf (s, "%d", recno);
1604 return diagrec(a, freq.errcode, freq.errstring);
1606 reclist->records[reclist->num_records] =
1607 surrogatediagrec(a, freq.basename, freq.errcode,
1609 reclist->num_records++;
1610 *next = freq.last_in_set ? 0 : recno + 1;
1614 this_length = freq.len;
1616 this_length = odr_total(a->encode) - total_length - dumped_records;
1617 yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d dumped=%d",
1618 this_length, total_length, dumped_records);
1619 if (a->preferredMessageSize > 0 &&
1620 this_length + total_length > a->preferredMessageSize)
1622 /* record is small enough, really */
1623 if (this_length <= a->preferredMessageSize && recno > start)
1625 yaz_log(LOG_DEBUG, " Dropped last normal-sized record");
1626 *pres = Z_PresentStatus_partial_2;
1629 /* record can only be fetched by itself */
1630 if (this_length < a->maximumRecordSize)
1632 yaz_log(LOG_DEBUG, " Record > prefmsgsz");
1635 yaz_log(LOG_DEBUG, " Dropped it");
1636 reclist->records[reclist->num_records] =
1637 surrogatediagrec(a, freq.basename, 16, 0);
1638 reclist->num_records++;
1639 *next = freq.last_in_set ? 0 : recno + 1;
1640 dumped_records += this_length;
1644 else /* too big entirely */
1646 yaz_log(LOG_LOG, "Record > maxrcdsz this=%d max=%d", this_length, a->maximumRecordSize);
1647 reclist->records[reclist->num_records] =
1648 surrogatediagrec(a, freq.basename, 17, 0);
1649 reclist->num_records++;
1650 *next = freq.last_in_set ? 0 : recno + 1;
1651 dumped_records += this_length;
1656 if (!(thisrec = (Z_NamePlusRecord *)
1657 odr_malloc(a->encode, sizeof(*thisrec))))
1659 if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
1660 strlen(freq.basename) + 1)))
1662 strcpy(thisrec->databaseName, freq.basename);
1663 thisrec->which = Z_NamePlusRecord_databaseRecord;
1665 if (freq.output_format_raw)
1667 struct oident *ident = oid_getentbyoid(freq.output_format_raw);
1668 freq.output_format = ident->value;
1670 thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format,
1671 freq.record, freq.len);
1672 if (!thisrec->u.databaseRecord)
1674 reclist->records[reclist->num_records] = thisrec;
1675 reclist->num_records++;
1676 *next = freq.last_in_set ? 0 : recno + 1;
1678 *num = reclist->num_records;
1682 static Z_APDU *process_searchRequest(association *assoc, request *reqb,
1685 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1686 bend_search_rr *bsrr =
1687 (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr));
1689 yaz_log(LOG_LOG, "Got SearchRequest.");
1691 bsrr->request = reqb;
1692 bsrr->association = assoc;
1693 bsrr->referenceId = req->referenceId;
1694 save_referenceId (reqb, bsrr->referenceId);
1696 yaz_log (LOG_LOG, "ResultSet '%s'", req->resultSetName);
1697 if (req->databaseNames)
1700 for (i = 0; i < req->num_databaseNames; i++)
1701 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1703 yaz_log_zquery(req->query);
1705 if (assoc->init->bend_search)
1707 bsrr->setname = req->resultSetName;
1708 bsrr->replace_set = *req->replaceIndicator;
1709 bsrr->num_bases = req->num_databaseNames;
1710 bsrr->basenames = req->databaseNames;
1711 bsrr->query = req->query;
1712 bsrr->stream = assoc->encode;
1713 nmem_transfer(bsrr->stream->mem, reqb->request_mem);
1714 bsrr->decode = assoc->decode;
1715 bsrr->print = assoc->print;
1718 bsrr->errstring = NULL;
1719 bsrr->search_info = NULL;
1720 (assoc->init->bend_search)(assoc->backend, bsrr);
1724 return response_searchRequest(assoc, reqb, bsrr, fd);
1727 int bend_searchresponse(void *handle, bend_search_rr *bsrr) {return 0;}
1730 * Prepare a searchresponse based on the backend results. We probably want
1731 * to look at making the fetching of records nonblocking as well, but
1732 * so far, we'll keep things simple.
1733 * If bsrt is null, that means we're called in response to a communications
1734 * event, and we'll have to get the response for ourselves.
1736 static Z_APDU *response_searchRequest(association *assoc, request *reqb,
1737 bend_search_rr *bsrt, int *fd)
1739 Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
1740 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1741 Z_SearchResponse *resp = (Z_SearchResponse *)
1742 odr_malloc (assoc->encode, sizeof(*resp));
1743 int *nulint = odr_intdup (assoc->encode, 0);
1744 bool_t *sr = odr_intdup(assoc->encode, 1);
1745 int *next = odr_intdup(assoc->encode, 0);
1746 int *none = odr_intdup(assoc->encode, Z_SearchResponse_none);
1748 apdu->which = Z_APDU_searchResponse;
1749 apdu->u.searchResponse = resp;
1750 resp->referenceId = req->referenceId;
1751 resp->additionalSearchInfo = 0;
1752 resp->otherInfo = 0;
1754 if (!bsrt && !bend_searchresponse(assoc->backend, bsrt))
1756 yaz_log(LOG_FATAL, "Bad result from backend");
1759 else if (bsrt->errcode)
1761 resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring);
1762 resp->resultCount = nulint;
1763 resp->numberOfRecordsReturned = nulint;
1764 resp->nextResultSetPosition = nulint;
1765 resp->searchStatus = nulint;
1766 resp->resultSetStatus = none;
1767 resp->presentStatus = 0;
1771 int *toget = odr_intdup(assoc->encode, 0);
1772 int *presst = odr_intdup(assoc->encode, 0);
1773 Z_RecordComposition comp, *compp = 0;
1775 yaz_log (LOG_LOG, "resultCount: %d", bsrt->hits);
1778 resp->resultCount = &bsrt->hits;
1780 comp.which = Z_RecordComp_simple;
1781 /* how many records does the user agent want, then? */
1782 if (bsrt->hits <= *req->smallSetUpperBound)
1784 *toget = bsrt->hits;
1785 if ((comp.u.simple = req->smallSetElementSetNames))
1788 else if (bsrt->hits < *req->largeSetLowerBound)
1790 *toget = *req->mediumSetPresentNumber;
1791 if (*toget > bsrt->hits)
1792 *toget = bsrt->hits;
1793 if ((comp.u.simple = req->mediumSetElementSetNames))
1799 if (*toget && !resp->records)
1804 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1807 form = prefformat->value;
1808 resp->records = pack_records(assoc, req->resultSetName, 1,
1809 toget, compp, next, presst, form, req->referenceId,
1810 req->preferredRecordSyntax);
1813 resp->numberOfRecordsReturned = toget;
1814 resp->nextResultSetPosition = next;
1815 resp->searchStatus = sr;
1816 resp->resultSetStatus = 0;
1817 resp->presentStatus = presst;
1821 if (*resp->resultCount)
1823 resp->numberOfRecordsReturned = nulint;
1824 resp->nextResultSetPosition = next;
1825 resp->searchStatus = sr;
1826 resp->resultSetStatus = 0;
1827 resp->presentStatus = 0;
1830 resp->additionalSearchInfo = bsrt->search_info;
1835 * Maybe we got a little over-friendly when we designed bend_fetch to
1836 * get only one record at a time. Some backends can optimise multiple-record
1837 * fetches, and at any rate, there is some overhead involved in
1838 * all that selecting and hopping around. Problem is, of course, that the
1839 * frontend can't know ahead of time how many records it'll need to
1840 * fill the negotiated PDU size. Annoying. Segmentation or not, Z/SR
1841 * is downright lousy as a bulk data transfer protocol.
1843 * To start with, we'll do the fetching of records from the backend
1844 * in one operation: To save some trips in and out of the event-handler,
1845 * and to simplify the interface to pack_records. At any rate, asynch
1846 * operation is more fun in operations that have an unpredictable execution
1847 * speed - which is normally more true for search than for present.
1849 static Z_APDU *process_presentRequest(association *assoc, request *reqb,
1852 Z_PresentRequest *req = reqb->apdu_request->u.presentRequest;
1856 Z_PresentResponse *resp;
1860 yaz_log(LOG_LOG, "Got PresentRequest.");
1862 if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax)))
1865 form = prefformat->value;
1866 resp = (Z_PresentResponse *)odr_malloc (assoc->encode, sizeof(*resp));
1868 resp->presentStatus = odr_intdup(assoc->encode, 0);
1869 if (assoc->init->bend_present)
1871 bend_present_rr *bprr = (bend_present_rr *)
1872 nmem_malloc (reqb->request_mem, sizeof(*bprr));
1873 bprr->setname = req->resultSetId;
1874 bprr->start = *req->resultSetStartPoint;
1875 bprr->number = *req->numberOfRecordsRequested;
1876 bprr->format = form;
1877 bprr->comp = req->recordComposition;
1878 bprr->referenceId = req->referenceId;
1879 bprr->stream = assoc->encode;
1880 bprr->print = assoc->print;
1881 bprr->request = reqb;
1882 bprr->association = assoc;
1884 bprr->errstring = NULL;
1885 (*assoc->init->bend_present)(assoc->backend, bprr);
1891 resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
1892 *resp->presentStatus = Z_PresentStatus_failure;
1895 apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1896 next = odr_intdup(assoc->encode, 0);
1897 num = odr_intdup(assoc->encode, 0);
1899 apdu->which = Z_APDU_presentResponse;
1900 apdu->u.presentResponse = resp;
1901 resp->referenceId = req->referenceId;
1902 resp->otherInfo = 0;
1906 *num = *req->numberOfRecordsRequested;
1908 pack_records(assoc, req->resultSetId, *req->resultSetStartPoint,
1909 num, req->recordComposition, next, resp->presentStatus,
1910 form, req->referenceId, req->preferredRecordSyntax);
1914 resp->numberOfRecordsReturned = num;
1915 resp->nextResultSetPosition = next;
1921 * Scan was implemented rather in a hurry, and with support for only the basic
1922 * elements of the service in the backend API. Suggestions are welcome.
1924 static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd)
1926 Z_ScanRequest *req = reqb->apdu_request->u.scanRequest;
1927 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
1928 Z_ScanResponse *res = (Z_ScanResponse *)
1929 odr_malloc (assoc->encode, sizeof(*res));
1930 int *scanStatus = odr_intdup(assoc->encode, Z_Scan_failure);
1931 int *numberOfEntriesReturned = odr_intdup(assoc->encode, 0);
1932 Z_ListEntries *ents = (Z_ListEntries *)
1933 odr_malloc (assoc->encode, sizeof(*ents));
1934 Z_DiagRecs *diagrecs_p = NULL;
1936 bend_scan_rr *bsrr = (bend_scan_rr *)
1937 odr_malloc (assoc->encode, sizeof(*bsrr));
1938 struct scan_entry *save_entries;
1940 yaz_log(LOG_LOG, "Got ScanRequest");
1942 apdu->which = Z_APDU_scanResponse;
1943 apdu->u.scanResponse = res;
1944 res->referenceId = req->referenceId;
1946 /* if step is absent, set it to 0 */
1947 res->stepSize = odr_intdup(assoc->encode, 0);
1949 *res->stepSize = *req->stepSize;
1951 res->scanStatus = scanStatus;
1952 res->numberOfEntriesReturned = numberOfEntriesReturned;
1953 res->positionOfTerm = 0;
1954 res->entries = ents;
1955 ents->num_entries = 0;
1956 ents->entries = NULL;
1957 ents->num_nonsurrogateDiagnostics = 0;
1958 ents->nonsurrogateDiagnostics = NULL;
1959 res->attributeSet = 0;
1962 if (req->databaseNames)
1965 for (i = 0; i < req->num_databaseNames; i++)
1966 yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
1968 bsrr->num_bases = req->num_databaseNames;
1969 bsrr->basenames = req->databaseNames;
1970 bsrr->num_entries = *req->numberOfTermsRequested;
1971 bsrr->term = req->termListAndStartPoint;
1972 bsrr->referenceId = req->referenceId;
1973 bsrr->stream = assoc->encode;
1974 bsrr->print = assoc->print;
1975 bsrr->step_size = res->stepSize;
1977 /* Note that version 2.0 of YAZ and older did not set entries ..
1978 We do now. And when we do it's easier to extend the scan entry
1979 We know that if the scan handler did set entries, it will
1980 not know of new member display_term.
1982 if (bsrr->num_entries > 0)
1985 bsrr->entries = odr_malloc(assoc->decode, sizeof(*bsrr->entries) *
1987 for (i = 0; i<bsrr->num_entries; i++)
1989 bsrr->entries[i].term = 0;
1990 bsrr->entries[i].occurrences = 0;
1991 bsrr->entries[i].errcode = 0;
1992 bsrr->entries[i].errstring = 0;
1993 bsrr->entries[i].display_term = 0;
1996 save_entries = bsrr->entries; /* save it so we can compare later */
1998 if (req->attributeSet &&
1999 (attset = oid_getentbyoid(req->attributeSet)) &&
2000 (attset->oclass == CLASS_ATTSET || attset->oclass == CLASS_GENERAL))
2001 bsrr->attributeset = attset->value;
2003 bsrr->attributeset = VAL_NONE;
2004 log_scan_term (req->termListAndStartPoint, bsrr->attributeset);
2005 bsrr->term_position = req->preferredPositionInResponse ?
2006 *req->preferredPositionInResponse : 1;
2007 ((int (*)(void *, bend_scan_rr *))
2008 (*assoc->init->bend_scan))(assoc->backend, bsrr);
2010 diagrecs_p = diagrecs(assoc, bsrr->errcode, bsrr->errstring);
2014 Z_Entry **tab = (Z_Entry **)
2015 odr_malloc (assoc->encode, sizeof(*tab) * bsrr->num_entries);
2017 if (bsrr->status == BEND_SCAN_PARTIAL)
2018 *scanStatus = Z_Scan_partial_5;
2020 *scanStatus = Z_Scan_success;
2021 ents->entries = tab;
2022 ents->num_entries = bsrr->num_entries;
2023 res->numberOfEntriesReturned = &ents->num_entries;
2024 res->positionOfTerm = &bsrr->term_position;
2025 for (i = 0; i < bsrr->num_entries; i++)
2031 tab[i] = e = (Z_Entry *)odr_malloc(assoc->encode, sizeof(*e));
2032 if (bsrr->entries[i].occurrences >= 0)
2034 e->which = Z_Entry_termInfo;
2035 e->u.termInfo = t = (Z_TermInfo *)
2036 odr_malloc(assoc->encode, sizeof(*t));
2037 t->suggestedAttributes = 0;
2039 if (save_entries == bsrr->entries &&
2040 bsrr->entries[i].display_term)
2042 /* the entries was NOT set by the handler. So it's
2043 safe to test for new member display_term. It is
2046 t->displayTerm = odr_strdup(assoc->encode,
2047 bsrr->entries[i].display_term);
2049 t->alternativeTerm = 0;
2050 t->byAttributes = 0;
2051 t->otherTermInfo = 0;
2052 t->globalOccurrences = &bsrr->entries[i].occurrences;
2053 t->term = (Z_Term *)
2054 odr_malloc(assoc->encode, sizeof(*t->term));
2055 t->term->which = Z_Term_general;
2056 t->term->u.general = o =
2057 (Odr_oct *)odr_malloc(assoc->encode, sizeof(Odr_oct));
2058 o->buf = (unsigned char *)
2059 odr_malloc(assoc->encode, o->len = o->size =
2060 strlen(bsrr->entries[i].term));
2061 memcpy(o->buf, bsrr->entries[i].term, o->len);
2062 yaz_log(LOG_DEBUG, " term #%d: '%s' (%d)", i,
2063 bsrr->entries[i].term, bsrr->entries[i].occurrences);
2067 Z_DiagRecs *drecs = diagrecs (assoc,
2068 bsrr->entries[i].errcode,
2069 bsrr->entries[i].errstring);
2070 assert (drecs->num_diagRecs == 1);
2071 e->which = Z_Entry_surrogateDiagnostic;
2072 assert (drecs->diagRecs[0]);
2073 e->u.surrogateDiagnostic = drecs->diagRecs[0];
2079 ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs;
2080 ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs;
2085 static Z_APDU *process_sortRequest(association *assoc, request *reqb,
2088 Z_SortRequest *req = reqb->apdu_request->u.sortRequest;
2089 Z_SortResponse *res = (Z_SortResponse *)
2090 odr_malloc (assoc->encode, sizeof(*res));
2091 bend_sort_rr *bsrr = (bend_sort_rr *)
2092 odr_malloc (assoc->encode, sizeof(*bsrr));
2094 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2096 yaz_log(LOG_LOG, "Got SortRequest.");
2098 bsrr->num_input_setnames = req->num_inputResultSetNames;
2099 bsrr->input_setnames = req->inputResultSetNames;
2100 bsrr->referenceId = req->referenceId;
2101 bsrr->output_setname = req->sortedResultSetName;
2102 bsrr->sort_sequence = req->sortSequence;
2103 bsrr->stream = assoc->encode;
2104 bsrr->print = assoc->print;
2106 bsrr->sort_status = Z_SortResponse_failure;
2108 bsrr->errstring = 0;
2110 (*assoc->init->bend_sort)(assoc->backend, bsrr);
2112 res->referenceId = bsrr->referenceId;
2113 res->sortStatus = odr_intdup(assoc->encode, bsrr->sort_status);
2114 res->resultSetStatus = 0;
2117 Z_DiagRecs *dr = diagrecs (assoc, bsrr->errcode, bsrr->errstring);
2118 res->diagnostics = dr->diagRecs;
2119 res->num_diagnostics = dr->num_diagRecs;
2123 res->num_diagnostics = 0;
2124 res->diagnostics = 0;
2126 res->resultCount = 0;
2129 apdu->which = Z_APDU_sortResponse;
2130 apdu->u.sortResponse = res;
2134 static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
2137 Z_DeleteResultSetRequest *req =
2138 reqb->apdu_request->u.deleteResultSetRequest;
2139 Z_DeleteResultSetResponse *res = (Z_DeleteResultSetResponse *)
2140 odr_malloc (assoc->encode, sizeof(*res));
2141 bend_delete_rr *bdrr = (bend_delete_rr *)
2142 odr_malloc (assoc->encode, sizeof(*bdrr));
2143 Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu));
2145 yaz_log(LOG_LOG, "Got DeleteRequest.");
2147 bdrr->num_setnames = req->num_resultSetList;
2148 bdrr->setnames = req->resultSetList;
2149 bdrr->stream = assoc->encode;
2150 bdrr->print = assoc->print;
2151 bdrr->function = *req->deleteFunction;
2152 bdrr->referenceId = req->referenceId;
2154 if (bdrr->num_setnames > 0)
2157 bdrr->statuses = (int*)
2158 odr_malloc(assoc->encode, sizeof(*bdrr->statuses) *
2159 bdrr->num_setnames);
2160 for (i = 0; i < bdrr->num_setnames; i++)
2161 bdrr->statuses[i] = 0;
2163 (*assoc->init->bend_delete)(assoc->backend, bdrr);
2165 res->referenceId = req->referenceId;
2167 res->deleteOperationStatus = odr_intdup(assoc->encode,bdrr->delete_status);
2169 res->deleteListStatuses = 0;
2170 if (bdrr->num_setnames > 0)
2173 res->deleteListStatuses = (Z_ListStatuses *)
2174 odr_malloc(assoc->encode, sizeof(*res->deleteListStatuses));
2175 res->deleteListStatuses->num = bdrr->num_setnames;
2176 res->deleteListStatuses->elements =
2178 odr_malloc (assoc->encode,
2179 sizeof(*res->deleteListStatuses->elements) *
2180 bdrr->num_setnames);
2181 for (i = 0; i<bdrr->num_setnames; i++)
2183 res->deleteListStatuses->elements[i] =
2185 odr_malloc (assoc->encode,
2186 sizeof(**res->deleteListStatuses->elements));
2187 res->deleteListStatuses->elements[i]->status = bdrr->statuses+i;
2188 res->deleteListStatuses->elements[i]->id =
2189 odr_strdup (assoc->encode, bdrr->setnames[i]);
2193 res->numberNotDeleted = 0;
2194 res->bulkStatuses = 0;
2195 res->deleteMessage = 0;
2198 apdu->which = Z_APDU_deleteResultSetResponse;
2199 apdu->u.deleteResultSetResponse = res;
2203 static void process_close(association *assoc, request *reqb)
2205 Z_Close *req = reqb->apdu_request->u.close;
2206 static char *reasons[] =
2213 "securityViolation",
2220 yaz_log(LOG_LOG, "Got Close, reason %s, message %s",
2221 reasons[*req->closeReason], req->diagnosticInformation ?
2222 req->diagnosticInformation : "NULL");
2223 if (assoc->version < 3) /* to make do_force respond with close */
2225 do_close_req(assoc, Z_Close_finished,
2226 "Association terminated by client", reqb);
2229 void save_referenceId (request *reqb, Z_ReferenceId *refid)
2233 reqb->len_refid = refid->len;
2234 reqb->refid = (char *)nmem_malloc (reqb->request_mem, refid->len);
2235 memcpy (reqb->refid, refid->buf, refid->len);
2239 reqb->len_refid = 0;
2244 void bend_request_send (bend_association a, bend_request req, Z_APDU *res)
2246 process_z_response (a, req, res);
2249 bend_request bend_request_mk (bend_association a)
2251 request *nreq = request_get (&a->outgoing);
2252 nreq->request_mem = nmem_create ();
2256 Z_ReferenceId *bend_request_getid (ODR odr, bend_request req)
2261 id = (Odr_oct *)odr_malloc (odr, sizeof(*odr));
2262 id->buf = (unsigned char *)odr_malloc (odr, req->len_refid);
2263 id->len = id->size = req->len_refid;
2264 memcpy (id->buf, req->refid, req->len_refid);
2268 void bend_request_destroy (bend_request *req)
2270 nmem_destroy((*req)->request_mem);
2271 request_release(*req);
2275 int bend_backend_respond (bend_association a, bend_request req)
2279 r = process_z_request (a, req, &msg);
2281 yaz_log (LOG_WARN, "%s", msg);
2285 void bend_request_setdata(bend_request r, void *p)
2290 void *bend_request_getdata(bend_request r)
2292 return r->clientData;
2295 static Z_APDU *process_segmentRequest (association *assoc, request *reqb)
2297 bend_segment_rr req;
2299 req.segment = reqb->apdu_request->u.segmentRequest;
2300 req.stream = assoc->encode;
2301 req.decode = assoc->decode;
2302 req.print = assoc->print;
2303 req.association = assoc;
2305 (*assoc->init->bend_segment)(assoc->backend, &req);
2310 static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd)
2312 bend_esrequest_rr esrequest;
2314 Z_ExtendedServicesRequest *req =
2315 reqb->apdu_request->u.extendedServicesRequest;
2316 Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_extendedServicesResponse);
2318 Z_ExtendedServicesResponse *resp = apdu->u.extendedServicesResponse;
2320 yaz_log(LOG_DEBUG,"inside Process esRequest");
2322 esrequest.esr = reqb->apdu_request->u.extendedServicesRequest;
2323 esrequest.stream = assoc->encode;
2324 esrequest.decode = assoc->decode;
2325 esrequest.print = assoc->print;
2326 esrequest.errcode = 0;
2327 esrequest.errstring = NULL;
2328 esrequest.request = reqb;
2329 esrequest.association = assoc;
2330 esrequest.taskPackage = 0;
2331 esrequest.referenceId = req->referenceId;
2333 (*assoc->init->bend_esrequest)(assoc->backend, &esrequest);
2335 /* If the response is being delayed, return NULL */
2336 if (esrequest.request == NULL)
2339 resp->referenceId = req->referenceId;
2341 if (esrequest.errcode == -1)
2343 /* Backend service indicates request will be processed */
2344 yaz_log(LOG_DEBUG,"Request could be processed...Accepted !");
2345 *resp->operationStatus = Z_ExtendedServicesResponse_accepted;
2347 else if (esrequest.errcode == 0)
2349 /* Backend service indicates request will be processed */
2350 yaz_log(LOG_DEBUG,"Request could be processed...Done !");
2351 *resp->operationStatus = Z_ExtendedServicesResponse_done;
2355 Z_DiagRecs *diagRecs = diagrecs (assoc, esrequest.errcode,
2356 esrequest.errstring);
2358 /* Backend indicates error, request will not be processed */
2359 yaz_log(LOG_DEBUG,"Request could not be processed...failure !");
2360 *resp->operationStatus = Z_ExtendedServicesResponse_failure;
2361 resp->num_diagnostics = diagRecs->num_diagRecs;
2362 resp->diagnostics = diagRecs->diagRecs;
2364 /* Do something with the members of bend_extendedservice */
2365 if (esrequest.taskPackage)
2366 resp->taskPackage = z_ext_record (assoc->encode, VAL_EXTENDED,
2367 (const char *) esrequest.taskPackage,
2369 yaz_log(LOG_DEBUG,"Send the result apdu");