Small.
[yaz-moved-to-github.git] / server / eventl.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: eventl.c,v $
7  * Revision 1.12  1995-08-29 10:41:18  quinn
8  * Small.
9  *
10  * Revision 1.11  1995/06/19  12:39:09  quinn
11  * Fixed bug in timeout code. Added BER dumper.
12  *
13  * Revision 1.10  1995/06/16  10:31:33  quinn
14  * Added session timeout.
15  *
16  * Revision 1.9  1995/06/05  10:53:31  quinn
17  * Added a better SCAN.
18  *
19  * Revision 1.8  1995/05/16  08:51:01  quinn
20  * License, documentation, and memory fixes
21  *
22  * Revision 1.7  1995/03/27  15:02:01  quinn
23  * Added some includes for better portability
24  *
25  * Revision 1.6  1995/03/27  08:34:21  quinn
26  * Added dynamic server functionality.
27  * Released bindings to session.c (is now redundant)
28  *
29  * Revision 1.5  1995/03/15  08:37:41  quinn
30  * Now we're pretty much set for nonblocking I/O.
31  *
32  * Revision 1.4  1995/03/14  16:59:48  quinn
33  * Bug-fixes
34  *
35  * Revision 1.3  1995/03/14  11:30:14  quinn
36  * Works better now.
37  *
38  * Revision 1.2  1995/03/14  10:27:59  quinn
39  * More work on demo server.
40  *
41  * Revision 1.1  1995/03/10  18:22:44  quinn
42  * The rudiments of an asynchronous server.
43  *
44  */
45
46 #include <assert.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <errno.h>
52 #include <string.h>
53 #ifdef _AIX
54 #include <sys/select.h>
55 #endif
56
57 #include <eventl.h>
58
59 #include <dmalloc.h>
60
61 static IOCHAN iochans = 0;
62
63 IOCHAN iochan_getchan(void)
64 {
65     return iochans;
66 }
67
68 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
69 {
70     IOCHAN new;
71
72     if (!(new = malloc(sizeof(*new))))
73         return 0;
74     new->destroyed = 0;
75     new->fd = fd;
76     new->flags = flags;
77     new->fun = cb;
78     new->next = iochans;
79     new->force_event = 0;
80     new->last_event = new->max_idle = 0;
81     iochans = new;
82     return new;
83 }
84
85 int event_loop()
86 {
87     do
88     {
89         IOCHAN p, nextp;
90         fd_set in, out, except;
91         int res, max;
92         static struct timeval nullto = {0, 0}, to;
93         struct timeval *timeout;
94
95         FD_ZERO(&in);
96         FD_ZERO(&out);
97         FD_ZERO(&except);
98         timeout = &to; /* hang on select */
99         to.tv_sec = 5*60;
100         to.tv_usec = 0;
101         max = 0;
102         for (p = iochans; p; p = p->next)
103         {
104             if (p->force_event)
105                 timeout = &nullto;        /* polling select */
106             if (p->flags & EVENT_INPUT)
107                 FD_SET(p->fd, &in);
108             if (p->flags & EVENT_OUTPUT)
109                 FD_SET(p->fd, &out);
110             if (p->flags & EVENT_EXCEPT)
111                 FD_SET(p->fd, &except);
112             if (p->fd > max)
113                 max = p->fd;
114         }
115         if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
116         {
117             if (errno == EINTR)
118                 continue;
119             return 1;
120         }
121         for (p = iochans; p; p = p->next)
122         {
123             int force_event = p->force_event;
124             time_t now = time(0);
125
126             p->force_event = 0;
127             if (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT)
128             {
129                 p->last_event = now;
130                 (*p->fun)(p, EVENT_INPUT);
131             }
132             if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
133                 force_event == EVENT_OUTPUT))
134             {
135                 p->last_event = now;
136                 (*p->fun)(p, EVENT_OUTPUT);
137             }
138             if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
139                 force_event == EVENT_EXCEPT))
140             {
141                 p->last_event = now;
142                 (*p->fun)(p, EVENT_EXCEPT);
143             }
144             if (!p->destroyed && p->max_idle && now - p->last_event >
145                 p->max_idle)
146             {
147                 p->last_event = now;
148                 (*p->fun)(p, EVENT_TIMEOUT);
149             }
150         }
151         for (p = iochans; p; p = nextp)
152         {
153             nextp = p->next;
154
155             if (p->destroyed)
156             {
157                 IOCHAN tmp = p, pr;
158
159                 if (p == iochans)
160                     iochans = p->next;
161                 else
162                 {
163                     for (pr = iochans; pr; pr = pr->next)
164                         if (pr->next == p)
165                             break;
166                     assert(pr); /* grave error if it weren't there */
167                     pr->next = p->next;
168                 }
169                 if (nextp == p)
170                     nextp = p->next;
171                 free(tmp);
172             }
173         }
174     }
175     while (iochans);
176     return 0;
177 }