+ if (res)
+ {
+ logf(LOG_DEBUG, " result immediately available");
+ return process_response(assoc, req, res);
+ }
+ else if (fd < 0)
+ {
+ logf(LOG_WARN, " bad result");
+ return -1;
+ }
+ else /* no result yet - one will be provided later */
+ {
+ IOCHAN chan;
+
+ /* Set up an I/O handler for the fd supplied by the backend */
+
+ logf(LOG_DEBUG, " establishing handler for result");
+ req->state = REQUEST_PENDING;
+ if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT)))
+ abort();
+ iochan_setdata(chan, assoc);
+ return 0;
+ }
+}
+
+/*
+ * Handle message from the backend.
+ */
+void backend_response(IOCHAN i, int event)
+{
+ association *assoc = iochan_getdata(i);
+ request *req = request_head(&assoc->incoming);
+ Z_APDU *res;
+ int fd;
+
+ logf(LOG_DEBUG, "backend_response");
+ assert(assoc && req && req->state != REQUEST_IDLE);
+ /* determine what it is we're waiting for */
+ switch (req->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:
+ logf(LOG_WARN, "Serious programmer's lapse or bug");
+ abort();
+ }
+ if ((res && process_response(assoc, req, res) < 0) || fd < 0)
+ {
+ logf(LOG_LOG, "Fatal error when talking to backend");
+ cs_close(assoc->client_link);
+ destroy_association(assoc);
+ iochan_destroy(assoc->client_chan);
+ iochan_destroy(i);
+ return;
+ }
+ else if (!res) /* no result yet - try again later */
+ {
+ logf(LOG_DEBUG, " no result yet");
+ iochan_setfd(i, fd); /* in case fd has changed */
+ }