]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/dispatch.c
Fix up char * -> unsigned char * mismatches.
[thirdparty/dhcp.git] / omapip / dispatch.c
CommitLineData
61b844bf
TL
1/* dispatch.c
2
3 I/O dispatcher. */
4
5/*
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23#include <omapip/omapip.h>
24
25static omapi_io_object_t omapi_io_states;
26u_int32_t cur_time;
27
28/* Register an I/O handle so that we can do asynchronous I/O on it. */
29
30isc_result_t omapi_register_io_object (omapi_object_t *h,
31 int (*readfd) (omapi_object_t *),
32 int (*writefd) (omapi_object_t *),
33 isc_result_t (*reader)
34 (omapi_object_t *),
35 isc_result_t (*writer)
36 (omapi_object_t *),
37 isc_result_t (*reaper)
38 (omapi_object_t *))
39{
40 isc_result_t status;
41 omapi_io_object_t *obj, *p;
42
43 /* omapi_io_states is a static object. If its reference count
44 is zero, this is the first I/O handle to be registered, so
45 we need to initialize it. Because there is no inner or outer
46 pointer on this object, and we're setting its refcnt to 1, it
47 will never be freed. */
48 if (!omapi_io_states.refcnt) {
49 omapi_io_states.refcnt = 1;
50 omapi_io_states.type = omapi_type_io_object;
51 }
52
53 obj = malloc (sizeof *obj);
54 if (!obj)
55 return ISC_R_NOMEMORY;
56 memset (obj, 0, sizeof *obj);
57
58 obj -> refcnt = 1;
59 obj -> type = omapi_type_io_object;
60
61 status = omapi_object_reference (&obj -> inner, h,
62 "omapi_register_io_object");
63 if (status != ISC_R_SUCCESS) {
64 omapi_object_dereference ((omapi_object_t **)&obj,
65 "omapi_register_io_object");
66 return status;
67 }
68
69 status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
70 "omapi_register_io_object");
71 if (status != ISC_R_SUCCESS) {
72 omapi_object_dereference ((omapi_object_t **)&obj,
73 "omapi_register_io_object");
74 return status;
75 }
76
77 /* Find the last I/O state, if there are any. */
78 for (p = omapi_io_states.next;
79 p && p -> next; p = p -> next)
80 ;
81 if (p)
82 p -> next = obj;
83 else
84 omapi_io_states.next = obj;
85
86 obj -> readfd = readfd;
87 obj -> writefd = writefd;
88 obj -> reader = reader;
89 obj -> writer = writer;
90 obj -> reaper = reaper;
91 return ISC_R_SUCCESS;
92}
93
94isc_result_t omapi_dispatch (struct timeval *t)
95{
96 return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
97 t);
98}
99
100isc_result_t omapi_wait_for_completion (omapi_object_t *object,
101 struct timeval *t)
102{
103 isc_result_t status;
104 omapi_waiter_object_t *waiter;
105 omapi_object_t *inner;
106
107 if (object) {
108 waiter = malloc (sizeof *waiter);
109 if (!waiter)
110 return ISC_R_NOMEMORY;
111 memset (waiter, 0, sizeof *waiter);
112 waiter -> refcnt = 1;
113 waiter -> type = omapi_type_waiter;
114
115 /* Paste the waiter object onto the inner object we're
116 waiting on. */
117 for (inner = object; inner -> inner; inner = inner -> inner)
118 ;
119
120 status = omapi_object_reference (&waiter -> outer, inner,
121 "omapi_wait_for_completion");
122 if (status != ISC_R_SUCCESS) {
123 omapi_object_dereference ((omapi_object_t **)&waiter,
124 "omapi_wait_for_completion");
125 return status;
126 }
127
128 status = omapi_object_reference (&inner -> inner,
129 (omapi_object_t *)waiter,
130 "omapi_wait_for_completion");
131 if (status != ISC_R_SUCCESS) {
132 omapi_object_dereference ((omapi_object_t **)&waiter,
133 "omapi_wait_for_completion");
134 return status;
135 }
136 } else
137 waiter = (omapi_waiter_object_t *)0;
138
139 do {
140 status = omapi_one_dispatch (waiter, t);
141 if (status != ISC_R_SUCCESS)
142 return status;
143 } while (!waiter || !waiter -> ready);
144
727ebc3a
TL
145 if (waiter -> outer) {
146 if (waiter -> outer -> inner) {
147 omapi_object_dereference (&waiter -> outer -> inner,
148 "omapi_wait_for_completion");
149 if (waiter -> inner)
150 omapi_object_reference
151 (&waiter -> outer -> inner,
152 waiter -> inner,
153 "omapi_wait_for_completion");
154 }
155 omapi_object_dereference (&waiter -> outer,
156 "omapi_wait_for_completion");
157 }
158 if (waiter -> inner)
159 omapi_object_dereference (&waiter -> inner,
160 "omapi_wait_for_completion");
161
61b844bf
TL
162 omapi_object_dereference ((omapi_object_t **)&waiter,
163 "omapi_wait_for_completion");
164 return ISC_R_SUCCESS;
165}
166
167isc_result_t omapi_one_dispatch (omapi_waiter_object_t *waiter,
168 struct timeval *t)
169{
170 fd_set r, w, x;
171 int max = 0;
172 int count;
173 int desc;
174 struct timeval now, to;
175 omapi_io_object_t *io, *prev;
176 isc_result_t status;
177
178 FD_ZERO (&x);
179
180 /* First, see if the timeout has expired, and if so return. */
181 if (t) {
182 gettimeofday (&now, (struct timezone *)0);
183 cur_time = now.tv_sec;
184 if (now.tv_sec > t -> tv_sec ||
185 (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
186 return ISC_R_TIMEDOUT;
187
188 /* We didn't time out, so figure out how long until
189 we do. */
190 to.tv_sec = t -> tv_sec - now.tv_sec;
191 to.tv_usec = t -> tv_usec - now.tv_usec;
192 if (to.tv_usec < 0) {
193 to.tv_usec += 1000000;
194 to.tv_sec--;
195 }
196 }
197
198 /* If the object we're waiting on has reached completion,
199 return now. */
200 if (waiter && waiter -> ready)
201 return ISC_R_SUCCESS;
202
203 /* If we have no I/O state, we can't proceed. */
204 if (!(io = omapi_io_states.next))
205 return ISC_R_NOMORE;
206
207 /* Set up the read and write masks. */
208 FD_ZERO (&r);
209 FD_ZERO (&w);
210
211 for (; io; io = io -> next) {
212 /* Check for a read socket. If we shouldn't be
213 trying to read for this I/O object, either there
214 won't be a readfd function, or it'll return -1. */
215 if (io -> readfd &&
216 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
217 FD_SET (desc, &r);
218 if (desc > max)
219 max = desc;
220 }
221
222 /* Same deal for write fdets. */
223 if (io -> writefd &&
224 (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
225 FD_SET (desc, &w);
226 if (desc > max)
227 max = desc;
228 }
229 }
230
231 /* Wait for a packet or a timeout... XXX */
232 count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0);
233
234 /* Get the current time... */
235 gettimeofday (&now, (struct timezone *)0);
236 cur_time = now.tv_sec;
237
238 /* Not likely to be transitory... */
239 if (count < 0)
240 return ISC_R_UNEXPECTED;
241
242 for (io = omapi_io_states.next; io; io = io -> next) {
243 /* Check for a read descriptor, and if there is one,
244 see if we got input on that socket. */
245 if (io -> readfd &&
246 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
247 if (FD_ISSET (desc, &r))
248 status = ((*(io -> reader)) (io -> inner));
249 /* XXX what to do with status? */
250 }
251
252 /* Same deal for write descriptors. */
253 if (io -> writefd &&
254 (desc = (*(io -> writefd)) (io -> inner)) >= 0)
255 {
256 if (FD_ISSET (desc, &w))
257 status = ((*(io -> writer)) (io -> inner));
258 /* XXX what to do with status? */
259 }
260 }
261
262 /* Now check for I/O handles that are no longer valid,
263 and remove them from the list. */
264 prev = (omapi_io_object_t *)0;
265 for (io = omapi_io_states.next; io; io = io -> next) {
266 if (io -> reaper) {
267 status = (*(io -> reaper)) (io -> inner);
268 if (status != ISC_R_SUCCESS) {
269 omapi_io_object_t *tmp =
270 (omapi_io_object_t *)0;
271 /* Save a reference to the next
272 pointer, if there is one. */
273 if (io -> next)
274 omapi_object_reference
275 ((omapi_object_t **)&tmp,
276 (omapi_object_t *)io -> next,
277 "omapi_wfc");
278 if (prev) {
279 omapi_object_dereference
280 (((omapi_object_t **)
281 &prev -> next), "omapi_wfc");
282 if (tmp)
283 omapi_object_reference
284 (((omapi_object_t **)
285 &prev -> next),
286 (omapi_object_t *)tmp,
287 "omapi_wfc");
288 } else {
289 omapi_object_dereference
290 (((omapi_object_t **)
291 &omapi_io_states.next),
292 "omapi_wfc");
293 if (tmp)
294 omapi_object_reference
295 (((omapi_object_t **)
296 &omapi_io_states.next),
297 (omapi_object_t *)tmp,
298 "omapi_wfc");
299 else
300 omapi_signal_in
301 ((omapi_object_t *)
302 &omapi_io_states,
303 "ready");
304 }
305 if (tmp)
306 omapi_object_dereference
307 ((omapi_object_t **)&tmp,
308 "omapi_wfc");
309 }
310 }
311 prev = io;
312 }
313
314 return ISC_R_SUCCESS;
315}
316
317isc_result_t omapi_io_set_value (omapi_object_t *h,
318 omapi_object_t *id,
319 omapi_data_string_t *name,
320 omapi_typed_data_t *value)
321{
322 if (h -> type != omapi_type_io_object)
323 return ISC_R_INVALIDARG;
324
325 if (h -> inner && h -> inner -> type -> set_value)
326 return (*(h -> inner -> type -> set_value))
327 (h -> inner, id, name, value);
328 return ISC_R_NOTFOUND;
329}
330
331isc_result_t omapi_io_get_value (omapi_object_t *h,
332 omapi_object_t *id,
333 omapi_data_string_t *name,
334 omapi_value_t **value)
335{
336 if (h -> type != omapi_type_io_object)
337 return ISC_R_INVALIDARG;
338
339 if (h -> inner && h -> inner -> type -> get_value)
340 return (*(h -> inner -> type -> get_value))
341 (h -> inner, id, name, value);
342 return ISC_R_NOTFOUND;
343}
344
345isc_result_t omapi_io_destroy (omapi_object_t *h, char *name)
346{
347 if (h -> type != omapi_type_io_object)
348 return ISC_R_INVALIDARG;
349 return ISC_R_SUCCESS;
350}
351
352isc_result_t omapi_io_signal_handler (omapi_object_t *h,
353 char *name, va_list ap)
354{
355 if (h -> type != omapi_type_io_object)
356 return ISC_R_INVALIDARG;
357
358 if (h -> inner && h -> inner -> type -> signal_handler)
359 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
360 name, ap);
361 return ISC_R_NOTFOUND;
362}
363
364isc_result_t omapi_io_stuff_values (omapi_object_t *c,
365 omapi_object_t *id,
366 omapi_object_t *i)
367{
368 if (i -> type != omapi_type_io_object)
369 return ISC_R_INVALIDARG;
370
371 if (i -> inner && i -> inner -> type -> stuff_values)
372 return (*(i -> inner -> type -> stuff_values)) (c, id,
373 i -> inner);
374 return ISC_R_SUCCESS;
375}
376
377isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
378 char *name, va_list ap)
379{
380 omapi_waiter_object_t *waiter;
381
382 if (h -> type != omapi_type_waiter)
383 return ISC_R_INVALIDARG;
384
385 if (!strcmp (name, "ready")) {
386 waiter = (omapi_waiter_object_t *)h;
387 waiter -> ready = 1;
388 return ISC_R_SUCCESS;
389 }
390
391 if (h -> inner && h -> inner -> type -> signal_handler)
392 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
393 name, ap);
394 return ISC_R_NOTFOUND;
395}
396