2 * Copyright (C) 1994, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.1 1995-03-15 16:02:10 quinn
8 * Modded session.c seshigh.c
10 * Revision 1.10 1995/03/15 15:18:51 quinn
11 * Little changes to better support nonblocking I/O
14 * Revision 1.9 1995/03/15 13:20:23 adam
15 * Yet another bug fix in very dummy_database...
17 * Revision 1.8 1995/03/15 11:18:17 quinn
20 * Revision 1.7 1995/03/15 09:40:15 adam
21 * Bug fixes in dummy_database_...
23 * Revision 1.6 1995/03/15 09:08:30 adam
24 * Take care of preferredMessageSize.
26 * Revision 1.5 1995/03/15 08:37:44 quinn
27 * Now we're pretty much set for nonblocking I/O.
29 * Revision 1.4 1995/03/15 08:27:20 adam
30 * PresentRequest changed to return MARC records from file 'dummy-records'.
32 * Revision 1.3 1995/03/14 16:59:48 quinn
35 * Revision 1.2 1995/03/14 11:30:14 quinn
38 * Revision 1.1 1995/03/14 10:28:01 quinn
39 * More work on demo server.
56 #define ENCODE_BUFFER_SIZE 10000
58 static int process_apdu(IOCHAN chan);
59 static int process_initRequest(IOCHAN client, Z_InitRequest *req);
60 static int process_searchRequest(IOCHAN client, Z_SearchRequest *req);
61 static int process_presentRequest(IOCHAN client, Z_PresentRequest *req);
63 association *create_association(IOCHAN channel, COMSTACK link)
67 if (!(new = malloc(sizeof(*new))))
69 new->client_chan = channel;
70 new->client_link = link;
71 if (!(new->decode = odr_createmem(ODR_DECODE)) ||
72 !(new->encode = odr_createmem(ODR_ENCODE)))
74 if (!(new->encode_buffer = malloc(ENCODE_BUFFER_SIZE)))
76 odr_setbuf(new->encode, new->encode_buffer, ENCODE_BUFFER_SIZE);
77 new->state = ASSOC_UNINIT;
78 new->input_buffer = 0;
79 new->input_buffer_len = 0;
83 void destroy_association(association *h)
85 odr_destroy(h->decode);
86 odr_destroy(h->encode);
87 free(h->encode_buffer);
91 void ir_session(IOCHAN h, int event)
94 association *assoc = iochan_getdata(h);
95 COMSTACK conn = assoc->client_link;
97 if (event == EVENT_INPUT)
99 assert(assoc && conn);
100 res = cs_get(conn, &assoc->input_buffer, &assoc->input_buffer_len);
103 case 0: case -1: /* connection closed by peer */
104 fprintf(stderr, "Closed connection\n");
106 destroy_association(assoc);
109 case 1: /* incomplete read */
112 assoc->input_apdu_len = res;
113 if (process_apdu(h) < 0)
115 fprintf(stderr, "Bad data from peer\n");
117 destroy_association(assoc);
120 else if (cs_more(conn)) /* arrange to be called again */
121 iochan_setevent(h, EVENT_INPUT);
124 else if (event == EVENT_OUTPUT)
126 switch (res = cs_put(conn, assoc->encode_buffer, assoc->encoded_len))
129 fprintf(stderr, "Closed connection\n");
131 destroy_association(assoc);
133 case 0: /* all sent */
134 iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset */
136 case 1: /* partial send */
137 break; /* we'll get called again */
140 else if (event == EVENT_EXCEPT)
142 fprintf(stderr, "Exception on line\n");
144 destroy_association(assoc);
149 static int process_apdu(IOCHAN chan)
153 association *assoc = iochan_getdata(chan);
155 odr_setbuf(assoc->decode, assoc->input_buffer, assoc->input_apdu_len);
156 if (!z_APDU(assoc->decode, &apdu, 0))
158 odr_perror(assoc->decode, "Incoming APDU");
163 case Z_APDU_initRequest:
164 res = process_initRequest(chan, apdu->u.initRequest); break;
165 case Z_APDU_searchRequest:
166 res = process_searchRequest(chan, apdu->u.searchRequest); break;
167 case Z_APDU_presentRequest:
168 res = process_presentRequest(chan, apdu->u.presentRequest); break;
170 fprintf(stderr, "Bad APDU\n");
176 static int process_initRequest(IOCHAN client, Z_InitRequest *req)
181 association *assoc = iochan_getdata(client);
182 bend_initrequest binitreq;
183 bend_initresult *binitres;
185 fprintf(stderr, "Got initRequest.\n");
186 if (req->implementationId)
187 fprintf(stderr, "Id: %s\n", req->implementationId);
188 if (req->implementationName)
189 fprintf(stderr, "Name: %s\n", req->implementationName);
190 if (req->implementationVersion)
191 fprintf(stderr, "Version: %s\n", req->implementationVersion);
193 binitreq.configname = "default-config";
194 if (!(binitres = bend_init(&binitreq)) || binitres->errcode)
196 fprintf(stderr, "Bad response from backend\n");
201 apdu.which = Z_APDU_initResponse;
202 apdu.u.initResponse = &resp;
203 resp.referenceId = req->referenceId;
204 resp.options = req->options; /* should check these */
205 resp.protocolVersion = req->protocolVersion;
206 assoc->maximumRecordSize = *req->maximumRecordSize;
207 if (assoc->maximumRecordSize > ENCODE_BUFFER_SIZE - 500)
208 assoc->maximumRecordSize = ENCODE_BUFFER_SIZE - 500;
209 assoc->preferredMessageSize = *req->preferredMessageSize;
210 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
211 assoc->preferredMessageSize = assoc->maximumRecordSize;
212 resp.preferredMessageSize = &assoc->preferredMessageSize;
213 resp.maximumRecordSize = &assoc->maximumRecordSize;
214 resp.result = &result;
215 resp.implementationId = "YAZ";
216 resp.implementationName = "YAZ/Simple asynchronous test server";
217 resp.implementationVersion = "$Revision: 1.1 $";
218 resp.userInformationField = 0;
219 if (!z_APDU(assoc->encode, &apdup, 0))
221 odr_perror(assoc->encode, "Encode init");
224 odr_getbuf(assoc->encode, &assoc->encoded_len);
225 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
229 static Z_Records *diagrec(int error, char *addinfo)
231 static Z_Records rec;
232 static Odr_oid bib1[] = { 1, 2, 3, 4, 5, -1 };
236 fprintf(stderr, "Diagnostic: %d -- %s\n", error, addinfo);
238 rec.which = Z_Records_NSD;
239 rec.u.nonSurrogateDiagnostic = &dr;
240 dr.diagnosticSetId = bib1;
242 dr.addinfo = addinfo;
246 static int process_searchRequest(IOCHAN client, Z_SearchRequest *req)
249 Z_SearchResponse resp;
250 association *assoc = iochan_getdata(client);
254 bend_searchrequest bsrq;
255 bend_searchresult *bsrt;
257 fprintf(stderr, "Got SearchRequest.\n");
259 apdu.which = Z_APDU_searchResponse;
260 apdu.u.searchResponse = &resp;
261 resp.referenceId = req->referenceId;
263 bsrq.setname = req->resultSetName;
264 bsrq.replace_set = *req->replaceIndicator;
265 bsrq.num_bases = req->num_databaseNames;
266 bsrq.basenames = req->databaseNames;
267 bsrq.query = req->query;
269 if (!(bsrt = bend_search(&bsrq)))
271 else if (bsrt->errcode)
272 resp.records = diagrec(bsrt->errcode, bsrt->errstring);
276 resp.resultCount = &bsrt->hits;
277 resp.numberOfRecordsReturned = &nulint;
278 nrp = bsrt->hits ? 1 : 0;
279 resp.nextResultSetPosition = &nrp;
280 resp.searchStatus = &sr;
281 resp.resultSetStatus = &sr;
282 resp.presentStatus = 0;
284 if (!z_APDU(assoc->encode, &apdup, 0))
286 odr_perror(assoc->encode, "Encode init");
289 odr_getbuf(assoc->encode, &assoc->encoded_len);
290 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
294 static Z_Records *dummy_database_records (int start, int no_requested,
296 int preferredMessageSize)
298 static Z_Records rec;
299 static int no_records = 0;
300 static Z_NamePlusRecordList z_nprl;
302 static Z_NamePlusRecord **records;
304 rec.which = Z_Records_DBOSD;
305 rec.u.databaseOrSurDiagnostics = &z_nprl;
312 inf = fopen ("dummy-records", "r");
315 records = malloc (sizeof(*records) * 50);
319 buf = iso2709_read (inf);
322 records[i] = malloc (sizeof(**records));
324 records[i]->databaseName = NULL;
325 records[i]->which = Z_NamePlusRecord_databaseRecord;
326 oep = records[i]->u.databaseRecord =
327 malloc (sizeof(*oep));
329 oep->direct_reference = NULL;
330 oep->indirect_reference = NULL;
331 oep->descriptor = NULL;
332 oep->which = ODR_EXTERNAL_octet;
333 oep->u.octet_aligned = malloc (sizeof(*oep->u.octet_aligned));
334 assert (oep->u.octet_aligned);
335 oep->u.octet_aligned->size = oep->u.octet_aligned->len
337 oep->u.octet_aligned->buf = buf;
342 if (no_records < start + no_requested)
345 z_nprl.records = records + start -1;
346 for (size = 0, i = 0; i<no_requested; i++)
348 if (z_nprl.records[i]->which == Z_NamePlusRecord_databaseRecord)
349 size += z_nprl.records[i]->u.databaseRecord->u.octet_aligned->size;
350 printf ("size=%d\n", size);
351 if (size > preferredMessageSize)
356 z_nprl.num_records = *no_returned = i;
360 static int process_presentRequest(IOCHAN client, Z_PresentRequest *req)
363 Z_PresentResponse resp;
364 association *assoc = iochan_getdata(client);
367 fprintf(stderr, "Got PresentRequest.\n");
369 apdu.which = Z_APDU_presentResponse;
370 apdu.u.presentResponse = &resp;
371 resp.referenceId = req->referenceId;
373 resp.numberOfRecordsReturned = &nrr;
374 resp.nextResultSetPosition = &nrr;
375 resp.presentStatus = &nrr;
378 resp.records = diagrec(1, "Waiting for records from Adam. :)");
380 if (!(resp.records = dummy_database_records (*req->resultSetStartPoint,
381 *req->numberOfRecordsRequested, &nrr, assoc->preferredMessageSize)))
382 resp.records = diagrec (1, "No records from Adam. Sorry");
383 printf ("nrr=%d\n", nrr);
386 if (!z_APDU(assoc->encode, &apdup, 0))
388 odr_perror(assoc->encode, "Encode init");
391 odr_getbuf(assoc->encode, &assoc->encoded_len);
392 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);