]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* dispatch.c |
2 | ||
3 | I/O dispatcher. */ | |
4 | ||
5 | /* | |
dccb6edf | 6 | * Copyright (c) 2004,2007-2008 by Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 7 | * Copyright (c) 1999-2003 by Internet Software Consortium |
61b844bf | 8 | * |
98311e4b DH |
9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above | |
11 | * copyright notice and this permission notice appear in all copies. | |
61b844bf | 12 | * |
98311e4b DH |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR | |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
19 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
61b844bf | 20 | * |
98311e4b DH |
21 | * Internet Systems Consortium, Inc. |
22 | * 950 Charter Street | |
23 | * Redwood City, CA 94063 | |
24 | * <info@isc.org> | |
2c85ac9b | 25 | * https://www.isc.org/ |
49733f31 | 26 | * |
98311e4b | 27 | * This software has been written for Internet Systems Consortium |
49733f31 | 28 | * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. |
98311e4b | 29 | * To learn more about Internet Systems Consortium, see |
2c85ac9b | 30 | * ``https://www.isc.org/''. To learn more about Vixie Enterprises, |
49733f31 TL |
31 | * see ``http://www.vix.com''. To learn more about Nominum, Inc., see |
32 | * ``http://www.nominum.com''. | |
61b844bf TL |
33 | */ |
34 | ||
fe5b0fdd DH |
35 | #include "dhcpd.h" |
36 | ||
6a4c4be8 | 37 | #include <omapip/omapip_p.h> |
28868515 | 38 | #include <sys/time.h> |
61b844bf TL |
39 | |
40 | static omapi_io_object_t omapi_io_states; | |
be62cf06 | 41 | struct timeval cur_tv; |
61b844bf | 42 | |
6368a1bd DH |
43 | struct eventqueue *rw_queue_empty; |
44 | ||
20916cae TL |
45 | OMAPI_OBJECT_ALLOC (omapi_io, |
46 | omapi_io_object_t, omapi_type_io_object) | |
47 | OMAPI_OBJECT_ALLOC (omapi_waiter, | |
48 | omapi_waiter_object_t, omapi_type_waiter) | |
49 | ||
6368a1bd DH |
50 | void |
51 | register_eventhandler(struct eventqueue **queue, void (*handler)(void *)) | |
52 | { | |
53 | struct eventqueue *t, *q; | |
54 | ||
55 | /* traverse to end of list */ | |
56 | t = NULL; | |
57 | for (q = *queue ; q ; q = q->next) { | |
58 | if (q->handler == handler) | |
59 | return; /* handler already registered */ | |
60 | t = q; | |
61 | } | |
62 | ||
63 | q = ((struct eventqueue *)dmalloc(sizeof(struct eventqueue), MDL)); | |
64 | if (!q) | |
65 | log_fatal("register_eventhandler: no memory!"); | |
66 | memset(q, 0, sizeof *q); | |
67 | if (t) | |
68 | t->next = q; | |
69 | else | |
70 | *queue = q; | |
71 | q->handler = handler; | |
72 | return; | |
73 | } | |
74 | ||
75 | void | |
76 | unregister_eventhandler(struct eventqueue **queue, void (*handler)(void *)) | |
77 | { | |
78 | struct eventqueue *t, *q; | |
79 | ||
80 | /* traverse to end of list */ | |
81 | t= NULL; | |
82 | for (q = *queue ; q ; q = q->next) { | |
83 | if (q->handler == handler) { | |
84 | if (t) | |
85 | t->next = q->next; | |
86 | else | |
87 | *queue = q->next; | |
88 | dfree(q, MDL); /* Don't access q after this!*/ | |
89 | break; | |
90 | } | |
91 | t = q; | |
92 | } | |
93 | return; | |
94 | } | |
95 | ||
96 | void | |
97 | trigger_event(struct eventqueue **queue) | |
98 | { | |
99 | struct eventqueue *q; | |
100 | ||
101 | for (q=*queue ; q ; q=q->next) { | |
102 | if (q->handler) | |
103 | (*q->handler)(NULL); | |
104 | } | |
105 | } | |
106 | ||
107 | ||
61b844bf TL |
108 | /* Register an I/O handle so that we can do asynchronous I/O on it. */ |
109 | ||
110 | isc_result_t omapi_register_io_object (omapi_object_t *h, | |
111 | int (*readfd) (omapi_object_t *), | |
112 | int (*writefd) (omapi_object_t *), | |
113 | isc_result_t (*reader) | |
114 | (omapi_object_t *), | |
115 | isc_result_t (*writer) | |
116 | (omapi_object_t *), | |
117 | isc_result_t (*reaper) | |
118 | (omapi_object_t *)) | |
119 | { | |
120 | isc_result_t status; | |
121 | omapi_io_object_t *obj, *p; | |
122 | ||
123 | /* omapi_io_states is a static object. If its reference count | |
124 | is zero, this is the first I/O handle to be registered, so | |
125 | we need to initialize it. Because there is no inner or outer | |
126 | pointer on this object, and we're setting its refcnt to 1, it | |
127 | will never be freed. */ | |
128 | if (!omapi_io_states.refcnt) { | |
129 | omapi_io_states.refcnt = 1; | |
130 | omapi_io_states.type = omapi_type_io_object; | |
131 | } | |
132 | ||
20916cae TL |
133 | obj = (omapi_io_object_t *)0; |
134 | status = omapi_io_allocate (&obj, MDL); | |
135 | if (status != ISC_R_SUCCESS) | |
136 | return status; | |
61b844bf | 137 | |
4bd8800e | 138 | status = omapi_object_reference (&obj -> inner, h, MDL); |
61b844bf | 139 | if (status != ISC_R_SUCCESS) { |
20916cae | 140 | omapi_io_dereference (&obj, MDL); |
61b844bf TL |
141 | return status; |
142 | } | |
143 | ||
4bd8800e TL |
144 | status = omapi_object_reference (&h -> outer, |
145 | (omapi_object_t *)obj, MDL); | |
61b844bf | 146 | if (status != ISC_R_SUCCESS) { |
20916cae | 147 | omapi_io_dereference (&obj, MDL); |
61b844bf TL |
148 | return status; |
149 | } | |
150 | ||
151 | /* Find the last I/O state, if there are any. */ | |
152 | for (p = omapi_io_states.next; | |
153 | p && p -> next; p = p -> next) | |
154 | ; | |
155 | if (p) | |
20916cae | 156 | omapi_io_reference (&p -> next, obj, MDL); |
61b844bf | 157 | else |
20916cae | 158 | omapi_io_reference (&omapi_io_states.next, obj, MDL); |
61b844bf TL |
159 | |
160 | obj -> readfd = readfd; | |
161 | obj -> writefd = writefd; | |
162 | obj -> reader = reader; | |
163 | obj -> writer = writer; | |
164 | obj -> reaper = reaper; | |
4619c0a2 DH |
165 | |
166 | omapi_io_dereference(&obj, MDL); | |
61b844bf TL |
167 | return ISC_R_SUCCESS; |
168 | } | |
169 | ||
b6237fb2 TL |
170 | isc_result_t omapi_unregister_io_object (omapi_object_t *h) |
171 | { | |
20916cae | 172 | omapi_io_object_t *p, *obj, *last, *ph; |
b6237fb2 | 173 | |
20916cae TL |
174 | if (!h -> outer || h -> outer -> type != omapi_type_io_object) |
175 | return ISC_R_INVALIDARG; | |
b6237fb2 | 176 | obj = (omapi_io_object_t *)h -> outer; |
20916cae TL |
177 | ph = (omapi_io_object_t *)0; |
178 | omapi_io_reference (&ph, obj, MDL); | |
b6237fb2 TL |
179 | |
180 | /* remove from the list of I/O states */ | |
c3064fe0 | 181 | last = &omapi_io_states; |
b6237fb2 | 182 | for (p = omapi_io_states.next; p; p = p -> next) { |
20916cae TL |
183 | if (p == obj) { |
184 | omapi_io_dereference (&last -> next, MDL); | |
185 | omapi_io_reference (&last -> next, p -> next, MDL); | |
b6237fb2 TL |
186 | break; |
187 | } | |
188 | last = p; | |
189 | } | |
190 | if (obj -> next) | |
20916cae TL |
191 | omapi_io_dereference (&obj -> next, MDL); |
192 | ||
b6237fb2 TL |
193 | if (obj -> outer) { |
194 | if (obj -> outer -> inner == (omapi_object_t *)obj) | |
195 | omapi_object_dereference (&obj -> outer -> inner, | |
196 | MDL); | |
197 | omapi_object_dereference (&obj -> outer, MDL); | |
198 | } | |
199 | omapi_object_dereference (&obj -> inner, MDL); | |
200 | omapi_object_dereference (&h -> outer, MDL); | |
20916cae | 201 | omapi_io_dereference (&ph, MDL); |
b6237fb2 TL |
202 | return ISC_R_SUCCESS; |
203 | } | |
204 | ||
61b844bf TL |
205 | isc_result_t omapi_dispatch (struct timeval *t) |
206 | { | |
207 | return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states, | |
208 | t); | |
209 | } | |
210 | ||
211 | isc_result_t omapi_wait_for_completion (omapi_object_t *object, | |
212 | struct timeval *t) | |
213 | { | |
214 | isc_result_t status; | |
215 | omapi_waiter_object_t *waiter; | |
216 | omapi_object_t *inner; | |
217 | ||
218 | if (object) { | |
20916cae TL |
219 | waiter = (omapi_waiter_object_t *)0; |
220 | status = omapi_waiter_allocate (&waiter, MDL); | |
221 | if (status != ISC_R_SUCCESS) | |
222 | return status; | |
61b844bf TL |
223 | |
224 | /* Paste the waiter object onto the inner object we're | |
225 | waiting on. */ | |
226 | for (inner = object; inner -> inner; inner = inner -> inner) | |
227 | ; | |
228 | ||
4bd8800e | 229 | status = omapi_object_reference (&waiter -> outer, inner, MDL); |
61b844bf | 230 | if (status != ISC_R_SUCCESS) { |
20916cae | 231 | omapi_waiter_dereference (&waiter, MDL); |
61b844bf TL |
232 | return status; |
233 | } | |
234 | ||
235 | status = omapi_object_reference (&inner -> inner, | |
236 | (omapi_object_t *)waiter, | |
4bd8800e | 237 | MDL); |
61b844bf | 238 | if (status != ISC_R_SUCCESS) { |
20916cae | 239 | omapi_waiter_dereference (&waiter, MDL); |
61b844bf TL |
240 | return status; |
241 | } | |
242 | } else | |
243 | waiter = (omapi_waiter_object_t *)0; | |
244 | ||
245 | do { | |
6a4c4be8 | 246 | status = omapi_one_dispatch ((omapi_object_t *)waiter, t); |
61b844bf TL |
247 | if (status != ISC_R_SUCCESS) |
248 | return status; | |
249 | } while (!waiter || !waiter -> ready); | |
250 | ||
727ebc3a TL |
251 | if (waiter -> outer) { |
252 | if (waiter -> outer -> inner) { | |
253 | omapi_object_dereference (&waiter -> outer -> inner, | |
4bd8800e | 254 | MDL); |
727ebc3a TL |
255 | if (waiter -> inner) |
256 | omapi_object_reference | |
257 | (&waiter -> outer -> inner, | |
4bd8800e | 258 | waiter -> inner, MDL); |
727ebc3a | 259 | } |
4bd8800e | 260 | omapi_object_dereference (&waiter -> outer, MDL); |
727ebc3a TL |
261 | } |
262 | if (waiter -> inner) | |
4bd8800e | 263 | omapi_object_dereference (&waiter -> inner, MDL); |
727ebc3a | 264 | |
49146f3c | 265 | status = waiter -> waitstatus; |
20916cae | 266 | omapi_waiter_dereference (&waiter, MDL); |
86a9cf83 | 267 | return status; |
61b844bf TL |
268 | } |
269 | ||
6a4c4be8 | 270 | isc_result_t omapi_one_dispatch (omapi_object_t *wo, |
61b844bf TL |
271 | struct timeval *t) |
272 | { | |
6368a1bd | 273 | fd_set r, w, x, rr, ww, xx; |
61b844bf TL |
274 | int max = 0; |
275 | int count; | |
276 | int desc; | |
277 | struct timeval now, to; | |
4619c0a2 | 278 | omapi_io_object_t *io, *prev, *next; |
6a4c4be8 | 279 | omapi_waiter_object_t *waiter; |
b6237fb2 | 280 | omapi_object_t *tmp = (omapi_object_t *)0; |
6a4c4be8 TL |
281 | |
282 | if (!wo || wo -> type != omapi_type_waiter) | |
283 | waiter = (omapi_waiter_object_t *)0; | |
284 | else | |
285 | waiter = (omapi_waiter_object_t *)wo; | |
61b844bf TL |
286 | |
287 | FD_ZERO (&x); | |
288 | ||
289 | /* First, see if the timeout has expired, and if so return. */ | |
290 | if (t) { | |
291 | gettimeofday (&now, (struct timezone *)0); | |
be62cf06 FD |
292 | cur_tv.tv_sec = now.tv_sec; |
293 | cur_tv.tv_usec = now.tv_usec; | |
61b844bf TL |
294 | if (now.tv_sec > t -> tv_sec || |
295 | (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec)) | |
296 | return ISC_R_TIMEDOUT; | |
297 | ||
298 | /* We didn't time out, so figure out how long until | |
299 | we do. */ | |
300 | to.tv_sec = t -> tv_sec - now.tv_sec; | |
301 | to.tv_usec = t -> tv_usec - now.tv_usec; | |
302 | if (to.tv_usec < 0) { | |
303 | to.tv_usec += 1000000; | |
304 | to.tv_sec--; | |
305 | } | |
d01dde76 DN |
306 | |
307 | /* It is possible for the timeout to get set larger than | |
308 | the largest time select() is willing to accept. | |
309 | Restricting the timeout to a maximum of one day should | |
310 | work around this. -DPN. (Ref: Bug #416) */ | |
311 | if (to.tv_sec > (60 * 60 * 24)) | |
312 | to.tv_sec = 60 * 60 * 24; | |
61b844bf TL |
313 | } |
314 | ||
315 | /* If the object we're waiting on has reached completion, | |
316 | return now. */ | |
317 | if (waiter && waiter -> ready) | |
318 | return ISC_R_SUCCESS; | |
319 | ||
cfb3f45d | 320 | again: |
61b844bf TL |
321 | /* If we have no I/O state, we can't proceed. */ |
322 | if (!(io = omapi_io_states.next)) | |
323 | return ISC_R_NOMORE; | |
324 | ||
325 | /* Set up the read and write masks. */ | |
326 | FD_ZERO (&r); | |
327 | FD_ZERO (&w); | |
328 | ||
329 | for (; io; io = io -> next) { | |
330 | /* Check for a read socket. If we shouldn't be | |
331 | trying to read for this I/O object, either there | |
332 | won't be a readfd function, or it'll return -1. */ | |
d8c46740 | 333 | if (io -> readfd && io -> inner && |
61b844bf TL |
334 | (desc = (*(io -> readfd)) (io -> inner)) >= 0) { |
335 | FD_SET (desc, &r); | |
336 | if (desc > max) | |
337 | max = desc; | |
338 | } | |
339 | ||
340 | /* Same deal for write fdets. */ | |
d8c46740 | 341 | if (io -> writefd && io -> inner && |
61b844bf TL |
342 | (desc = (*(io -> writefd)) (io -> inner)) >= 0) { |
343 | FD_SET (desc, &w); | |
344 | if (desc > max) | |
345 | max = desc; | |
346 | } | |
347 | } | |
348 | ||
6368a1bd DH |
349 | /* poll if all reader are dry */ |
350 | now.tv_sec = 0; | |
351 | now.tv_usec = 0; | |
352 | rr=r; | |
353 | ww=w; | |
354 | xx=x; | |
355 | ||
356 | /* poll once */ | |
357 | count = select(max + 1, &r, &w, &x, &now); | |
358 | if (!count) { | |
359 | /* We are dry now */ | |
360 | trigger_event(&rw_queue_empty); | |
361 | /* Wait for a packet or a timeout... XXX */ | |
f9453d21 DH |
362 | r = rr; |
363 | w = ww; | |
364 | x = xx; | |
365 | count = select(max + 1, &r, &w, &x, t ? &to : NULL); | |
6368a1bd | 366 | } |
61b844bf TL |
367 | |
368 | /* Get the current time... */ | |
be62cf06 | 369 | gettimeofday (&cur_tv, (struct timezone *)0); |
61b844bf | 370 | |
cfb3f45d TL |
371 | /* We probably have a bad file descriptor. Figure out which one. |
372 | When we find it, call the reaper function on it, which will | |
373 | maybe make it go away, and then try again. */ | |
374 | if (count < 0) { | |
375 | struct timeval t0; | |
9bf59e83 TL |
376 | omapi_io_object_t *prev = (omapi_io_object_t *)0; |
377 | io = (omapi_io_object_t *)0; | |
378 | if (omapi_io_states.next) | |
379 | omapi_io_reference (&io, omapi_io_states.next, MDL); | |
cfb3f45d | 380 | |
9bf59e83 | 381 | while (io) { |
cfb3f45d TL |
382 | omapi_object_t *obj; |
383 | FD_ZERO (&r); | |
384 | FD_ZERO (&w); | |
385 | t0.tv_sec = t0.tv_usec = 0; | |
386 | ||
387 | if (io -> readfd && io -> inner && | |
388 | (desc = (*(io -> readfd)) (io -> inner)) >= 0) { | |
389 | FD_SET (desc, &r); | |
cfb3f45d TL |
390 | count = select (desc + 1, &r, &w, &x, &t0); |
391 | bogon: | |
392 | if (count < 0) { | |
393 | log_error ("Bad descriptor %d.", desc); | |
394 | for (obj = (omapi_object_t *)io; | |
395 | obj -> outer; | |
396 | obj = obj -> outer) | |
397 | ; | |
645eab7b TL |
398 | for (; obj; obj = obj -> inner) { |
399 | omapi_value_t *ov; | |
400 | int len; | |
401 | const char *s; | |
402 | ov = (omapi_value_t *)0; | |
403 | omapi_get_value_str (obj, | |
404 | (omapi_object_t *)0, | |
405 | "name", &ov); | |
406 | if (ov && ov -> value && | |
407 | (ov -> value -> type == | |
408 | omapi_datatype_string)) { | |
409 | s = (char *) | |
410 | ov -> value -> u.buffer.value; | |
411 | len = ov -> value -> u.buffer.len; | |
412 | } else { | |
413 | s = ""; | |
414 | len = 0; | |
415 | } | |
416 | log_error ("Object %lx %s%s%.*s", | |
417 | (unsigned long)obj, | |
418 | obj -> type -> name, | |
419 | len ? " " : "", | |
420 | len, s); | |
421 | if (len) | |
422 | omapi_value_dereference (&ov, MDL); | |
423 | } | |
98311e4b | 424 | (*(io -> reaper)) (io -> inner); |
9bf59e83 TL |
425 | if (prev) { |
426 | omapi_io_dereference (&prev -> next, MDL); | |
427 | if (io -> next) | |
428 | omapi_io_reference (&prev -> next, | |
429 | io -> next, MDL); | |
430 | } else { | |
431 | omapi_io_dereference | |
432 | (&omapi_io_states.next, MDL); | |
433 | if (io -> next) | |
434 | omapi_io_reference | |
435 | (&omapi_io_states.next, | |
436 | io -> next, MDL); | |
437 | } | |
438 | omapi_io_dereference (&io, MDL); | |
cfb3f45d TL |
439 | goto again; |
440 | } | |
441 | } | |
442 | ||
443 | FD_ZERO (&r); | |
444 | FD_ZERO (&w); | |
445 | t0.tv_sec = t0.tv_usec = 0; | |
446 | ||
447 | /* Same deal for write fdets. */ | |
448 | if (io -> writefd && io -> inner && | |
449 | (desc = (*(io -> writefd)) (io -> inner)) >= 0) { | |
450 | FD_SET (desc, &w); | |
cfb3f45d TL |
451 | count = select (desc + 1, &r, &w, &x, &t0); |
452 | if (count < 0) | |
453 | goto bogon; | |
454 | } | |
9bf59e83 TL |
455 | if (prev) |
456 | omapi_io_dereference (&prev, MDL); | |
457 | omapi_io_reference (&prev, io, MDL); | |
458 | omapi_io_dereference (&io, MDL); | |
459 | if (prev -> next) | |
460 | omapi_io_reference (&io, prev -> next, MDL); | |
cfb3f45d | 461 | } |
9bf59e83 TL |
462 | if (prev) |
463 | omapi_io_dereference (&prev, MDL); | |
464 | ||
cfb3f45d | 465 | } |
61b844bf TL |
466 | |
467 | for (io = omapi_io_states.next; io; io = io -> next) { | |
d8c46740 TL |
468 | if (!io -> inner) |
469 | continue; | |
b6237fb2 | 470 | omapi_object_reference (&tmp, io -> inner, MDL); |
61b844bf TL |
471 | /* Check for a read descriptor, and if there is one, |
472 | see if we got input on that socket. */ | |
473 | if (io -> readfd && | |
b6237fb2 | 474 | (desc = (*(io -> readfd)) (tmp)) >= 0) { |
61b844bf | 475 | if (FD_ISSET (desc, &r)) |
98311e4b | 476 | ((*(io -> reader)) (tmp)); |
61b844bf TL |
477 | } |
478 | ||
479 | /* Same deal for write descriptors. */ | |
480 | if (io -> writefd && | |
b6237fb2 | 481 | (desc = (*(io -> writefd)) (tmp)) >= 0) |
61b844bf TL |
482 | { |
483 | if (FD_ISSET (desc, &w)) | |
98311e4b | 484 | ((*(io -> writer)) (tmp)); |
61b844bf | 485 | } |
b6237fb2 | 486 | omapi_object_dereference (&tmp, MDL); |
61b844bf TL |
487 | } |
488 | ||
489 | /* Now check for I/O handles that are no longer valid, | |
490 | and remove them from the list. */ | |
4619c0a2 DH |
491 | prev = NULL; |
492 | io = NULL; | |
493 | if (omapi_io_states.next != NULL) { | |
494 | omapi_io_reference(&io, omapi_io_states.next, MDL); | |
495 | } | |
496 | while (io != NULL) { | |
497 | if ((io->inner == NULL) || | |
498 | ((io->reaper != NULL) && | |
499 | ((io->reaper)(io->inner) != ISC_R_SUCCESS))) | |
500 | { | |
501 | ||
502 | omapi_io_object_t *tmp = NULL; | |
503 | /* Save a reference to the next | |
504 | pointer, if there is one. */ | |
505 | if (io->next != NULL) { | |
506 | omapi_io_reference(&tmp, io->next, MDL); | |
507 | omapi_io_dereference(&io->next, MDL); | |
61b844bf | 508 | } |
4619c0a2 DH |
509 | if (prev != NULL) { |
510 | omapi_io_dereference(&prev->next, MDL); | |
511 | if (tmp != NULL) | |
512 | omapi_io_reference(&prev->next, | |
513 | tmp, MDL); | |
514 | } else { | |
515 | omapi_io_dereference(&omapi_io_states.next, | |
516 | MDL); | |
517 | if (tmp != NULL) | |
518 | omapi_io_reference | |
519 | (&omapi_io_states.next, | |
520 | tmp, MDL); | |
521 | else | |
522 | omapi_signal_in( | |
523 | (omapi_object_t *) | |
524 | &omapi_io_states, | |
525 | "ready"); | |
526 | } | |
527 | if (tmp != NULL) | |
528 | omapi_io_dereference(&tmp, MDL); | |
529 | ||
530 | } else { | |
531 | ||
532 | if (prev != NULL) { | |
533 | omapi_io_dereference(&prev, MDL); | |
534 | } | |
535 | omapi_io_reference(&prev, io, MDL); | |
536 | ||
61b844bf | 537 | } |
4619c0a2 DH |
538 | |
539 | /* | |
540 | * Equivalent to: | |
541 | * io = io->next | |
542 | * But using our reference counting voodoo. | |
543 | */ | |
544 | next = NULL; | |
545 | if (io->next != NULL) { | |
546 | omapi_io_reference(&next, io->next, MDL); | |
547 | } | |
548 | omapi_io_dereference(&io, MDL); | |
549 | if (next != NULL) { | |
550 | omapi_io_reference(&io, next, MDL); | |
551 | omapi_io_dereference(&next, MDL); | |
552 | } | |
553 | } | |
554 | if (prev != NULL) { | |
555 | omapi_io_dereference(&prev, MDL); | |
61b844bf TL |
556 | } |
557 | ||
558 | return ISC_R_SUCCESS; | |
559 | } | |
560 | ||
561 | isc_result_t omapi_io_set_value (omapi_object_t *h, | |
562 | omapi_object_t *id, | |
563 | omapi_data_string_t *name, | |
564 | omapi_typed_data_t *value) | |
565 | { | |
566 | if (h -> type != omapi_type_io_object) | |
567 | return ISC_R_INVALIDARG; | |
568 | ||
569 | if (h -> inner && h -> inner -> type -> set_value) | |
570 | return (*(h -> inner -> type -> set_value)) | |
571 | (h -> inner, id, name, value); | |
572 | return ISC_R_NOTFOUND; | |
573 | } | |
574 | ||
575 | isc_result_t omapi_io_get_value (omapi_object_t *h, | |
576 | omapi_object_t *id, | |
577 | omapi_data_string_t *name, | |
578 | omapi_value_t **value) | |
579 | { | |
580 | if (h -> type != omapi_type_io_object) | |
581 | return ISC_R_INVALIDARG; | |
582 | ||
583 | if (h -> inner && h -> inner -> type -> get_value) | |
584 | return (*(h -> inner -> type -> get_value)) | |
585 | (h -> inner, id, name, value); | |
586 | return ISC_R_NOTFOUND; | |
587 | } | |
588 | ||
98311e4b DH |
589 | /* omapi_io_destroy (object, MDL); |
590 | * | |
20ae1aff | 591 | * Find the requested IO [object] and remove it from the list of io |
98311e4b DH |
592 | * states, causing the cleanup functions to destroy it. Note that we must |
593 | * hold a reference on the object while moving its ->next reference and | |
594 | * removing the reference in the chain to the target object...otherwise it | |
595 | * may be cleaned up from under us. | |
596 | */ | |
4bd8800e | 597 | isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line) |
61b844bf | 598 | { |
98311e4b | 599 | omapi_io_object_t *obj = NULL, *p, *last = NULL, **holder; |
bdcaf7b9 | 600 | |
61b844bf TL |
601 | if (h -> type != omapi_type_io_object) |
602 | return ISC_R_INVALIDARG; | |
bdcaf7b9 | 603 | |
b6237fb2 TL |
604 | /* remove from the list of I/O states */ |
605 | for (p = omapi_io_states.next; p; p = p -> next) { | |
98311e4b DH |
606 | if (p == (omapi_io_object_t *)h) { |
607 | omapi_io_reference (&obj, p, MDL); | |
608 | ||
609 | if (last) | |
610 | holder = &last -> next; | |
611 | else | |
612 | holder = &omapi_io_states.next; | |
613 | ||
614 | omapi_io_dereference (holder, MDL); | |
615 | ||
616 | if (obj -> next) { | |
617 | omapi_io_reference (holder, obj -> next, MDL); | |
618 | omapi_io_dereference (&obj -> next, MDL); | |
619 | } | |
620 | ||
621 | return omapi_io_dereference (&obj, MDL); | |
bdcaf7b9 | 622 | } |
b6237fb2 | 623 | last = p; |
bdcaf7b9 | 624 | } |
98311e4b DH |
625 | |
626 | return ISC_R_NOTFOUND; | |
61b844bf TL |
627 | } |
628 | ||
629 | isc_result_t omapi_io_signal_handler (omapi_object_t *h, | |
b1b7b521 | 630 | const char *name, va_list ap) |
61b844bf TL |
631 | { |
632 | if (h -> type != omapi_type_io_object) | |
633 | return ISC_R_INVALIDARG; | |
634 | ||
635 | if (h -> inner && h -> inner -> type -> signal_handler) | |
636 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
637 | name, ap); | |
638 | return ISC_R_NOTFOUND; | |
639 | } | |
640 | ||
641 | isc_result_t omapi_io_stuff_values (omapi_object_t *c, | |
642 | omapi_object_t *id, | |
643 | omapi_object_t *i) | |
644 | { | |
645 | if (i -> type != omapi_type_io_object) | |
646 | return ISC_R_INVALIDARG; | |
647 | ||
648 | if (i -> inner && i -> inner -> type -> stuff_values) | |
649 | return (*(i -> inner -> type -> stuff_values)) (c, id, | |
650 | i -> inner); | |
651 | return ISC_R_SUCCESS; | |
652 | } | |
653 | ||
654 | isc_result_t omapi_waiter_signal_handler (omapi_object_t *h, | |
b1b7b521 | 655 | const char *name, va_list ap) |
61b844bf TL |
656 | { |
657 | omapi_waiter_object_t *waiter; | |
658 | ||
659 | if (h -> type != omapi_type_waiter) | |
660 | return ISC_R_INVALIDARG; | |
661 | ||
662 | if (!strcmp (name, "ready")) { | |
663 | waiter = (omapi_waiter_object_t *)h; | |
664 | waiter -> ready = 1; | |
49146f3c DN |
665 | waiter -> waitstatus = ISC_R_SUCCESS; |
666 | return ISC_R_SUCCESS; | |
667 | } | |
668 | ||
669 | if (!strcmp (name, "status")) { | |
670 | waiter = (omapi_waiter_object_t *)h; | |
671 | waiter -> ready = 1; | |
672 | waiter -> waitstatus = va_arg (ap, isc_result_t); | |
61b844bf TL |
673 | return ISC_R_SUCCESS; |
674 | } | |
675 | ||
d758ad8c TL |
676 | if (!strcmp (name, "disconnect")) { |
677 | waiter = (omapi_waiter_object_t *)h; | |
678 | waiter -> ready = 1; | |
679 | waiter -> waitstatus = ISC_R_CONNRESET; | |
680 | return ISC_R_SUCCESS; | |
681 | } | |
682 | ||
61b844bf TL |
683 | if (h -> inner && h -> inner -> type -> signal_handler) |
684 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
685 | name, ap); | |
686 | return ISC_R_NOTFOUND; | |
687 | } | |
688 | ||
d758ad8c TL |
689 | isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *, |
690 | void *), | |
691 | void *p) | |
692 | { | |
693 | omapi_io_object_t *io; | |
694 | isc_result_t status; | |
695 | ||
696 | for (io = omapi_io_states.next; io; io = io -> next) { | |
697 | if (io -> inner) { | |
698 | status = (*func) (io -> inner, p); | |
699 | if (status != ISC_R_SUCCESS) | |
700 | return status; | |
701 | } | |
702 | } | |
703 | return ISC_R_SUCCESS; | |
704 | } |