1 | /*
|
---|
2 | * Copyright (c) 1995-1999, Index Data
|
---|
3 | * See the file LICENSE for details.
|
---|
4 | * Sebastian Hammer, Adam Dickmeiss
|
---|
5 | *
|
---|
6 | * $Log$
|
---|
7 | * Revision 1.1 2000/08/03 03:11:40 johnmcp
|
---|
8 | * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
|
---|
9 | *
|
---|
10 | * Revision 1.29 1999/11/30 13:47:12 adam
|
---|
11 | * Improved installation. Moved header files to include/yaz.
|
---|
12 | *
|
---|
13 | * Revision 1.28 1999/08/27 09:40:32 adam
|
---|
14 | * Renamed logf function to yaz_log. Removed VC++ project files.
|
---|
15 | *
|
---|
16 | * Revision 1.27 1999/02/02 13:57:34 adam
|
---|
17 | * Uses preprocessor define WIN32 instead of WINDOWS to build code
|
---|
18 | * for Microsoft WIN32.
|
---|
19 | *
|
---|
20 | * Revision 1.26 1998/02/11 11:53:35 adam
|
---|
21 | * Changed code so that it compiles as C++.
|
---|
22 | *
|
---|
23 | * Revision 1.25 1998/01/29 13:30:23 adam
|
---|
24 | * Better event handle system for NT/Unix.
|
---|
25 | *
|
---|
26 | * Revision 1.24 1997/09/04 14:19:13 adam
|
---|
27 | * Added credits.
|
---|
28 | *
|
---|
29 | * Revision 1.23 1997/09/01 08:52:59 adam
|
---|
30 | * New windows NT/95 port using MSV5.0. The test server 'ztest' was
|
---|
31 | * moved a separate directory. MSV5.0 project server.dsp created.
|
---|
32 | * As an option, the server can now operate as an NT service.
|
---|
33 | *
|
---|
34 | * Revision 1.22 1996/07/06 19:58:35 quinn
|
---|
35 | * System headerfiles gathered in yconfig
|
---|
36 | *
|
---|
37 | * Revision 1.21 1996/02/21 12:55:51 quinn
|
---|
38 | * small
|
---|
39 | *
|
---|
40 | * Revision 1.20 1996/02/21 12:52:55 quinn
|
---|
41 | * Test
|
---|
42 | *
|
---|
43 | * Revision 1.19 1995/12/05 11:17:30 quinn
|
---|
44 | * Moved some paranthesises around. Sigh.
|
---|
45 | *
|
---|
46 | * Revision 1.18 1995/11/13 09:27:41 quinn
|
---|
47 | * Fiddling with the variant stuff.
|
---|
48 | *
|
---|
49 | * Revision 1.17 1995/11/07 12:37:44 quinn
|
---|
50 | * Added support for forcing TIMEOUT event.
|
---|
51 | *
|
---|
52 | * Revision 1.16 1995/11/01 13:54:56 quinn
|
---|
53 | * Minor adjustments
|
---|
54 | *
|
---|
55 | * Revision 1.15 1995/09/15 14:44:15 quinn
|
---|
56 | * *** empty log message ***
|
---|
57 | *
|
---|
58 | * Revision 1.14 1995/08/29 14:44:50 quinn
|
---|
59 | * Reset timeouts.
|
---|
60 | *
|
---|
61 | * Revision 1.13 1995/08/29 11:17:56 quinn
|
---|
62 | * Added code to receive close
|
---|
63 | *
|
---|
64 | * Revision 1.12 1995/08/29 10:41:18 quinn
|
---|
65 | * Small.
|
---|
66 | *
|
---|
67 | * Revision 1.11 1995/06/19 12:39:09 quinn
|
---|
68 | * Fixed bug in timeout code. Added BER dumper.
|
---|
69 | *
|
---|
70 | * Revision 1.10 1995/06/16 10:31:33 quinn
|
---|
71 | * Added session timeout.
|
---|
72 | *
|
---|
73 | * Revision 1.9 1995/06/05 10:53:31 quinn
|
---|
74 | * Added a better SCAN.
|
---|
75 | *
|
---|
76 | * Revision 1.8 1995/05/16 08:51:01 quinn
|
---|
77 | * License, documentation, and memory fixes
|
---|
78 | *
|
---|
79 | * Revision 1.7 1995/03/27 15:02:01 quinn
|
---|
80 | * Added some includes for better portability
|
---|
81 | *
|
---|
82 | * Revision 1.6 1995/03/27 08:34:21 quinn
|
---|
83 | * Added dynamic server functionality.
|
---|
84 | * Released bindings to session.c (is now redundant)
|
---|
85 | *
|
---|
86 | * Revision 1.5 1995/03/15 08:37:41 quinn
|
---|
87 | * Now we're pretty much set for nonblocking I/O.
|
---|
88 | *
|
---|
89 | * Revision 1.4 1995/03/14 16:59:48 quinn
|
---|
90 | * Bug-fixes
|
---|
91 | *
|
---|
92 | * Revision 1.3 1995/03/14 11:30:14 quinn
|
---|
93 | * Works better now.
|
---|
94 | *
|
---|
95 | * Revision 1.2 1995/03/14 10:27:59 quinn
|
---|
96 | * More work on demo server.
|
---|
97 | *
|
---|
98 | * Revision 1.1 1995/03/10 18:22:44 quinn
|
---|
99 | * The rudiments of an asynchronous server.
|
---|
100 | *
|
---|
101 | */
|
---|
102 |
|
---|
103 | #include <stdio.h>
|
---|
104 | #include <assert.h>
|
---|
105 | #ifdef WIN32
|
---|
106 | #include <winsock.h>
|
---|
107 | #else
|
---|
108 | #include <unistd.h>
|
---|
109 | #endif
|
---|
110 | #include <stdlib.h>
|
---|
111 | #include <errno.h>
|
---|
112 | #include <string.h>
|
---|
113 |
|
---|
114 | #include <yaz/yconfig.h>
|
---|
115 | #include <yaz/log.h>
|
---|
116 | #include <yaz/comstack.h>
|
---|
117 | #include <yaz/xmalloc.h>
|
---|
118 | #include "eventl.h"
|
---|
119 | #include "session.h"
|
---|
120 | #include <yaz/statserv.h>
|
---|
121 |
|
---|
122 | IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
|
---|
123 | {
|
---|
124 | IOCHAN new_iochan;
|
---|
125 |
|
---|
126 | if (!(new_iochan = (IOCHAN)xmalloc(sizeof(*new_iochan))))
|
---|
127 | return 0;
|
---|
128 | new_iochan->destroyed = 0;
|
---|
129 | new_iochan->fd = fd;
|
---|
130 | new_iochan->flags = flags;
|
---|
131 | new_iochan->fun = cb;
|
---|
132 | new_iochan->force_event = 0;
|
---|
133 | new_iochan->last_event = new_iochan->max_idle = 0;
|
---|
134 | new_iochan->next = NULL;
|
---|
135 | return new_iochan;
|
---|
136 | }
|
---|
137 |
|
---|
138 | int event_loop(IOCHAN *iochans)
|
---|
139 | {
|
---|
140 | do /* loop as long as there are active associations to process */
|
---|
141 | {
|
---|
142 | IOCHAN p, nextp;
|
---|
143 | fd_set in, out, except;
|
---|
144 | int res, max;
|
---|
145 | static struct timeval nullto = {0, 0}, to;
|
---|
146 | struct timeval *timeout;
|
---|
147 |
|
---|
148 | FD_ZERO(&in);
|
---|
149 | FD_ZERO(&out);
|
---|
150 | FD_ZERO(&except);
|
---|
151 | timeout = &to; /* hang on select */
|
---|
152 | to.tv_sec = 5*60;
|
---|
153 | to.tv_usec = 0;
|
---|
154 | max = 0;
|
---|
155 | for (p = *iochans; p; p = p->next)
|
---|
156 | {
|
---|
157 | if (p->force_event)
|
---|
158 | timeout = &nullto; /* polling select */
|
---|
159 | if (p->flags & EVENT_INPUT)
|
---|
160 | FD_SET(p->fd, &in);
|
---|
161 | if (p->flags & EVENT_OUTPUT)
|
---|
162 | FD_SET(p->fd, &out);
|
---|
163 | if (p->flags & EVENT_EXCEPT)
|
---|
164 | FD_SET(p->fd, &except);
|
---|
165 | if (p->fd > max)
|
---|
166 | max = p->fd;
|
---|
167 | }
|
---|
168 | if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
|
---|
169 | {
|
---|
170 | if (errno == EINTR)
|
---|
171 | continue;
|
---|
172 | else
|
---|
173 | {
|
---|
174 | /* Destroy the first member in the chain, and try again */
|
---|
175 | association *assoc = (association *)iochan_getdata(*iochans);
|
---|
176 | COMSTACK conn = assoc->client_link;
|
---|
177 |
|
---|
178 | cs_close(conn);
|
---|
179 | destroy_association(assoc);
|
---|
180 | iochan_destroy(*iochans);
|
---|
181 | yaz_log(LOG_DEBUG, "error select, destroying iochan %p",
|
---|
182 | *iochans);
|
---|
183 | }
|
---|
184 | }
|
---|
185 | for (p = *iochans; p; p = p->next)
|
---|
186 | {
|
---|
187 | int force_event = p->force_event;
|
---|
188 | time_t now = time(0);
|
---|
189 |
|
---|
190 | p->force_event = 0;
|
---|
191 | if (!p->destroyed && (FD_ISSET(p->fd, &in) ||
|
---|
192 | force_event == EVENT_INPUT))
|
---|
193 | {
|
---|
194 | p->last_event = now;
|
---|
195 | (*p->fun)(p, EVENT_INPUT);
|
---|
196 | }
|
---|
197 | if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
|
---|
198 | force_event == EVENT_OUTPUT))
|
---|
199 | {
|
---|
200 | p->last_event = now;
|
---|
201 | (*p->fun)(p, EVENT_OUTPUT);
|
---|
202 | }
|
---|
203 | if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
|
---|
204 | force_event == EVENT_EXCEPT))
|
---|
205 | {
|
---|
206 | p->last_event = now;
|
---|
207 | (*p->fun)(p, EVENT_EXCEPT);
|
---|
208 | }
|
---|
209 | if (!p->destroyed && ((p->max_idle && now - p->last_event >
|
---|
210 | p->max_idle) || force_event == EVENT_TIMEOUT))
|
---|
211 | {
|
---|
212 | p->last_event = now;
|
---|
213 | (*p->fun)(p, EVENT_TIMEOUT);
|
---|
214 | }
|
---|
215 | }
|
---|
216 | for (p = *iochans; p; p = nextp)
|
---|
217 | {
|
---|
218 | nextp = p->next;
|
---|
219 |
|
---|
220 | if (p->destroyed)
|
---|
221 | {
|
---|
222 | IOCHAN tmp = p, pr;
|
---|
223 |
|
---|
224 | /* We need to inform the threadlist that this channel has been destroyed */
|
---|
225 | statserv_remove(p);
|
---|
226 |
|
---|
227 | /* Now reset the pointers */
|
---|
228 | if (p == *iochans)
|
---|
229 | *iochans = p->next;
|
---|
230 | else
|
---|
231 | {
|
---|
232 | for (pr = *iochans; pr; pr = pr->next)
|
---|
233 | if (pr->next == p)
|
---|
234 | break;
|
---|
235 | assert(pr); /* grave error if it weren't there */
|
---|
236 | pr->next = p->next;
|
---|
237 | }
|
---|
238 | if (nextp == p)
|
---|
239 | nextp = p->next;
|
---|
240 | xfree(tmp);
|
---|
241 | }
|
---|
242 | }
|
---|
243 | }
|
---|
244 | while (*iochans);
|
---|
245 | return 0;
|
---|
246 | }
|
---|