From afff2d64ae8758642c8e88bfebff9c00a982daa4 Mon Sep 17 00:00:00 2001 From: Sebastian Hammer Date: Mon, 27 Mar 1995 08:34:20 +0000 Subject: [PATCH] Added dynamic server functionality. Released bindings to session.c (is now redundant) --- server/Makefile | 11 ++--- server/eventl.c | 23 ++++++++-- server/eventl.h | 8 +++- server/seshigh.c | 112 ++++++++++++++++++++++++++++++++-------------- server/session.h | 9 +++- server/statserv.c | 129 ++++++++++++++++++++++++++++++++++++++++++++--------- 6 files changed, 228 insertions(+), 64 deletions(-) diff --git a/server/Makefile b/server/Makefile index 5e82c42..396c5eb 100644 --- a/server/Makefile +++ b/server/Makefile @@ -1,23 +1,24 @@ # Copyright (C) 1994, Index Data I/S # All rights reserved. # Sebastian Hammer, Adam Dickmeiss -# $Id: Makefile,v 1.12 1995-03-20 09:46:24 quinn Exp $ +# $Id: Makefile,v 1.13 1995-03-27 08:34:20 quinn Exp $ SHELL=/bin/sh INCLUDE=-I../include -I. -I../asn -I../odr -I../yazlib -I../../egate/include\ - -I../../xtimosi/src -I../../alex/include + -I../../xtimosi/src -I../../alex/include -I../util LIBDIR=../../lib LIBINCLUDE=-L$(LIBDIR) #CFLAGS=-Wall -pedantic -g DEFS=$(INCLUDE) LIB=$(LIBDIR)/libserver.a LIBS=$(LIBDIR)/libserver.a $(LIBDIR)/libasn.a $(LIBDIR)/libodr.a \ -$(LIBDIR)/libcomstack.a ../../alex/lib/util.a ../../egate/lib/util.a\ -../../xtimosi/src/libmosi.a ../yazlib/rfct.o ../yazlib/makensap.o +$(LIBDIR)/libcomstack.a ../../egate/lib/util.a\ +../../xtimosi/src/libmosi.a ../yazlib/rfct.o ../yazlib/makensap.o \ +$(LIBDIR)/libutil.a PO = eventl.o seshigh.o statserv.o CPP=cc -E PROG=ztest -PROGO=ztest.o session.o +PROGO=ztest.o all: $(LIBDIR) $(LIB) $(PROG) diff --git a/server/eventl.c b/server/eventl.c index 104088c..2d9886b 100644 --- a/server/eventl.c +++ b/server/eventl.c @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: eventl.c,v $ - * Revision 1.5 1995-03-15 08:37:41 quinn + * Revision 1.6 1995-03-27 08:34:21 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.5 1995/03/15 08:37:41 quinn * Now we're pretty much set for nonblocking I/O. * * Revision 1.4 1995/03/14 16:59:48 quinn @@ -29,7 +33,14 @@ #include -IOCHAN iochans = 0; +#include + +static IOCHAN iochans = 0; + +IOCHAN iochan_getchan(void) +{ + return iochans; +} IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags) { @@ -81,12 +92,11 @@ int event_loop() continue; return 1; } - for (p = iochans; p; p = nextp) + for (p = iochans; p; p = p->next) { int force_event = p->force_event; p->force_event = 0; - nextp = p->next; if (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT) (*p->fun)(p, EVENT_INPUT); if (!p->destroyed && (FD_ISSET(p->fd, &out) || @@ -95,6 +105,11 @@ int event_loop() if (!p->destroyed && (FD_ISSET(p->fd, &except) || force_event == EVENT_EXCEPT)) (*p->fun)(p, EVENT_EXCEPT); + } + for (p = iochans; p; p = nextp) + { + nextp = p->next; + if (p->destroyed) { IOCHAN tmp = p, pr; diff --git a/server/eventl.h b/server/eventl.h index 1ef43a2..01ea810 100644 --- a/server/eventl.h +++ b/server/eventl.h @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: eventl.h,v $ - * Revision 1.3 1995-03-15 08:37:42 quinn + * Revision 1.4 1995-03-27 08:34:23 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.3 1995/03/15 08:37:42 quinn * Now we're pretty much set for nonblocking I/O. * * Revision 1.2 1995/03/14 10:28:00 quinn @@ -49,7 +53,9 @@ int force_event; #define iochan_getfun(i) ((i)->fun) #define iochan_setfun(i, d) ((i)->fun = d) #define iochan_setevent(i, e) ((i)->force_event = (e)) +#define iochan_getnext(i) ((i)->next) +IOCHAN iochan_getchan(void); IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags); int event_loop(); diff --git a/server/seshigh.c b/server/seshigh.c index 8b5702a..b6ecb75 100644 --- a/server/seshigh.c +++ b/server/seshigh.c @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: seshigh.c,v $ - * Revision 1.9 1995-03-22 15:01:26 quinn + * Revision 1.10 1995-03-27 08:34:24 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.9 1995/03/22 15:01:26 quinn * Adjusting record packing. * * Revision 1.8 1995/03/22 10:13:21 quinn @@ -40,6 +44,7 @@ #include #include #include +#include #include @@ -69,6 +74,10 @@ association *create_association(IOCHAN channel, COMSTACK link) new->state = ASSOC_UNINIT; new->input_buffer = 0; new->input_buffer_len = 0; + if (cs_getproto(link) == CS_Z3950) + new->proto = PROTO_Z3950; + else + new->proto = PROTO_SR; return new; } @@ -214,7 +223,7 @@ static int process_initRequest(IOCHAN client, Z_InitRequest *req) resp.result = &result; resp.implementationId = "YAZ"; resp.implementationName = "YAZ/Simple asynchronous test server"; - resp.implementationVersion = "$Revision: 1.9 $"; + resp.implementationVersion = "$Revision: 1.10 $"; resp.userInformationField = 0; if (!z_APDU(assoc->encode, &apdup, 0)) { @@ -227,38 +236,46 @@ static int process_initRequest(IOCHAN client, Z_InitRequest *req) return 0; } -static Z_Records *diagrec(int error, char *addinfo) +static Z_Records *diagrec(oid_proto proto, int error, char *addinfo) { static Z_Records rec; - static Odr_oid bib1[] = { 1, 2, 3, 4, 5, -1 }; + oident bib1; static Z_DiagRec dr; static int err; + bib1.proto = proto; + bib1.class = CLASS_DIAGSET; + bib1.value = VAL_BIB1; + fprintf(stderr, "Diagnostic: %d -- %s\n", error, addinfo ? addinfo : "NULL"); err = error; rec.which = Z_Records_NSD; rec.u.nonSurrogateDiagnostic = &dr; - dr.diagnosticSetId = bib1; + dr.diagnosticSetId = oid_getoidbyent(&bib1); dr.condition = &err; dr.addinfo = addinfo ? addinfo : ""; return &rec; } -static Z_NamePlusRecord *surrogatediagrec(char *dbname, int error, - char *addinfo) +static Z_NamePlusRecord *surrogatediagrec(oid_proto proto, char *dbname, + int error, char *addinfo) { static Z_NamePlusRecord rec; static Z_DiagRec dr; - static Odr_oid bib1[] = { 1, 2, 3, 4, 5, -1 }; static int err; + oident bib1; + + bib1.proto = proto; + bib1.class = CLASS_DIAGSET; + bib1.value = VAL_BIB1; fprintf(stderr, "SurrogateDiagnotic: %d -- %s\n", error, addinfo); err = error; rec.databaseName = dbname; rec.which = Z_NamePlusRecord_surrogateDiagnostic; rec.u.surrogateDiagnostic = &dr; - dr.diagnosticSetId = bib1; + dr.diagnosticSetId = oid_getoidbyent(&bib1); dr.condition = &err; dr.addinfo = addinfo ? addinfo : ""; return &rec; @@ -274,6 +291,8 @@ static Z_Records *pack_records(association *a, char *setname, int start, static Z_Records records; static Z_NamePlusRecordList reclist; static Z_NamePlusRecord *list[MAX_RECORDS]; + oident recform; + Odr_oid *oid; records.which = Z_Records_DBOSD; records.u.databaseOrSurDiagnostics = &reclist; @@ -283,6 +302,12 @@ static Z_Records *pack_records(association *a, char *setname, int start, *num = 0; *next = 0; + recform.proto = a->proto; + recform.class = CLASS_RECSYN; + recform.value = VAL_USMARC; + if (!(oid = odr_oiddup(a->encode, oid_getoidbyent(&recform)))) + return 0; + fprintf(stderr, "Request to pack %d+%d\n", start, toget); fprintf(stderr, "pms=%d, mrs=%d\n", a->preferredMessageSize, a->maximumRecordSize); @@ -303,14 +328,14 @@ static Z_Records *pack_records(association *a, char *setname, int start, if (!(fres = bend_fetch(&freq))) { *pres = Z_PRES_FAILURE; - return diagrec(2, "Backend interface problem"); + return diagrec(a->proto, 2, "Backend interface problem"); } /* backend should be able to signal whether error is system-wide or only pertaining to current record */ if (fres->errcode) { *pres = Z_PRES_FAILURE; - return diagrec(fres->errcode, fres->errstring); + return diagrec(a->proto, fres->errcode, fres->errstring); } fprintf(stderr, " Got record, len=%d, total=%d\n", fres->len, total_length); @@ -332,7 +357,7 @@ static Z_Records *pack_records(association *a, char *setname, int start, { fprintf(stderr, " Dropped it\n"); reclist.records[reclist.num_records] = - surrogatediagrec(fres->basename, 16, 0); + surrogatediagrec(a->proto, fres->basename, 16, 0); reclist.num_records++; *pres = Z_PRES_PARTIAL_2; break; @@ -342,8 +367,7 @@ static Z_Records *pack_records(association *a, char *setname, int start, { fprintf(stderr, "Record > maxrcdsz\n"); reclist.records[reclist.num_records] = - surrogatediagrec(fres->basename, - 17, 0); + surrogatediagrec(a->proto, fres->basename, 17, 0); reclist.num_records++; *pres = Z_PRES_PARTIAL_2; break; @@ -359,7 +383,7 @@ static Z_Records *pack_records(association *a, char *setname, int start, if (!(thisrec->u.databaseRecord = thisext = odr_malloc(a->encode, sizeof(Z_DatabaseRecord)))) return 0; - thisext->direct_reference = 0; /* should be OID for current MARC */ + thisext->direct_reference = oid; /* should be OID for current MARC */ thisext->indirect_reference = 0; thisext->descriptor = 0; thisext->which = ODR_EXTERNAL_octet; @@ -390,6 +414,7 @@ static int process_searchRequest(IOCHAN client, Z_SearchRequest *req) int nrp; bend_searchrequest bsrq; bend_searchresult *bsrt; + oident *oent; fprintf(stderr, "Got SearchRequest.\n"); apdup = &apdu; @@ -397,26 +422,47 @@ static int process_searchRequest(IOCHAN client, Z_SearchRequest *req) 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; + resp.records = 0; + if (req->query->which == Z_Query_type_1) + { + Z_RPNQuery *q = req->query->u.type_1; - if (!(bsrt = bend_search(&bsrq))) - return -1; - else if (bsrt->errcode) - resp.records = diagrec(bsrt->errcode, bsrt->errstring); + if (!(oent = oid_getentbyoid(q->attributeSetId)) || + oent->class != CLASS_ATTSET || + oent->value != VAL_BIB1) + resp.records = diagrec(assoc->proto, 121, 0); + } + if (!resp.records) + { + 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(assoc->proto, 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; + } 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; + { + resp.resultCount = &nulint; + resp.numberOfRecordsReturned = &nulint; + resp.nextResultSetPosition = &nulint; + resp.searchStatus = &nulint; + resp.resultSetStatus = 0; + } if (!z_APDU(assoc->encode, &apdup, 0)) { diff --git a/server/session.h b/server/session.h index cd7c2a3..179b2ce 100644 --- a/server/session.h +++ b/server/session.h @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: session.h,v $ - * Revision 1.1 1995-03-14 10:28:02 quinn + * Revision 1.2 1995-03-27 08:34:29 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.1 1995/03/14 10:28:02 quinn * More work on demo server. * * @@ -15,6 +19,7 @@ #include #include +#include typedef struct association { @@ -29,6 +34,7 @@ typedef struct association int input_buffer_len; int input_apdu_len; int state; + oid_proto proto; #define ASSOC_UNINIT 0 #define ASSOC_IDLE 1 @@ -38,6 +44,7 @@ typedef struct association } association; association *create_association(IOCHAN channel, COMSTACK link); +void destroy_association(association *h); void ir_session(IOCHAN h, int event); #endif diff --git a/server/statserv.c b/server/statserv.c index 0531798..a616cc9 100644 --- a/server/statserv.c +++ b/server/statserv.c @@ -4,7 +4,11 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: statserv.c,v $ - * Revision 1.8 1995-03-20 09:46:26 quinn + * Revision 1.9 1995-03-27 08:34:30 quinn + * Added dynamic server functionality. + * Released bindings to session.c (is now redundant) + * + * Revision 1.8 1995/03/20 09:46:26 quinn * Added osi support. * * Revision 1.7 1995/03/16 13:29:04 quinn @@ -37,6 +41,11 @@ */ #include +#include +#include +#include +#include +#include #include #include @@ -45,44 +54,110 @@ #include #include #include - -#include -#include +#include static char *me = ""; +static int dynamic = 0; /* fork on incoming connection */ #define DEFAULT_LISTENER "tcp:localhost:9999" /* * handle incoming connect requests. + * The dynamic mode is a bit tricky mostly because we want to avoid + * doing all of the listening and accepting in the parent - it's + * safer that way. */ -void listener(IOCHAN h, int event) +static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); association *newas; + static int hand[2]; + static int child = 0; + int res; if (event == EVENT_INPUT) { - if (cs_listen(line, 0, 0) < 0) + if (dynamic && !child) { - if (cs_errno(line) == CSNODATA) + int res; + + if (pipe(hand) < 0) + { + perror("pipe"); + exit(1); + } + if ((res = fork()) < 0) + { + perror("fork"); + exit(1); + } + else if (res == 0) /* child */ + { + close(hand[0]); + child = 1; + } + else /* parent */ + { + close(hand[1]); + /* wait for child to take the call */ + for (;;) + { + char dummy[1]; + int res; + + if ((res = read(hand[0], dummy, 1)) < 0 && errno != EINTR) + { + perror("handshake read"); + exit(1); + } + else if (res >= 0) + break; + } + fprintf(stderr, "P: Child has taken the call\n"); + close(hand[0]); return; + } + } + if ((res = cs_listen(line, 0, 0)) < 0) + { fprintf(stderr, "cs_listen failed.\n"); - exit(1); + return; } + else if (res == 1) + return; iochan_setevent(h, EVENT_OUTPUT); iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */ } + /* in dynamic mode, only the child ever comes down here */ else if (event == EVENT_OUTPUT) { COMSTACK new_line; IOCHAN new_chan; - if (!(new_line = cs_accept(line))) - { + if (!(new_line = cs_accept(line))) + { fprintf(stderr, "Accept failed.\n"); - exit(1); + iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ + return; + } + if (dynamic) + { + IOCHAN pp; + /* close our half of the listener sockets */ + for (pp = iochan_getchan(); pp; pp = iochan_getnext(pp)) + { + COMSTACK l = iochan_getdata(pp); + cs_close(l); + iochan_destroy(pp); + } + /* release dad */ + fprintf(stderr, "Releasing parent\n"); + close(hand[1]); + fprintf(stderr, "New fd is %d\n", cs_fileno(new_line)); } + else + iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ + if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, EVENT_INPUT))) { @@ -95,7 +170,6 @@ void listener(IOCHAN h, int event) exit(1); } iochan_setdata(new_chan, newas); - iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset for listen */ } else { @@ -107,7 +181,7 @@ void listener(IOCHAN h, int event) /* * Set up a listening endpoint, and give it to the event-handler. */ -void add_listener(char *where) +static void add_listener(char *where, int what) { COMSTACK l; CS_TYPE type; @@ -115,7 +189,8 @@ void add_listener(char *where) void *ap; IOCHAN lst; - fprintf(stderr, "Adding listener on %s\n", where); + fprintf(stderr, "Adding %s listener on %s\n", + what == PROTO_SR ? "SR" : "Z3950", where); if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2) { fprintf(stderr, "%s: Address format: ('tcp'|'osi')':'
.\n", @@ -145,7 +220,7 @@ void add_listener(char *where) fprintf(stderr, "You must specify either 'osi:' or 'tcp:'.\n"); exit(1); } - if (!(l = cs_create(type, 0))) + if (!(l = cs_create(type, 0, what))) { fprintf(stderr, "Failed to create listener\n"); exit(1); @@ -165,22 +240,36 @@ void add_listener(char *where) iochan_setdata(lst, l); } +static void catchchld(int num) +{ + while (waitpid(-1, 0, WNOHANG) > 0); + signal(SIGCHLD, catchchld); +} + int statserv_main(int argc, char **argv) { int ret, listeners = 0; char *arg; + int protocol = CS_Z3950;; me = argv[0]; - while ((ret = options("l:", argv, argc, &arg)) != -2) + while ((ret = options("szdl:", argv, argc, &arg)) != -2) switch (ret) { - case 0: me = arg; break; - case 'l': add_listener(arg); listeners++; break; + case 0: + add_listener(arg, protocol); + listeners++; + break; + case 'z': protocol = CS_Z3950; break; + case 's': protocol = CS_SR; break; + case 'd': dynamic = 1; break; default: - fprintf(stderr, "Usage: %s [-l ]\n", me); + fprintf(stderr, "Usage: %s [ -zsd ... ]\n", me); exit(1); } + if (dynamic) + signal(SIGCHLD, catchchld); if (!listeners) - add_listener(DEFAULT_LISTENER); + add_listener(DEFAULT_LISTENER, protocol); return event_loop(); } -- 1.7.10.4