]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/dispatch.c
Oops, fix a past-o.
[thirdparty/dhcp.git] / omapip / dispatch.c
CommitLineData
61b844bf
TL
1/* dispatch.c
2
3 I/O dispatcher. */
4
5/*
49733f31
TL
6 * Copyright (c) 1999-2000 Internet Software Consortium.
7 * All rights reserved.
61b844bf 8 *
49733f31
TL
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
61b844bf 12 *
49733f31
TL
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
61b844bf 21 *
49733f31
TL
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
61b844bf
TL
42 */
43
6a4c4be8 44#include <omapip/omapip_p.h>
61b844bf
TL
45
46static omapi_io_object_t omapi_io_states;
47u_int32_t cur_time;
48
49/* Register an I/O handle so that we can do asynchronous I/O on it. */
50
51isc_result_t omapi_register_io_object (omapi_object_t *h,
52 int (*readfd) (omapi_object_t *),
53 int (*writefd) (omapi_object_t *),
54 isc_result_t (*reader)
55 (omapi_object_t *),
56 isc_result_t (*writer)
57 (omapi_object_t *),
58 isc_result_t (*reaper)
59 (omapi_object_t *))
60{
61 isc_result_t status;
62 omapi_io_object_t *obj, *p;
63
64 /* omapi_io_states is a static object. If its reference count
65 is zero, this is the first I/O handle to be registered, so
66 we need to initialize it. Because there is no inner or outer
67 pointer on this object, and we're setting its refcnt to 1, it
68 will never be freed. */
69 if (!omapi_io_states.refcnt) {
70 omapi_io_states.refcnt = 1;
71 omapi_io_states.type = omapi_type_io_object;
72 }
73
4bd8800e 74 obj = dmalloc (sizeof *obj, MDL);
61b844bf
TL
75 if (!obj)
76 return ISC_R_NOMEMORY;
77 memset (obj, 0, sizeof *obj);
61b844bf 78 obj -> refcnt = 1;
37e365b4 79 rc_register_mdl (&obj, obj, obj -> refcnt);
61b844bf
TL
80 obj -> type = omapi_type_io_object;
81
4bd8800e 82 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 83 if (status != ISC_R_SUCCESS) {
4bd8800e 84 omapi_object_dereference ((omapi_object_t **)&obj, MDL);
61b844bf
TL
85 return status;
86 }
87
4bd8800e
TL
88 status = omapi_object_reference (&h -> outer,
89 (omapi_object_t *)obj, MDL);
61b844bf 90 if (status != ISC_R_SUCCESS) {
4bd8800e 91 omapi_object_dereference ((omapi_object_t **)&obj, MDL);
61b844bf
TL
92 return status;
93 }
94
95 /* Find the last I/O state, if there are any. */
96 for (p = omapi_io_states.next;
97 p && p -> next; p = p -> next)
98 ;
99 if (p)
b6237fb2
TL
100 omapi_object_reference ((omapi_object_t **)&p -> next,
101 (omapi_object_t *)obj, MDL);
61b844bf 102 else
b6237fb2
TL
103 omapi_object_reference
104 ((omapi_object_t **)&omapi_io_states.next,
105 (omapi_object_t *)obj, MDL);
61b844bf
TL
106
107 obj -> readfd = readfd;
108 obj -> writefd = writefd;
109 obj -> reader = reader;
110 obj -> writer = writer;
111 obj -> reaper = reaper;
112 return ISC_R_SUCCESS;
113}
114
b6237fb2
TL
115isc_result_t omapi_unregister_io_object (omapi_object_t *h)
116{
117 omapi_io_object_t *p, *obj, *last;
118 omapi_object_t *ph;
119
120 obj = (omapi_io_object_t *)h -> outer;
121 ph = (omapi_object_t *)0;
122 omapi_object_reference (&ph, h -> outer, MDL);
123
124 /* remove from the list of I/O states */
125 for (p = omapi_io_states.next; p; p = p -> next) {
126 if ((omapi_object_t *)p == h -> outer) {
127 omapi_object_dereference ((omapi_object_t **)
128 &last -> next, MDL);
129 omapi_object_reference ((omapi_object_t **)
130 &last -> next,
131 (omapi_object_t *)p -> next,
132 MDL);
133 break;
134 }
135 last = p;
136 }
137 if (obj -> next)
138 omapi_object_dereference ((omapi_object_t **)&obj -> next,
139 MDL);
140 if (obj -> outer) {
141 if (obj -> outer -> inner == (omapi_object_t *)obj)
142 omapi_object_dereference (&obj -> outer -> inner,
143 MDL);
144 omapi_object_dereference (&obj -> outer, MDL);
145 }
146 omapi_object_dereference (&obj -> inner, MDL);
147 omapi_object_dereference (&h -> outer, MDL);
148 omapi_object_dereference (&ph, MDL);
149 return ISC_R_SUCCESS;
150}
151
61b844bf
TL
152isc_result_t omapi_dispatch (struct timeval *t)
153{
154 return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
155 t);
156}
157
158isc_result_t omapi_wait_for_completion (omapi_object_t *object,
159 struct timeval *t)
160{
161 isc_result_t status;
162 omapi_waiter_object_t *waiter;
163 omapi_object_t *inner;
164
165 if (object) {
4bd8800e 166 waiter = dmalloc (sizeof *waiter, MDL);
61b844bf
TL
167 if (!waiter)
168 return ISC_R_NOMEMORY;
169 memset (waiter, 0, sizeof *waiter);
170 waiter -> refcnt = 1;
37e365b4 171 rc_register_mdl (&waiter, waiter, waiter -> refcnt);
61b844bf
TL
172 waiter -> type = omapi_type_waiter;
173
174 /* Paste the waiter object onto the inner object we're
175 waiting on. */
176 for (inner = object; inner -> inner; inner = inner -> inner)
177 ;
178
4bd8800e 179 status = omapi_object_reference (&waiter -> outer, inner, MDL);
61b844bf
TL
180 if (status != ISC_R_SUCCESS) {
181 omapi_object_dereference ((omapi_object_t **)&waiter,
4bd8800e 182 MDL);
61b844bf
TL
183 return status;
184 }
185
186 status = omapi_object_reference (&inner -> inner,
187 (omapi_object_t *)waiter,
4bd8800e 188 MDL);
61b844bf
TL
189 if (status != ISC_R_SUCCESS) {
190 omapi_object_dereference ((omapi_object_t **)&waiter,
4bd8800e 191 MDL);
61b844bf
TL
192 return status;
193 }
194 } else
195 waiter = (omapi_waiter_object_t *)0;
196
197 do {
6a4c4be8 198 status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
61b844bf
TL
199 if (status != ISC_R_SUCCESS)
200 return status;
201 } while (!waiter || !waiter -> ready);
202
727ebc3a
TL
203 if (waiter -> outer) {
204 if (waiter -> outer -> inner) {
205 omapi_object_dereference (&waiter -> outer -> inner,
4bd8800e 206 MDL);
727ebc3a
TL
207 if (waiter -> inner)
208 omapi_object_reference
209 (&waiter -> outer -> inner,
4bd8800e 210 waiter -> inner, MDL);
727ebc3a 211 }
4bd8800e 212 omapi_object_dereference (&waiter -> outer, MDL);
727ebc3a
TL
213 }
214 if (waiter -> inner)
4bd8800e 215 omapi_object_dereference (&waiter -> inner, MDL);
727ebc3a 216
4bd8800e 217 omapi_object_dereference ((omapi_object_t **)&waiter, MDL);
61b844bf
TL
218 return ISC_R_SUCCESS;
219}
220
6a4c4be8 221isc_result_t omapi_one_dispatch (omapi_object_t *wo,
61b844bf
TL
222 struct timeval *t)
223{
224 fd_set r, w, x;
225 int max = 0;
226 int count;
227 int desc;
228 struct timeval now, to;
229 omapi_io_object_t *io, *prev;
230 isc_result_t status;
6a4c4be8 231 omapi_waiter_object_t *waiter;
b6237fb2 232 omapi_object_t *tmp = (omapi_object_t *)0;
6a4c4be8
TL
233
234 if (!wo || wo -> type != omapi_type_waiter)
235 waiter = (omapi_waiter_object_t *)0;
236 else
237 waiter = (omapi_waiter_object_t *)wo;
61b844bf
TL
238
239 FD_ZERO (&x);
240
241 /* First, see if the timeout has expired, and if so return. */
242 if (t) {
243 gettimeofday (&now, (struct timezone *)0);
244 cur_time = now.tv_sec;
245 if (now.tv_sec > t -> tv_sec ||
246 (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
247 return ISC_R_TIMEDOUT;
248
249 /* We didn't time out, so figure out how long until
250 we do. */
251 to.tv_sec = t -> tv_sec - now.tv_sec;
252 to.tv_usec = t -> tv_usec - now.tv_usec;
253 if (to.tv_usec < 0) {
254 to.tv_usec += 1000000;
255 to.tv_sec--;
256 }
257 }
258
259 /* If the object we're waiting on has reached completion,
260 return now. */
261 if (waiter && waiter -> ready)
262 return ISC_R_SUCCESS;
263
264 /* If we have no I/O state, we can't proceed. */
265 if (!(io = omapi_io_states.next))
266 return ISC_R_NOMORE;
267
268 /* Set up the read and write masks. */
269 FD_ZERO (&r);
270 FD_ZERO (&w);
271
272 for (; io; io = io -> next) {
273 /* Check for a read socket. If we shouldn't be
274 trying to read for this I/O object, either there
275 won't be a readfd function, or it'll return -1. */
276 if (io -> readfd &&
277 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
278 FD_SET (desc, &r);
279 if (desc > max)
280 max = desc;
281 }
282
283 /* Same deal for write fdets. */
284 if (io -> writefd &&
285 (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
286 FD_SET (desc, &w);
287 if (desc > max)
288 max = desc;
289 }
290 }
291
292 /* Wait for a packet or a timeout... XXX */
293 count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0);
294
295 /* Get the current time... */
296 gettimeofday (&now, (struct timezone *)0);
297 cur_time = now.tv_sec;
298
299 /* Not likely to be transitory... */
300 if (count < 0)
301 return ISC_R_UNEXPECTED;
302
303 for (io = omapi_io_states.next; io; io = io -> next) {
b6237fb2 304 omapi_object_reference (&tmp, io -> inner, MDL);
61b844bf
TL
305 /* Check for a read descriptor, and if there is one,
306 see if we got input on that socket. */
307 if (io -> readfd &&
b6237fb2 308 (desc = (*(io -> readfd)) (tmp)) >= 0) {
61b844bf 309 if (FD_ISSET (desc, &r))
b6237fb2 310 status = ((*(io -> reader)) (tmp));
61b844bf
TL
311 /* XXX what to do with status? */
312 }
313
314 /* Same deal for write descriptors. */
315 if (io -> writefd &&
b6237fb2 316 (desc = (*(io -> writefd)) (tmp)) >= 0)
61b844bf
TL
317 {
318 if (FD_ISSET (desc, &w))
b6237fb2 319 status = ((*(io -> writer)) (tmp));
61b844bf
TL
320 /* XXX what to do with status? */
321 }
b6237fb2 322 omapi_object_dereference (&tmp, MDL);
61b844bf
TL
323 }
324
325 /* Now check for I/O handles that are no longer valid,
326 and remove them from the list. */
327 prev = (omapi_io_object_t *)0;
328 for (io = omapi_io_states.next; io; io = io -> next) {
329 if (io -> reaper) {
330 status = (*(io -> reaper)) (io -> inner);
331 if (status != ISC_R_SUCCESS) {
332 omapi_io_object_t *tmp =
333 (omapi_io_object_t *)0;
334 /* Save a reference to the next
335 pointer, if there is one. */
336 if (io -> next)
337 omapi_object_reference
338 ((omapi_object_t **)&tmp,
339 (omapi_object_t *)io -> next,
4bd8800e 340 MDL);
61b844bf
TL
341 if (prev) {
342 omapi_object_dereference
343 (((omapi_object_t **)
4bd8800e 344 &prev -> next), MDL);
61b844bf
TL
345 if (tmp)
346 omapi_object_reference
347 (((omapi_object_t **)
348 &prev -> next),
349 (omapi_object_t *)tmp,
4bd8800e 350 MDL);
61b844bf
TL
351 } else {
352 omapi_object_dereference
353 (((omapi_object_t **)
354 &omapi_io_states.next),
4bd8800e 355 MDL);
61b844bf
TL
356 if (tmp)
357 omapi_object_reference
358 (((omapi_object_t **)
359 &omapi_io_states.next),
360 (omapi_object_t *)tmp,
4bd8800e 361 MDL);
61b844bf
TL
362 else
363 omapi_signal_in
364 ((omapi_object_t *)
365 &omapi_io_states,
366 "ready");
367 }
368 if (tmp)
369 omapi_object_dereference
4bd8800e 370 ((omapi_object_t **)&tmp, MDL);
61b844bf
TL
371 }
372 }
373 prev = io;
374 }
375
376 return ISC_R_SUCCESS;
377}
378
379isc_result_t omapi_io_set_value (omapi_object_t *h,
380 omapi_object_t *id,
381 omapi_data_string_t *name,
382 omapi_typed_data_t *value)
383{
384 if (h -> type != omapi_type_io_object)
385 return ISC_R_INVALIDARG;
386
387 if (h -> inner && h -> inner -> type -> set_value)
388 return (*(h -> inner -> type -> set_value))
389 (h -> inner, id, name, value);
390 return ISC_R_NOTFOUND;
391}
392
393isc_result_t omapi_io_get_value (omapi_object_t *h,
394 omapi_object_t *id,
395 omapi_data_string_t *name,
396 omapi_value_t **value)
397{
398 if (h -> type != omapi_type_io_object)
399 return ISC_R_INVALIDARG;
400
401 if (h -> inner && h -> inner -> type -> get_value)
402 return (*(h -> inner -> type -> get_value))
403 (h -> inner, id, name, value);
404 return ISC_R_NOTFOUND;
405}
406
4bd8800e 407isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
61b844bf 408{
bdcaf7b9
TL
409 omapi_io_object_t *obj, *p, *last;
410
61b844bf
TL
411 if (h -> type != omapi_type_io_object)
412 return ISC_R_INVALIDARG;
bdcaf7b9
TL
413
414 obj = (omapi_io_object_t *)h;
415
b6237fb2
TL
416 /* remove from the list of I/O states */
417 for (p = omapi_io_states.next; p; p = p -> next) {
418 if (p == obj) {
419 omapi_object_dereference ((omapi_object_t **)
420 &last -> next, MDL);
421 omapi_object_reference ((omapi_object_t **)
422 &last -> next,
423 (omapi_object_t *)p -> next,
424 MDL);
425 omapi_object_dereference ((omapi_object_t **)&p, MDL);
426 break;
bdcaf7b9 427 }
b6237fb2 428 last = p;
bdcaf7b9 429 }
b6237fb2 430
61b844bf
TL
431 return ISC_R_SUCCESS;
432}
433
434isc_result_t omapi_io_signal_handler (omapi_object_t *h,
b1b7b521 435 const char *name, va_list ap)
61b844bf
TL
436{
437 if (h -> type != omapi_type_io_object)
438 return ISC_R_INVALIDARG;
439
440 if (h -> inner && h -> inner -> type -> signal_handler)
441 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
442 name, ap);
443 return ISC_R_NOTFOUND;
444}
445
446isc_result_t omapi_io_stuff_values (omapi_object_t *c,
447 omapi_object_t *id,
448 omapi_object_t *i)
449{
450 if (i -> type != omapi_type_io_object)
451 return ISC_R_INVALIDARG;
452
453 if (i -> inner && i -> inner -> type -> stuff_values)
454 return (*(i -> inner -> type -> stuff_values)) (c, id,
455 i -> inner);
456 return ISC_R_SUCCESS;
457}
458
459isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
b1b7b521 460 const char *name, va_list ap)
61b844bf
TL
461{
462 omapi_waiter_object_t *waiter;
463
464 if (h -> type != omapi_type_waiter)
465 return ISC_R_INVALIDARG;
466
467 if (!strcmp (name, "ready")) {
468 waiter = (omapi_waiter_object_t *)h;
469 waiter -> ready = 1;
470 return ISC_R_SUCCESS;
471 }
472
473 if (h -> inner && h -> inner -> type -> signal_handler)
474 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
475 name, ap);
476 return ISC_R_NOTFOUND;
477}
478