Modded session.c seshigh.c
authorSebastian Hammer <quinn@indexdata.com>
Wed, 15 Mar 1995 16:02:10 +0000 (16:02 +0000)
committerSebastian Hammer <quinn@indexdata.com>
Wed, 15 Mar 1995 16:02:10 +0000 (16:02 +0000)
server/seshigh.c [new file with mode: 0644]

diff --git a/server/seshigh.c b/server/seshigh.c
new file mode 100644 (file)
index 0000000..2a7a4c6
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 1994, Index Data I/S 
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: seshigh.c,v $
+ * Revision 1.1  1995-03-15 16:02:10  quinn
+ * Modded session.c seshigh.c
+ *
+ * Revision 1.10  1995/03/15  15:18:51  quinn
+ * Little changes to better support nonblocking I/O
+ * Added backend.h
+ *
+ * Revision 1.9  1995/03/15  13:20:23  adam
+ * Yet another bug fix in very dummy_database...
+ *
+ * Revision 1.8  1995/03/15  11:18:17  quinn
+ * Smallish changes.
+ *
+ * Revision 1.7  1995/03/15  09:40:15  adam
+ * Bug fixes in dummy_database_...
+ *
+ * Revision 1.6  1995/03/15  09:08:30  adam
+ * Take care of preferredMessageSize.
+ *
+ * Revision 1.5  1995/03/15  08:37:44  quinn
+ * Now we're pretty much set for nonblocking I/O.
+ *
+ * Revision 1.4  1995/03/15  08:27:20  adam
+ * PresentRequest changed to return MARC records from file 'dummy-records'.
+ *
+ * Revision 1.3  1995/03/14  16:59:48  quinn
+ * Bug-fixes
+ *
+ * Revision 1.2  1995/03/14  11:30:14  quinn
+ * Works better now.
+ *
+ * Revision 1.1  1995/03/14  10:28:01  quinn
+ * More work on demo server.
+ *
+ *
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <comstack.h>
+#include <eventl.h>
+#include <session.h>
+#include <proto.h>
+
+#include <backend.h>
+
+#include <iso2709.h>
+
+#define ENCODE_BUFFER_SIZE 10000
+
+static int process_apdu(IOCHAN chan);
+static int process_initRequest(IOCHAN client, Z_InitRequest *req);
+static int process_searchRequest(IOCHAN client, Z_SearchRequest *req);
+static int process_presentRequest(IOCHAN client, Z_PresentRequest *req);
+
+association *create_association(IOCHAN channel, COMSTACK link)
+{
+    association *new;
+
+    if (!(new = malloc(sizeof(*new))))
+       return 0;
+    new->client_chan = channel;
+    new->client_link = link;
+    if (!(new->decode = odr_createmem(ODR_DECODE)) ||
+       !(new->encode = odr_createmem(ODR_ENCODE)))
+       return 0;
+    if (!(new->encode_buffer = malloc(ENCODE_BUFFER_SIZE)))
+       return 0;
+    odr_setbuf(new->encode, new->encode_buffer, ENCODE_BUFFER_SIZE);
+    new->state = ASSOC_UNINIT;
+    new->input_buffer = 0;
+    new->input_buffer_len = 0;
+    return new;
+}
+
+void destroy_association(association *h)
+{
+    odr_destroy(h->decode);
+    odr_destroy(h->encode);
+    free(h->encode_buffer);
+    free(h);
+}
+
+void ir_session(IOCHAN h, int event)
+{
+    int res;
+    association *assoc = iochan_getdata(h);
+    COMSTACK conn = assoc->client_link;
+
+    if (event == EVENT_INPUT)
+    {
+       assert(assoc && conn);
+       res = cs_get(conn, &assoc->input_buffer, &assoc->input_buffer_len);
+       switch (res)
+       {
+           case 0: case -1: /* connection closed by peer */
+               fprintf(stderr, "Closed connection\n");
+               cs_close(conn);
+               destroy_association(assoc);
+               iochan_destroy(h);
+               return;
+           case 1:  /* incomplete read */
+               return;
+           default: /* data! */
+               assoc->input_apdu_len = res;
+               if (process_apdu(h) < 0)
+               {
+                   fprintf(stderr, "Bad data from peer\n");
+                   cs_close(conn);
+                   destroy_association(assoc);
+                   iochan_destroy(h);
+               }
+               else if (cs_more(conn)) /* arrange to be called again */
+                   iochan_setevent(h, EVENT_INPUT);
+       }
+    }
+    else if (event == EVENT_OUTPUT)
+    {
+       switch (res = cs_put(conn, assoc->encode_buffer, assoc->encoded_len))
+       {
+           case -1:
+               fprintf(stderr, "Closed connection\n");
+               cs_close(conn);
+               destroy_association(assoc);
+               iochan_destroy(h);
+           case 0: /* all sent */
+               iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset */
+               break;
+           case 1: /* partial send */
+               break; /* we'll get called again */
+       }
+    }
+    else if (event == EVENT_EXCEPT)
+    {
+       fprintf(stderr, "Exception on line\n");
+       cs_close(conn);
+       destroy_association(assoc);
+       iochan_destroy(h);
+    }
+}
+
+static int process_apdu(IOCHAN chan)
+{
+    Z_APDU *apdu;
+    int res;
+    association *assoc = iochan_getdata(chan);
+
+    odr_setbuf(assoc->decode, assoc->input_buffer, assoc->input_apdu_len);
+    if (!z_APDU(assoc->decode, &apdu, 0))
+    {
+       odr_perror(assoc->decode, "Incoming APDU");
+       return -1;
+    }
+    switch (apdu->which)
+    {
+       case Z_APDU_initRequest:
+           res = process_initRequest(chan, apdu->u.initRequest); break;
+       case Z_APDU_searchRequest:
+           res = process_searchRequest(chan, apdu->u.searchRequest); break;
+       case Z_APDU_presentRequest:
+           res = process_presentRequest(chan, apdu->u.presentRequest); break;
+       default:
+           fprintf(stderr, "Bad APDU\n");
+           return -1;
+    }
+    return res;
+}
+
+static int process_initRequest(IOCHAN client, Z_InitRequest *req)
+{
+    Z_APDU apdu, *apdup;
+    Z_InitResponse resp;
+    bool_t result = 1;
+    association *assoc = iochan_getdata(client);
+    bend_initrequest binitreq;
+    bend_initresult *binitres;
+
+    fprintf(stderr, "Got initRequest.\n");
+    if (req->implementationId)
+       fprintf(stderr, "Id:        %s\n", req->implementationId);
+    if (req->implementationName)
+       fprintf(stderr, "Name:      %s\n", req->implementationName);
+    if (req->implementationVersion)
+       fprintf(stderr, "Version:   %s\n", req->implementationVersion);
+
+    binitreq.configname = "default-config";
+    if (!(binitres = bend_init(&binitreq)) || binitres->errcode)
+    {
+       fprintf(stderr, "Bad response from backend\n");
+       return -1;
+    }
+
+    apdup = &apdu;
+    apdu.which = Z_APDU_initResponse;
+    apdu.u.initResponse = &resp;
+    resp.referenceId = req->referenceId;
+    resp.options = req->options; /* should check these */
+    resp.protocolVersion = req->protocolVersion;
+    assoc->maximumRecordSize = *req->maximumRecordSize;
+    if (assoc->maximumRecordSize > ENCODE_BUFFER_SIZE - 500)
+       assoc->maximumRecordSize = ENCODE_BUFFER_SIZE - 500;
+    assoc->preferredMessageSize = *req->preferredMessageSize;
+    if (assoc->preferredMessageSize > assoc->maximumRecordSize)
+       assoc->preferredMessageSize = assoc->maximumRecordSize;
+    resp.preferredMessageSize = &assoc->preferredMessageSize;
+    resp.maximumRecordSize = &assoc->maximumRecordSize;
+    resp.result = &result;
+    resp.implementationId = "YAZ";
+    resp.implementationName = "YAZ/Simple asynchronous test server";
+    resp.implementationVersion = "$Revision: 1.1 $";
+    resp.userInformationField = 0;
+    if (!z_APDU(assoc->encode, &apdup, 0))
+    {
+       odr_perror(assoc->encode, "Encode init");
+       return -1;
+    }
+    odr_getbuf(assoc->encode, &assoc->encoded_len);
+    iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
+    return 0;
+}
+
+static Z_Records *diagrec(int error, char *addinfo)
+{
+    static Z_Records rec;
+    static Odr_oid bib1[] = { 1, 2, 3, 4, 5, -1 };
+    static Z_DiagRec dr;
+    static int err;
+
+    fprintf(stderr, "Diagnostic: %d -- %s\n", error, addinfo);
+    err = error;
+    rec.which = Z_Records_NSD;
+    rec.u.nonSurrogateDiagnostic = &dr;
+    dr.diagnosticSetId = bib1;
+    dr.condition = &err;
+    dr.addinfo = addinfo;
+    return &rec;
+}
+
+static int process_searchRequest(IOCHAN client, Z_SearchRequest *req)
+{
+    Z_APDU apdu, *apdup;
+    Z_SearchResponse resp;
+    association *assoc = iochan_getdata(client);
+    int nulint = 0;
+    bool_t sr = 1;
+    int nrp;
+    bend_searchrequest bsrq;
+    bend_searchresult *bsrt;
+
+    fprintf(stderr, "Got SearchRequest.\n");
+    apdup = &apdu;
+    apdu.which = Z_APDU_searchResponse;
+    apdu.u.searchResponse = &resp;
+    resp.referenceId = req->referenceId;
+
+    bsrq.setname = req->resultSetName;
+    bsrq.replace_set = *req->replaceIndicator;
+    bsrq.num_bases = req->num_databaseNames;
+    bsrq.basenames = req->databaseNames;
+    bsrq.query = req->query;
+
+    if (!(bsrt = bend_search(&bsrq)))
+       return -1;
+    else if (bsrt->errcode)
+       resp.records = diagrec(bsrt->errcode, bsrt->errstring);
+    else
+       resp.records = 0;
+
+    resp.resultCount = &bsrt->hits;
+    resp.numberOfRecordsReturned = &nulint;
+    nrp = bsrt->hits ? 1 : 0;
+    resp.nextResultSetPosition = &nrp;
+    resp.searchStatus = &sr;
+    resp.resultSetStatus = &sr;
+    resp.presentStatus = 0;
+
+    if (!z_APDU(assoc->encode, &apdup, 0))
+    {
+       odr_perror(assoc->encode, "Encode init");
+       return -1;
+    }
+    odr_getbuf(assoc->encode, &assoc->encoded_len);
+    iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
+    return 0;
+}
+
+static Z_Records *dummy_database_records (int start, int no_requested, 
+                                         int *no_returned, 
+                                          int preferredMessageSize)
+{
+    static Z_Records rec;
+    static int no_records = 0;
+    static Z_NamePlusRecordList z_nprl;
+    int i, size;
+    static Z_NamePlusRecord **records;
+    
+    rec.which = Z_Records_DBOSD;
+    rec.u.databaseOrSurDiagnostics = &z_nprl;
+    if (!no_records)
+    {
+        FILE *inf;
+        char *buf;
+        Odr_external *oep;
+        
+        inf = fopen ("dummy-records", "r");
+        if (!inf)
+            return NULL;
+        records = malloc (sizeof(*records) * 50);
+        assert (records);
+        for (i=0; i<50; i++)
+        {
+            buf = iso2709_read (inf);
+            if (!buf)
+                break;
+            records[i] = malloc (sizeof(**records));
+            assert (records[i]);
+            records[i]->databaseName = NULL;
+            records[i]->which = Z_NamePlusRecord_databaseRecord;
+            oep = records[i]->u.databaseRecord = 
+                malloc (sizeof(*oep));
+            assert (oep);
+            oep->direct_reference = NULL;
+            oep->indirect_reference = NULL;
+            oep->descriptor = NULL;
+            oep->which = ODR_EXTERNAL_octet;
+            oep->u.octet_aligned = malloc (sizeof(*oep->u.octet_aligned));
+            assert (oep->u.octet_aligned);
+            oep->u.octet_aligned->size = oep->u.octet_aligned->len
+                = strlen(buf);
+            oep->u.octet_aligned->buf = buf;
+        }
+        no_records = i;
+        fclose (inf);
+    }
+    if (no_records < start + no_requested)
+        return NULL;
+    
+    z_nprl.records = records + start -1;
+    for (size = 0, i = 0; i<no_requested; i++)
+    {
+        if (z_nprl.records[i]->which == Z_NamePlusRecord_databaseRecord)
+            size += z_nprl.records[i]->u.databaseRecord->u.octet_aligned->size;
+        printf ("size=%d\n", size);
+        if (size > preferredMessageSize)
+            break;
+    }
+    if (i == 0)
+        return NULL;
+    z_nprl.num_records = *no_returned = i;
+    return &rec;
+}
+
+static int process_presentRequest(IOCHAN client, Z_PresentRequest *req)
+{
+    Z_APDU apdu, *apdup;
+    Z_PresentResponse resp;
+    association *assoc = iochan_getdata(client);
+    int nrr = 1;
+
+    fprintf(stderr, "Got PresentRequest.\n");
+    apdup = &apdu;
+    apdu.which = Z_APDU_presentResponse;
+    apdu.u.presentResponse = &resp;
+    resp.referenceId = req->referenceId;
+
+    resp.numberOfRecordsReturned = &nrr;
+    resp.nextResultSetPosition = &nrr;
+    resp.presentStatus = &nrr;
+
+#if 0
+    resp.records = diagrec(1, "Waiting for records from Adam.  :)");
+#else
+    if (!(resp.records = dummy_database_records (*req->resultSetStartPoint,
+        *req->numberOfRecordsRequested, &nrr, assoc->preferredMessageSize)))
+        resp.records = diagrec (1, "No records from Adam. Sorry");
+    printf ("nrr=%d\n", nrr);
+#endif
+
+    if (!z_APDU(assoc->encode, &apdup, 0))
+    {
+       odr_perror(assoc->encode, "Encode init");
+       return -1;
+    }
+    odr_getbuf(assoc->encode, &assoc->encoded_len);
+    iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
+    return 0;
+}