2 * Copyright (C) 1994, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.2 1995-03-16 13:29:01 quinn
10 * Revision 1.1 1995/03/15 16:02:10 quinn
11 * Modded session.c seshigh.c
13 * Revision 1.10 1995/03/15 15:18:51 quinn
14 * Little changes to better support nonblocking I/O
17 * Revision 1.9 1995/03/15 13:20:23 adam
18 * Yet another bug fix in very dummy_database...
20 * Revision 1.8 1995/03/15 11:18:17 quinn
23 * Revision 1.7 1995/03/15 09:40:15 adam
24 * Bug fixes in dummy_database_...
26 * Revision 1.6 1995/03/15 09:08:30 adam
27 * Take care of preferredMessageSize.
29 * Revision 1.5 1995/03/15 08:37:44 quinn
30 * Now we're pretty much set for nonblocking I/O.
32 * Revision 1.4 1995/03/15 08:27:20 adam
33 * PresentRequest changed to return MARC records from file 'dummy-records'.
35 * Revision 1.3 1995/03/14 16:59:48 quinn
38 * Revision 1.2 1995/03/14 11:30:14 quinn
41 * Revision 1.1 1995/03/14 10:28:01 quinn
42 * More work on demo server.
59 #define ENCODE_BUFFER_SIZE 10000
61 static int process_apdu(IOCHAN chan);
62 static int process_initRequest(IOCHAN client, Z_InitRequest *req);
63 static int process_searchRequest(IOCHAN client, Z_SearchRequest *req);
64 static int process_presentRequest(IOCHAN client, Z_PresentRequest *req);
66 association *create_association(IOCHAN channel, COMSTACK link)
70 if (!(new = malloc(sizeof(*new))))
72 new->client_chan = channel;
73 new->client_link = link;
74 if (!(new->decode = odr_createmem(ODR_DECODE)) ||
75 !(new->encode = odr_createmem(ODR_ENCODE)))
77 if (!(new->encode_buffer = malloc(ENCODE_BUFFER_SIZE)))
79 odr_setbuf(new->encode, new->encode_buffer, ENCODE_BUFFER_SIZE);
80 new->state = ASSOC_UNINIT;
81 new->input_buffer = 0;
82 new->input_buffer_len = 0;
86 void destroy_association(association *h)
88 odr_destroy(h->decode);
89 odr_destroy(h->encode);
90 free(h->encode_buffer);
94 void ir_session(IOCHAN h, int event)
97 association *assoc = iochan_getdata(h);
98 COMSTACK conn = assoc->client_link;
100 if (event == EVENT_INPUT)
102 assert(assoc && conn);
103 res = cs_get(conn, &assoc->input_buffer, &assoc->input_buffer_len);
106 case 0: case -1: /* connection closed by peer */
107 fprintf(stderr, "Closed connection\n");
109 destroy_association(assoc);
112 case 1: /* incomplete read */
115 assoc->input_apdu_len = res;
116 if (process_apdu(h) < 0)
118 fprintf(stderr, "Bad data from peer\n");
120 destroy_association(assoc);
123 else if (cs_more(conn)) /* arrange to be called again */
124 iochan_setevent(h, EVENT_INPUT);
127 else if (event == EVENT_OUTPUT)
129 switch (res = cs_put(conn, assoc->encode_buffer, assoc->encoded_len))
132 fprintf(stderr, "Closed connection\n");
134 destroy_association(assoc);
136 case 0: /* all sent */
137 iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset */
139 case 1: /* partial send */
140 break; /* we'll get called again */
143 else if (event == EVENT_EXCEPT)
145 fprintf(stderr, "Exception on line\n");
147 destroy_association(assoc);
152 static int process_apdu(IOCHAN chan)
156 association *assoc = iochan_getdata(chan);
158 odr_setbuf(assoc->decode, assoc->input_buffer, assoc->input_apdu_len);
159 if (!z_APDU(assoc->decode, &apdu, 0))
161 odr_perror(assoc->decode, "Incoming APDU");
166 case Z_APDU_initRequest:
167 res = process_initRequest(chan, apdu->u.initRequest); break;
168 case Z_APDU_searchRequest:
169 res = process_searchRequest(chan, apdu->u.searchRequest); break;
170 case Z_APDU_presentRequest:
171 res = process_presentRequest(chan, apdu->u.presentRequest); break;
173 fprintf(stderr, "Bad APDU\n");
179 static int process_initRequest(IOCHAN client, Z_InitRequest *req)
184 association *assoc = iochan_getdata(client);
185 bend_initrequest binitreq;
186 bend_initresult *binitres;
188 fprintf(stderr, "Got initRequest.\n");
189 if (req->implementationId)
190 fprintf(stderr, "Id: %s\n", req->implementationId);
191 if (req->implementationName)
192 fprintf(stderr, "Name: %s\n", req->implementationName);
193 if (req->implementationVersion)
194 fprintf(stderr, "Version: %s\n", req->implementationVersion);
196 binitreq.configname = "default-config";
197 if (!(binitres = bend_init(&binitreq)) || binitres->errcode)
199 fprintf(stderr, "Bad response from backend\n");
204 apdu.which = Z_APDU_initResponse;
205 apdu.u.initResponse = &resp;
206 resp.referenceId = req->referenceId;
207 resp.options = req->options; /* should check these */
208 resp.protocolVersion = req->protocolVersion;
209 assoc->maximumRecordSize = *req->maximumRecordSize;
210 if (assoc->maximumRecordSize > ENCODE_BUFFER_SIZE - 500)
211 assoc->maximumRecordSize = ENCODE_BUFFER_SIZE - 500;
212 assoc->preferredMessageSize = *req->preferredMessageSize;
213 if (assoc->preferredMessageSize > assoc->maximumRecordSize)
214 assoc->preferredMessageSize = assoc->maximumRecordSize;
215 resp.preferredMessageSize = &assoc->preferredMessageSize;
216 resp.maximumRecordSize = &assoc->maximumRecordSize;
217 resp.result = &result;
218 resp.implementationId = "YAZ";
219 resp.implementationName = "YAZ/Simple asynchronous test server";
220 resp.implementationVersion = "$Revision: 1.2 $";
221 resp.userInformationField = 0;
222 if (!z_APDU(assoc->encode, &apdup, 0))
224 odr_perror(assoc->encode, "Encode initres");
227 odr_getbuf(assoc->encode, &assoc->encoded_len);
228 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
232 static Z_Records *diagrec(int error, char *addinfo)
234 static Z_Records rec;
235 static Odr_oid bib1[] = { 1, 2, 3, 4, 5, -1 };
239 fprintf(stderr, "Diagnostic: %d -- %s\n", error, addinfo);
241 rec.which = Z_Records_NSD;
242 rec.u.nonSurrogateDiagnostic = &dr;
243 dr.diagnosticSetId = bib1;
245 dr.addinfo = addinfo;
249 static int process_searchRequest(IOCHAN client, Z_SearchRequest *req)
252 Z_SearchResponse resp;
253 association *assoc = iochan_getdata(client);
257 bend_searchrequest bsrq;
258 bend_searchresult *bsrt;
260 fprintf(stderr, "Got SearchRequest.\n");
262 apdu.which = Z_APDU_searchResponse;
263 apdu.u.searchResponse = &resp;
264 resp.referenceId = req->referenceId;
266 bsrq.setname = req->resultSetName;
267 bsrq.replace_set = *req->replaceIndicator;
268 bsrq.num_bases = req->num_databaseNames;
269 bsrq.basenames = req->databaseNames;
270 bsrq.query = req->query;
272 if (!(bsrt = bend_search(&bsrq)))
274 else if (bsrt->errcode)
275 resp.records = diagrec(bsrt->errcode, bsrt->errstring);
279 resp.resultCount = &bsrt->hits;
280 resp.numberOfRecordsReturned = &nulint;
281 nrp = bsrt->hits ? 1 : 0;
282 resp.nextResultSetPosition = &nrp;
283 resp.searchStatus = &sr;
284 resp.resultSetStatus = &sr;
285 resp.presentStatus = 0;
287 if (!z_APDU(assoc->encode, &apdup, 0))
289 odr_perror(assoc->encode, "Encode searchres");
292 odr_getbuf(assoc->encode, &assoc->encoded_len);
293 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);
297 static int process_presentRequest(IOCHAN client, Z_PresentRequest *req)
300 Z_PresentResponse resp;
301 association *assoc = iochan_getdata(client);
304 fprintf(stderr, "Got PresentRequest.\n");
306 apdu.which = Z_APDU_presentResponse;
307 apdu.u.presentResponse = &resp;
308 resp.referenceId = req->referenceId;
310 resp.numberOfRecordsReturned = &nrr;
311 resp.nextResultSetPosition = &nrr;
312 resp.presentStatus = &nrr;
314 resp.records = diagrec(1, "No records yet.");
316 if (!z_APDU(assoc->encode, &apdup, 0))
318 odr_perror(assoc->encode, "Encode presentres");
321 odr_getbuf(assoc->encode, &assoc->encoded_len);
322 iochan_setflags(client, EVENT_OUTPUT | EVENT_EXCEPT);