/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2009 Index Data
+ * Copyright (C) 1995-2010 Index Data
* See the file LICENSE for details.
*/
/**
static void process_gdu_request(association *assoc, request *req);
static int process_z_request(association *assoc, request *req, char **msg);
-void backend_response(IOCHAN i, int event);
static int process_gdu_response(association *assoc, request *req, Z_GDU *res);
static int process_z_response(association *assoc, request *req, Z_APDU *res);
static Z_APDU *process_initRequest(association *assoc, request *reqb);
static Z_External *init_diagnostics(ODR odr, int errcode,
const char *errstring);
-static Z_APDU *process_searchRequest(association *assoc, request *reqb,
- int *fd);
+static Z_APDU *process_searchRequest(association *assoc, request *reqb);
static Z_APDU *response_searchRequest(association *assoc, request *reqb,
- bend_search_rr *bsrr, int *fd);
-static Z_APDU *process_presentRequest(association *assoc, request *reqb,
- int *fd);
-static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd);
-static Z_APDU *process_sortRequest(association *assoc, request *reqb, int *fd);
+ bend_search_rr *bsrr);
+static Z_APDU *process_presentRequest(association *assoc, request *reqb);
+static Z_APDU *process_scanRequest(association *assoc, request *reqb);
+static Z_APDU *process_sortRequest(association *assoc, request *reqb);
static void process_close(association *assoc, request *reqb);
-void save_referenceId(request *reqb, Z_ReferenceId *refid);
-static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
- int *fd);
+static Z_APDU *process_deleteRequest(association *assoc, request *reqb);
static Z_APDU *process_segmentRequest(association *assoc, request *reqb);
-
-static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd);
+static Z_APDU *process_ESRequest(association *assoc, request *reqb);
/* dynamic logging levels */
static int logbits_set = 0;
}
}
-
-
static void wr_diag(WRBUF w, int error, const char *addinfo)
{
wrbuf_printf(w, "ERROR %d+", error);
wrbuf_puts_replace_char(w, diagbib1_str(error), ' ', '_');
- if (addinfo){
+ if (addinfo)
+ {
wrbuf_puts(w, "+");
wrbuf_puts_replace_char(w, addinfo, ' ', '_');
}
-
wrbuf_puts(w, " ");
}
-
/*
* Create and initialize a new association-handle.
* channel : iochannel for the current line.
static void do_close(association *a, int reason, char *message)
{
request *req = request_get(&a->outgoing);
- do_close_req (a, reason, message, req);
+ do_close_req(a, reason, message, req);
}
{
if (assoc->state != ASSOC_UP)
{
- yaz_log(YLOG_DEBUG, "Final timeout - closing connection.");
+ yaz_log(log_session, "Timeout. Closing connection");
/* do we need to lod this at all */
cs_close(conn);
destroy_association(assoc);
}
else
{
- yaz_log(log_sessiondetail,
- "Session idle too long. Sending close.");
+ yaz_log(log_sessiondetail, "Timeout. Sending Z39.50 Close");
do_close(assoc, Z_Close_lackOfActivity, 0);
}
return;
static void assoc_init_reset(association *assoc)
{
- xfree (assoc->init);
+ xfree(assoc->init);
assoc->init = (bend_initrequest *) xmalloc(sizeof(*assoc->init));
assoc->init->stream = assoc->encode;
{
Z_IdAuthentication *auth = (Z_IdAuthentication *)
odr_malloc(assoc->decode, sizeof(*auth));
- int len;
+ size_t len;
len = strlen(sr->username) + 1;
if (sr->password)
static int ccl2pqf(ODR odr, const Odr_oct *ccl, CCL_bibset bibset,
- bend_search_rr *bsrr) {
+ bend_search_rr *bsrr)
+{
char *ccl0;
struct ccl_rpn_node *node;
int errcode, pos;
ccl0 = odr_strdupn(odr, (char*) ccl->buf, ccl->len);
- if ((node = ccl_find_str(bibset, ccl0, &errcode, &pos)) == 0) {
+ if ((node = ccl_find_str(bibset, ccl0, &errcode, &pos)) == 0)
+ {
bsrr->errstring = (char*) ccl_err_msg(errcode);
return YAZ_SRW_QUERY_SYNTAX_ERROR; /* Query syntax error */
}
static void srw_bend_search(association *assoc, request *req,
Z_SRW_PDU *sr,
- Z_SRW_searchRetrieveResponse *srw_res,
+ Z_SRW_PDU *res,
int *http_code)
{
+ Z_SRW_searchRetrieveResponse *srw_res = res->u.response;
int srw_error = 0;
Z_External *ext;
Z_SRW_searchRetrieveRequest *srw_req = sr->u.request;
rr.partial_resultset = 0;
rr.query = (Z_Query *) odr_malloc(assoc->decode, sizeof(*rr.query));
rr.query->u.type_1 = 0;
+ rr.extra_args = sr->extra_args;
+ rr.extra_response_data = 0;
if (srw_req->query_type == Z_SRW_query_type_cql)
{
rr.stream = assoc->encode;
rr.decode = assoc->decode;
rr.print = assoc->print;
- rr.request = req;
if ( srw_req->sort.sortKeys )
rr.srw_sortKeys = odr_strdup(assoc->encode,
srw_req->sort.sortKeys );
rr.association = assoc;
- rr.fd = 0;
rr.hits = 0;
rr.errcode = 0;
rr.errstring = 0;
bprr->stream = assoc->encode;
bprr->referenceId = 0;
bprr->print = assoc->print;
- bprr->request = req;
bprr->association = assoc;
bprr->errcode = 0;
bprr->errstring = NULL;
(*assoc->init->bend_present)(assoc->backend, bprr);
- if (!bprr->request)
- return;
if (bprr->errcode)
{
srw_error = yaz_diag_bib1_to_srw(bprr->errcode);
srw_res->records = 0;
}
}
+ if (rr.extra_response_data)
+ {
+ res->extraResponseData_buf = rr.extra_response_data;
+ res->extraResponseData_len = strlen(rr.extra_response_data);
+ }
if (rr.estimated_hit_count || rr.partial_resultset)
{
yaz_add_srw_diagnostic(
int num_diagnostic = 0;
const char *host = z_HTTP_header_lookup(hreq->headers, "Host");
+ yaz_log(log_request, "%s %s HTTP/%s", hreq->method, hreq->path, hreq->version);
if (!control_association(assoc, host, 0))
{
p = z_get_HTTP_Response(o, 404);
}
else
{
- srw_bend_search(assoc, req, sr, res->u.response,
- &http_code);
+ srw_bend_search(assoc, req, sr, res, &http_code);
}
if (http_code == 200)
soap_package->u.generic->p = res;
*/
static int process_z_request(association *assoc, request *req, char **msg)
{
- int fd = -1;
Z_APDU *res;
int retval;
case Z_APDU_initRequest:
res = process_initRequest(assoc, req); break;
case Z_APDU_searchRequest:
- res = process_searchRequest(assoc, req, &fd); break;
+ res = process_searchRequest(assoc, req); break;
case Z_APDU_presentRequest:
- res = process_presentRequest(assoc, req, &fd); break;
+ res = process_presentRequest(assoc, req); break;
case Z_APDU_scanRequest:
if (assoc->init->bend_scan)
- res = process_scanRequest(assoc, req, &fd);
+ res = process_scanRequest(assoc, req);
else
{
*msg = "Cannot handle Scan APDU";
break;
case Z_APDU_extendedServicesRequest:
if (assoc->init->bend_esrequest)
- res = process_ESRequest(assoc, req, &fd);
+ res = process_ESRequest(assoc, req);
else
{
*msg = "Cannot handle Extended Services APDU";
break;
case Z_APDU_sortRequest:
if (assoc->init->bend_sort)
- res = process_sortRequest(assoc, req, &fd);
+ res = process_sortRequest(assoc, req);
else
{
*msg = "Cannot handle Sort APDU";
return 0;
case Z_APDU_deleteResultSetRequest:
if (assoc->init->bend_delete)
- res = process_deleteRequest(assoc, req, &fd);
+ res = process_deleteRequest(assoc, req);
else
{
*msg = "Cannot handle Delete APDU";
yaz_log(YLOG_DEBUG, " result immediately available");
retval = process_z_response(assoc, req, res);
}
- else if (fd < 0)
+ else
{
yaz_log(YLOG_DEBUG, " result unavailble");
- retval = 0;
- }
- else /* no result yet - one will be provided later */
- {
- IOCHAN chan;
-
- /* Set up an I/O handler for the fd supplied by the backend */
-
- yaz_log(YLOG_DEBUG, " establishing handler for result");
- req->state = REQUEST_PENDING;
- if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT, 0)))
- abort();
- iochan_setdata(chan, assoc);
- retval = 0;
+ retval = -1;
}
return retval;
}
/*
- * Handle message from the backend.
- */
-void backend_response(IOCHAN i, int event)
-{
- association *assoc = (association *)iochan_getdata(i);
- request *req = request_head(&assoc->incoming);
- Z_APDU *res;
- int fd;
-
- yaz_log(YLOG_DEBUG, "backend_response");
- assert(assoc && req && req->state != REQUEST_IDLE);
- /* determine what it is we're waiting for */
- switch (req->apdu_request->which)
- {
- case Z_APDU_searchRequest:
- res = response_searchRequest(assoc, req, 0, &fd); break;
-#if 0
- case Z_APDU_presentRequest:
- res = response_presentRequest(assoc, req, 0, &fd); break;
- case Z_APDU_scanRequest:
- res = response_scanRequest(assoc, req, 0, &fd); break;
-#endif
- default:
- yaz_log(YLOG_FATAL, "Serious programmer's lapse or bug");
- abort();
- }
- if ((res && process_z_response(assoc, req, res) < 0) || fd < 0)
- {
- yaz_log(YLOG_WARN, "Fatal error when talking to backend");
- do_close(assoc, Z_Close_systemProblem, 0);
- iochan_destroy(i);
- return;
- }
- else if (!res) /* no result yet - try again later */
- {
- yaz_log(YLOG_DEBUG, " no result yet");
- iochan_setfd(i, fd); /* in case fd has changed */
- }
-}
-
-/*
* Encode response, and transfer the request structure to the outgoing queue.
*/
static int process_gdu_response(association *assoc, request *req, Z_GDU *res)
binitres->errstring);
*resp->result = 0;
}
+ else
+ assoc->state = ASSOC_UP;
+
if (log_request)
{
if (!req->idAuthentication)
if (freq.errcode == YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE &&
freq.errstring == 0)
{
- sprintf (s, "%d", recno);
+ sprintf(s, "%d", recno);
freq.errstring = s;
}
if (errcode)
return records;
}
-static Z_APDU *process_searchRequest(association *assoc, request *reqb,
- int *fd)
+static Z_APDU *process_searchRequest(association *assoc, request *reqb)
{
Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
bend_search_rr *bsrr =
(bend_search_rr *)nmem_malloc(reqb->request_mem, sizeof(*bsrr));
yaz_log(log_requestdetail, "Got SearchRequest.");
- bsrr->fd = fd;
- bsrr->request = reqb;
bsrr->association = assoc;
bsrr->referenceId = req->referenceId;
- save_referenceId (reqb, bsrr->referenceId);
bsrr->srw_sortKeys = 0;
bsrr->srw_setname = 0;
bsrr->srw_setnameIdleTime = 0;
bsrr->estimated_hit_count = 0;
bsrr->partial_resultset = 0;
+ bsrr->extra_args = 0;
+ bsrr->extra_response_data = 0;
yaz_log (log_requestdetail, "ResultSet '%s'", req->resultSetName);
if (req->databaseNames)
if (!bsrr->errcode)
(assoc->init->bend_search)(assoc->backend, bsrr);
- if (!bsrr->request) /* backend not ready with the search response */
- return 0; /* should not be used any more */
}
else
{
/* FIXME - make a diagnostic for it */
yaz_log(YLOG_WARN,"Search not supported ?!?!");
}
- return response_searchRequest(assoc, reqb, bsrr, fd);
+ return response_searchRequest(assoc, reqb, bsrr);
}
-int bend_searchresponse(void *handle, bend_search_rr *bsrr) {return 0;}
-
/*
* Prepare a searchresponse based on the backend results. We probably want
* to look at making the fetching of records nonblocking as well, but
* event, and we'll have to get the response for ourselves.
*/
static Z_APDU *response_searchRequest(association *assoc, request *reqb,
- bend_search_rr *bsrt, int *fd)
+ bend_search_rr *bsrt)
{
Z_SearchRequest *req = reqb->apdu_request->u.searchRequest;
Z_APDU *apdu = (Z_APDU *)odr_malloc(assoc->encode, sizeof(*apdu));
resp->referenceId = req->referenceId;
resp->additionalSearchInfo = 0;
resp->otherInfo = 0;
- *fd = -1;
- if (!bsrt && !bend_searchresponse(assoc->backend, bsrt))
+ if (!bsrt)
{
yaz_log(YLOG_FATAL, "Bad result from backend");
return 0;
comp.which = Z_RecordComp_simple;
/* how many records does the user agent want, then? */
- if (bsrt->hits <= *req->smallSetUpperBound)
+ if (bsrt->hits < 0)
+ *toget = 0;
+ else if (bsrt->hits <= *req->smallSetUpperBound)
{
*toget = bsrt->hits;
if ((comp.u.simple = req->smallSetElementSetNames))
bprr->referenceId = req->referenceId;
bprr->stream = assoc->encode;
bprr->print = assoc->print;
- bprr->request = reqb;
bprr->association = assoc;
bprr->errcode = 0;
bprr->errstring = NULL;
(*assoc->init->bend_present)(assoc->backend, bprr);
- if (!bprr->request)
- return 0;
if (bprr->errcode)
{
resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
int i;
WRBUF wr = wrbuf_alloc();
- for (i = 0 ; i < req->num_databaseNames; i++){
+ for (i = 0 ; i < req->num_databaseNames; i++)
+ {
if (i)
wrbuf_printf(wr, "+");
wrbuf_puts(wr, req->databaseNames[i]);
* operation is more fun in operations that have an unpredictable execution
* speed - which is normally more true for search than for present.
*/
-static Z_APDU *process_presentRequest(association *assoc, request *reqb,
- int *fd)
+static Z_APDU *process_presentRequest(association *assoc, request *reqb)
{
Z_PresentRequest *req = reqb->apdu_request->u.presentRequest;
Z_APDU *apdu;
bprr->referenceId = req->referenceId;
bprr->stream = assoc->encode;
bprr->print = assoc->print;
- bprr->request = reqb;
bprr->association = assoc;
bprr->errcode = 0;
bprr->errstring = NULL;
(*assoc->init->bend_present)(assoc->backend, bprr);
- if (!bprr->request)
- return 0; /* should not happen */
if (bprr->errcode)
{
resp->records = diagrec(assoc, bprr->errcode, bprr->errstring);
* Scan was implemented rather in a hurry, and with support for only the basic
* elements of the service in the backend API. Suggestions are welcome.
*/
-static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd)
+static Z_APDU *process_scanRequest(association *assoc, request *reqb)
{
Z_ScanRequest *req = reqb->apdu_request->u.scanRequest;
Z_APDU *apdu = (Z_APDU *)odr_malloc(assoc->encode, sizeof(*apdu));
return apdu;
}
-static Z_APDU *process_sortRequest(association *assoc, request *reqb,
- int *fd)
+static Z_APDU *process_sortRequest(association *assoc, request *reqb)
{
int i;
Z_SortRequest *req = reqb->apdu_request->u.sortRequest;
return apdu;
}
-static Z_APDU *process_deleteRequest(association *assoc, request *reqb,
- int *fd)
+static Z_APDU *process_deleteRequest(association *assoc, request *reqb)
{
int i;
Z_DeleteResultSetRequest *req =
yaz_log(log_request,"Close OK");
}
-void save_referenceId(request *reqb, Z_ReferenceId *refid)
-{
- if (refid)
- {
- reqb->len_refid = refid->len;
- reqb->refid = (char *)nmem_malloc(reqb->request_mem, refid->len);
- memcpy(reqb->refid, refid->buf, refid->len);
- }
- else
- {
- reqb->len_refid = 0;
- reqb->refid = NULL;
- }
-}
-
-void bend_request_send(bend_association a, bend_request req, Z_APDU *res)
-{
- process_z_response(a, req, res);
-}
-
-bend_request bend_request_mk(bend_association a)
-{
- request *nreq = request_get(&a->outgoing);
- nreq->request_mem = nmem_create();
- return nreq;
-}
-
-Z_ReferenceId *bend_request_getid(ODR odr, bend_request req)
-{
- Z_ReferenceId *id;
- if (!req->refid)
- return 0;
- id = (Odr_oct *)odr_malloc(odr, sizeof(*odr));
- id->buf = (unsigned char *)odr_malloc(odr, req->len_refid);
- id->len = id->size = req->len_refid;
- memcpy(id->buf, req->refid, req->len_refid);
- return id;
-}
-
-void bend_request_destroy(bend_request *req)
-{
- nmem_destroy((*req)->request_mem);
- request_release(*req);
- *req = NULL;
-}
-
-int bend_backend_respond(bend_association a, bend_request req)
-{
- char *msg;
- int r;
- r = process_z_request(a, req, &msg);
- if (r < 0)
- yaz_log(YLOG_WARN, "%s", msg);
- return r;
-}
-
-void bend_request_setdata(bend_request r, void *p)
-{
- r->clientData = p;
-}
-
-void *bend_request_getdata(bend_request r)
-{
- return r->clientData;
-}
-
static Z_APDU *process_segmentRequest(association *assoc, request *reqb)
{
bend_segment_rr req;
return 0;
}
-static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd)
+static Z_APDU *process_ESRequest(association *assoc, request *reqb)
{
bend_esrequest_rr esrequest;
const char *ext_name = "unknown";
esrequest.print = assoc->print;
esrequest.errcode = 0;
esrequest.errstring = NULL;
- esrequest.request = reqb;
esrequest.association = assoc;
esrequest.taskPackage = 0;
esrequest.referenceId = req->referenceId;
-
if (esrequest.esr && esrequest.esr->taskSpecificParameters)
{
(*assoc->init->bend_esrequest)(assoc->backend, &esrequest);
- /* If the response is being delayed, return NULL */
- if (esrequest.request == NULL)
- return(NULL);
-
resp->referenceId = req->referenceId;
if (esrequest.errcode == -1)