The rudiments of an asynchronous server.
authorSebastian Hammer <quinn@indexdata.com>
Fri, 10 Mar 1995 18:22:44 +0000 (18:22 +0000)
committerSebastian Hammer <quinn@indexdata.com>
Fri, 10 Mar 1995 18:22:44 +0000 (18:22 +0000)
server/Makefile [new file with mode: 0644]
server/eventl.c [new file with mode: 0644]
server/eventl.h [new file with mode: 0644]
server/statserv.c [new file with mode: 0644]

diff --git a/server/Makefile b/server/Makefile
new file mode 100644 (file)
index 0000000..6830cc8
--- /dev/null
@@ -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.tmp >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 (file)
index 0000000..e363111
--- /dev/null
@@ -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 <assert.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <eventl.h>
+
+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 (file)
index 0000000..d8b965c
--- /dev/null
@@ -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 (file)
index 0000000..7a938e3
--- /dev/null
@@ -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 <stdio.h>
+
+#include <eventl.h>
+
+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')':'<address>.\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 <listener-addr>]\n", me);
+               exit(1);
+       }
+    if (!listeners)
+    {
+       fprintf(stderr, "%s: Must specify at least one listener.\n", me);
+       exit(1);
+    }
+    return event_loop();
+}