From 7e158942eb374e7211dd3dbd834e664c70a2d143 Mon Sep 17 00:00:00 2001 From: Sebastian Hammer Date: Fri, 10 Mar 1995 18:22:44 +0000 Subject: [PATCH] The rudiments of an asynchronous server. --- server/Makefile | 46 +++++++++++++++++ server/eventl.c | 101 +++++++++++++++++++++++++++++++++++++ server/eventl.h | 43 ++++++++++++++++ server/statserv.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 335 insertions(+) create mode 100644 server/Makefile create mode 100644 server/eventl.c create mode 100644 server/eventl.h create mode 100644 server/statserv.c diff --git a/server/Makefile b/server/Makefile new file mode 100644 index 0000000..6830cc8 --- /dev/null +++ b/server/Makefile @@ -0,0 +1,46 @@ +# Copyright (C) 1994, Index Data I/S +# All rights reserved. +# Sebastian Hammer, Adam Dickmeiss +# $Id: Makefile,v 1.1 1995-03-10 18:22:44 quinn Exp $ + +SHELL=/bin/sh +INCLUDE=-I../include -I. -I../asn -I../odr -I../../egate/include -I../../xtimosi/src +#CFLAGS=-Wall -pedantic -g +#CFLAGS=-g +DEFS=$(INCLUDE) +LIB= server.a +PO = eventl.o +CPP=cc -E +#CC=checkergcc + +all: $(LIB) + +alll: + +$(LIB): $(PO) + rm -f $(LIB) + ar qc $(LIB) $(PO) + ranlib $(LIB) + +.c.o: + $(CC) -c $(DEFS) $(CFLAGS) $< + +clean: + rm -f *.[oa] test core mon.out gmon.out errlist tst cli + +depend: depend2 +: +depend1: + mv Makefile Makefile.tmp + sed '/^#Depend/q' Makefile + $(CPP) $(INCLUDE) -M *.c >>Makefile + -rm Makefile.tmp + +depend2: + $(CPP) $(INCLUDE) -M *.c >.depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +#Depend --- DOT NOT DELETE THIS LINE diff --git a/server/eventl.c b/server/eventl.c new file mode 100644 index 0000000..e363111 --- /dev/null +++ b/server/eventl.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: eventl.c,v $ + * Revision 1.1 1995-03-10 18:22:44 quinn + * The rudiments of an asynchronous server. + * + */ + +#include +#include +#include +#include +#include + +#include + +IOCHAN iochans = 0; + +IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags) +{ + IOCHAN new; + + if (!(new = malloc(sizeof(*new)))) + return 0; + new->destroyed = 0; + new->fd = fd; + new->flags = flags; + new->fun = cb; + return new; +} + +void iochan_destroy(IOCHAN i) +{ + i->destroyed = 1; +} + +int event_loop() +{ + do + { + IOCHAN p, nextp; + fd_set in, out, except; + int res, max; + + FD_ZERO(&in); + FD_ZERO(&out); + FD_ZERO(&except); + for (p = iochans; p; p = p->next) + { + if (p->flags & EVENT_INPUT) + FD_SET(p->fd, &in); + if (p->flags & EVENT_OUTPUT) + FD_SET(p->fd, &out); + if (p->flags & EVENT_EXCEPT) + FD_SET(p->fd, &except); + if (p->fd > max) + max = p->fd; + } + if ((res = select(max + 1, &in, &out, &except, 0)) < 0) + { + if (errno == EINTR) + continue; + return 1; + } + if (!res) + continue; + for (p = iochans; p; p = nextp) + { + nextp = p->next; + if (FD_ISSET(p->fd, &in)) + (*p->fun)(p, EVENT_INPUT); + if (!p->destroyed && FD_ISSET(p->fd, &in)) + (*p->fun)(p, EVENT_OUTPUT); + if (!p->destroyed && FD_ISSET(p->fd, &except)) + (*p->fun)(p, EVENT_EXCEPT); + if (p->destroyed) + { + IOCHAN tmp = p, pr; + + if (p == iochans) + iochans = p->next; + else + { + for (pr = iochans; pr; pr = pr->next) + if (pr->next == p) + break; + assert(pr); + pr->next = p->next; + } + if (nextp == p) + nextp = p->next; + free(tmp); + } + } + } + while (iochans); + return 0; +} diff --git a/server/eventl.h b/server/eventl.h new file mode 100644 index 0000000..d8b965c --- /dev/null +++ b/server/eventl.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: eventl.h,v $ + * Revision 1.1 1995-03-10 18:22:45 quinn + * The rudiments of an asynchronous server. + * + */ + +#ifndef EVENTL_H +#define EVENTL_H + +struct iochan; + +typedef void (*IOC_CALLBACK)(struct iochan *i, int event); + +typedef struct iochan +{ + int fd; + int flags; +#define EVENT_INPUT 0x01 +#define EVENT_OUTPUT 0x02 +#define EVENT_EXCEPT 0x04 +#define EVENT_TIMEOUT 0x08 + IOC_CALLBACK fun; + void *data; + int destroyed; + + struct iochan *next; +} *IOCHAN; + +#define iochan_destroy(i) (void)((i)->destroyed = 1) +#define iochan_getfd(i) +#define iochan_getdata(i) ((i)->data) +#define iochan_setdata(i, d) ((i)->data = d) +#define iochan_getflags(i) ((i)->flags) +#define iochan_setflags(i, d) ((i)->flags = d) +#define iochan_getfun(i) ((i)->fun) +#define iochan_setfun(i, d) ((i)->fun = d) + +#endif diff --git a/server/statserv.c b/server/statserv.c new file mode 100644 index 0000000..7a938e3 --- /dev/null +++ b/server/statserv.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: statserv.c,v $ + * Revision 1.1 1995-03-10 18:22:45 quinn + * The rudiments of an asynchronous server. + * + */ + +/* + * Simple, static server. I wouldn't advise a static server unless you + * really have to, but it's great for debugging memory management. :) + */ + +#include + +#include + +static char *me = ""; + +/* + * handle incoming connect requests. + */ +void listener(IOCHAN h, int event) +{ + COMSTACK line = (COMSTACK) iochan_getdata(h); + + if (event == EVENT_INPUT) + { + if (cs_listen(line, 0, 0) < 0) + { + if (cs_errno(line) == CSNODATA) + return; + fprintf(stderr, "cs_listen failed.\n"); + exit(1); + } + iochan_setflags(h, EVENT_OUTPUT) /* set us up for accepting */ + } + else if (event == EVENT_OUTPUT) + { + COMSTACK new_line; + IOCHAN new_chan; + + if (!(new_line = cs_accept(line))) + { + fprintf(stderr, "Accept failed.\n"); + exit(1); + } + if (!(new_chan = iochan_create(cs_fileno(initializer, init_fun, + EVENT_INPUT)))) + { + fprintf(stderr, "Failed to create iochan\n"); + exit(1); + } + iochan_setflags(h, EVENT_INPUT); /* reset for listening */ + } + else + { + fprintf(stderr, "Bad event on listener.\n"); + exit(1); + } +} + +/* + * Set up a listening endpoint, and give it to the event-handler. + */ +void add_listener(char *where) +{ + COMSTACK l; + CS_TYPE type; + char mode[100], addr[100] + void *ap; + IOCHAN lst; + + if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2) + { + fprintf(stderr, "%s: Address format: ('tcp'|'osi')':'
.\n", + me); + exit(1); + } + if (!strcmp(mode, "tcp")) + { + if (!(ap = tcpip_strtoaddr(where))) + { + fprintf(stderr, "Address resolution failed for TCP.\n"); + exit(1); + } + type = tcpip_type; + } + else if (!strcmp(mode, "osi")) + { + if (!(ap = mosi_strtoaddr(where))) + { + fprintf(stderr, "Address resolution failed for TCP.\n"); + exit(1); + } + type = mosi_type; + } + else + { + fprintf(stderr, "You must specify either 'osi:' or 'tcp:'.\n"); + exit(1); + } + if (!(l = cs_create(type, 1))) + { + fprintf(stderr, "Failed to create listener\n"); + exit(1); + } + if (cs_bind(l, ap, CS_SERVER) < 0) + { + fprintf(stderr, "Failed to bind.\n"); + perror(where); + exit(1); + } + if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT))) + { + fprintf(stderr, "Failed to create IOCHAN-type\n"); + exit(1); + } + iochan_setdata(lst, l); +} + +int main(int argc, char **argv) +{ + int ret, listeners = 0; + char *arg; + + while ((ret = options("l:", argv, argc, &arg)) != -2) + switch (ret) + { + case 0: me = arg; break; + case 'l': add_listener(arg); l++; break; + default: + fprintf(stderr, "Usage: %s [-l ]\n", me); + exit(1); + } + if (!listeners) + { + fprintf(stderr, "%s: Must specify at least one listener.\n", me); + exit(1); + } + return event_loop(); +} -- 1.7.10.4