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