6 * Copyright (c) 2004,2007-2009,2013-2014 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
31 #include <omapip/omapip_p.h>
34 static omapi_io_object_t omapi_io_states
;
35 struct timeval cur_tv
;
37 struct eventqueue
*rw_queue_empty
;
39 OMAPI_OBJECT_ALLOC (omapi_io
,
40 omapi_io_object_t
, omapi_type_io_object
)
41 OMAPI_OBJECT_ALLOC (omapi_waiter
,
42 omapi_waiter_object_t
, omapi_type_waiter
)
45 register_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
47 struct eventqueue
*t
, *q
;
49 /* traverse to end of list */
51 for (q
= *queue
; q
; q
= q
->next
) {
52 if (q
->handler
== handler
)
53 return; /* handler already registered */
57 q
= ((struct eventqueue
*)dmalloc(sizeof(struct eventqueue
), MDL
));
59 log_fatal("register_eventhandler: no memory!");
60 memset(q
, 0, sizeof *q
);
70 unregister_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
72 struct eventqueue
*t
, *q
;
74 /* traverse to end of list */
76 for (q
= *queue
; q
; q
= q
->next
) {
77 if (q
->handler
== handler
) {
82 dfree(q
, MDL
); /* Don't access q after this!*/
91 trigger_event(struct eventqueue
**queue
)
95 for (q
=*queue
; q
; q
=q
->next
) {
102 * Callback routine to connect the omapi I/O object and socket with
103 * the isc socket code. The isc socket code will call this routine
104 * which will then call the correct local routine to process the bytes.
106 * Currently we are always willing to read more data, this should be modified
107 * so that on connections we don't read more if we already have enough.
109 * If we have more bytes to write we ask the library to call us when
110 * we can write more. If we indicate we don't have more to write we need
111 * to poke the library via isc_socket_fdwatchpoke.
115 * sockdelete indicates if we are deleting the socket or leaving it in place
116 * 1 is delete, 0 is leave in place
120 omapi_iscsock_cb(isc_task_t
*task
,
121 isc_socket_t
*socket
,
125 omapi_io_object_t
*obj
;
128 /* Get the current time... */
129 gettimeofday (&cur_tv
, (struct timezone
*)0);
131 /* isc socket stuff */
134 * walk through the io states list, if our object is on there
135 * service it. if not ignore it.
137 for (obj
= omapi_io_states
.next
;
138 (obj
!= NULL
) && (obj
->next
!= NULL
);
147 /* Not much to be done if we have the wrong type of object. */
148 if (((omapi_object_t
*)cbarg
) -> type
!= omapi_type_io_object
) {
149 log_fatal ("Incorrect object type, must be of type io_object");
151 obj
= (omapi_io_object_t
*)cbarg
;
154 * If the object is marked as closed don't try and process
155 * anything just indicate that we don't want any more.
157 * This should be a temporary fix until we arrange to properly
160 if (obj
->closed
== ISC_TRUE
) {
165 if ((flags
== ISC_SOCKFDWATCH_READ
) &&
166 (obj
->reader
!= NULL
) &&
167 (obj
->inner
!= NULL
)) {
168 status
= obj
->reader(obj
->inner
);
170 * If we are shutting down (basically tried to
171 * read and got no bytes) we don't need to try
174 if (status
== ISC_R_SHUTTINGDOWN
)
176 /* Otherwise We always ask for more when reading */
178 } else if ((flags
== ISC_SOCKFDWATCH_WRITE
) &&
179 (obj
->writer
!= NULL
) &&
180 (obj
->inner
!= NULL
)) {
181 status
= obj
->writer(obj
->inner
);
182 /* If the writer has more to write they should return
183 * ISC_R_INPROGRESS */
184 if (status
== ISC_R_INPROGRESS
) {
190 * We get here if we either had an error (inconsistent
191 * structures etc) or no more to write, tell the socket
192 * lib we don't have more to do right now.
197 /* Register an I/O handle so that we can do asynchronous I/O on it. */
199 isc_result_t
omapi_register_io_object (omapi_object_t
*h
,
200 int (*readfd
) (omapi_object_t
*),
201 int (*writefd
) (omapi_object_t
*),
202 isc_result_t (*reader
)
204 isc_result_t (*writer
)
206 isc_result_t (*reaper
)
210 omapi_io_object_t
*obj
, *p
;
211 int fd_flags
= 0, fd
= 0;
213 /* omapi_io_states is a static object. If its reference count
214 is zero, this is the first I/O handle to be registered, so
215 we need to initialize it. Because there is no inner or outer
216 pointer on this object, and we're setting its refcnt to 1, it
217 will never be freed. */
218 if (!omapi_io_states
.refcnt
) {
219 omapi_io_states
.refcnt
= 1;
220 omapi_io_states
.type
= omapi_type_io_object
;
223 obj
= (omapi_io_object_t
*)0;
224 status
= omapi_io_allocate (&obj
, MDL
);
225 if (status
!= ISC_R_SUCCESS
)
227 obj
->closed
= ISC_FALSE
; /* mark as open */
229 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
230 if (status
!= ISC_R_SUCCESS
) {
231 omapi_io_dereference (&obj
, MDL
);
235 status
= omapi_object_reference (&h
-> outer
,
236 (omapi_object_t
*)obj
, MDL
);
237 if (status
!= ISC_R_SUCCESS
) {
238 omapi_io_dereference (&obj
, MDL
);
243 * Attach the I/O object to the isc socket library via the
244 * fdwatch function. This allows the socket library to watch
245 * over a socket that we built. If there are both a read and
246 * a write socket we asssume they are the same socket.
250 fd_flags
|= ISC_SOCKFDWATCH_READ
;
255 fd_flags
|= ISC_SOCKFDWATCH_WRITE
;
260 status
= isc_socket_fdwatchcreate(dhcp_gbl_ctx
.socketmgr
,
266 if (status
!= ISC_R_SUCCESS
) {
267 log_error("Unable to register fd with library %s",
268 isc_result_totext(status
));
271 /* is this the cleanup we need? */
272 omapi_object_dereference(&h
->outer
, MDL
);
273 omapi_io_dereference (&obj
, MDL
);
279 /* Find the last I/O state, if there are any. */
280 for (p
= omapi_io_states
.next
;
281 p
&& p
-> next
; p
= p
-> next
)
284 omapi_io_reference (&p
-> next
, obj
, MDL
);
286 omapi_io_reference (&omapi_io_states
.next
, obj
, MDL
);
288 obj
-> readfd
= readfd
;
289 obj
-> writefd
= writefd
;
290 obj
-> reader
= reader
;
291 obj
-> writer
= writer
;
292 obj
-> reaper
= reaper
;
294 omapi_io_dereference(&obj
, MDL
);
295 return ISC_R_SUCCESS
;
299 * ReRegister an I/O handle so that we can do asynchronous I/O on it.
300 * If the handle doesn't exist we call the register routine to build it.
301 * If it does exist we change the functions associated with it, and
302 * repoke the fd code to make it happy. Neither the objects nor the
303 * fd are allowed to have changed.
306 isc_result_t
omapi_reregister_io_object (omapi_object_t
*h
,
307 int (*readfd
) (omapi_object_t
*),
308 int (*writefd
) (omapi_object_t
*),
309 isc_result_t (*reader
)
311 isc_result_t (*writer
)
313 isc_result_t (*reaper
)
316 omapi_io_object_t
*obj
;
319 if ((!h
-> outer
) || (h
-> outer
-> type
!= omapi_type_io_object
)) {
321 * If we don't have an object or if the type isn't what
322 * we expect do the normal registration (which will overwrite
323 * an incorrect type, that's what we did historically, may
324 * want to change that)
326 return (omapi_register_io_object (h
, readfd
, writefd
,
327 reader
, writer
, reaper
));
330 /* We have an io object of the correct type, try to update it */
332 /* Should we validate that the fd matches the previous one?
333 * It's suppossed to, that's a requirement, don't bother yet */
335 obj
= (omapi_io_object_t
*)h
->outer
;
337 obj
->readfd
= readfd
;
338 obj
->writefd
= writefd
;
339 obj
->reader
= reader
;
340 obj
->writer
= writer
;
341 obj
->reaper
= reaper
;
344 fd_flags
|= ISC_SOCKFDWATCH_READ
;
348 fd_flags
|= ISC_SOCKFDWATCH_WRITE
;
351 isc_socket_fdwatchpoke(obj
->fd
, fd_flags
);
353 return (ISC_R_SUCCESS
);
356 isc_result_t
omapi_unregister_io_object (omapi_object_t
*h
)
358 omapi_io_object_t
*obj
, *ph
;
360 omapi_io_object_t
*p
, *last
;
363 if (!h
-> outer
|| h
-> outer
-> type
!= omapi_type_io_object
)
364 return DHCP_R_INVALIDARG
;
365 obj
= (omapi_io_object_t
*)h
-> outer
;
366 ph
= (omapi_io_object_t
*)0;
367 omapi_io_reference (&ph
, obj
, MDL
);
371 * For now we leave this out. We can't clean up the isc socket
372 * structure cleanly yet so we need to leave the io object in place.
373 * By leaving it on the io states list we avoid it being freed.
374 * We also mark it as closed to avoid using it.
377 /* remove from the list of I/O states */
378 last
= &omapi_io_states
;
379 for (p
= omapi_io_states
.next
; p
; p
= p
-> next
) {
381 omapi_io_dereference (&last
-> next
, MDL
);
382 omapi_io_reference (&last
-> next
, p
-> next
, MDL
);
388 omapi_io_dereference (&obj
-> next
, MDL
);
392 if (obj
-> outer
-> inner
== (omapi_object_t
*)obj
)
393 omapi_object_dereference (&obj
-> outer
-> inner
,
395 omapi_object_dereference (&obj
-> outer
, MDL
);
397 omapi_object_dereference (&obj
-> inner
, MDL
);
398 omapi_object_dereference (&h
-> outer
, MDL
);
401 /* remove isc socket associations */
402 if (obj
->fd
!= NULL
) {
403 isc_socket_cancel(obj
->fd
, dhcp_gbl_ctx
.task
,
405 isc_socket_detach(&obj
->fd
);
408 obj
->closed
= ISC_TRUE
;
411 omapi_io_dereference (&ph
, MDL
);
412 return ISC_R_SUCCESS
;
415 isc_result_t
omapi_dispatch (struct timeval
*t
)
417 return omapi_wait_for_completion ((omapi_object_t
*)&omapi_io_states
,
421 isc_result_t
omapi_wait_for_completion (omapi_object_t
*object
,
425 omapi_waiter_object_t
*waiter
;
426 omapi_object_t
*inner
;
429 waiter
= (omapi_waiter_object_t
*)0;
430 status
= omapi_waiter_allocate (&waiter
, MDL
);
431 if (status
!= ISC_R_SUCCESS
)
434 /* Paste the waiter object onto the inner object we're
436 for (inner
= object
; inner
-> inner
; inner
= inner
-> inner
)
439 status
= omapi_object_reference (&waiter
-> outer
, inner
, MDL
);
440 if (status
!= ISC_R_SUCCESS
) {
441 omapi_waiter_dereference (&waiter
, MDL
);
445 status
= omapi_object_reference (&inner
-> inner
,
446 (omapi_object_t
*)waiter
,
448 if (status
!= ISC_R_SUCCESS
) {
449 omapi_waiter_dereference (&waiter
, MDL
);
453 waiter
= (omapi_waiter_object_t
*)0;
456 status
= omapi_one_dispatch ((omapi_object_t
*)waiter
, t
);
457 if (status
!= ISC_R_SUCCESS
)
459 } while (!waiter
|| !waiter
-> ready
);
461 if (waiter
-> outer
) {
462 if (waiter
-> outer
-> inner
) {
463 omapi_object_dereference (&waiter
-> outer
-> inner
,
466 omapi_object_reference
467 (&waiter
-> outer
-> inner
,
468 waiter
-> inner
, MDL
);
470 omapi_object_dereference (&waiter
-> outer
, MDL
);
473 omapi_object_dereference (&waiter
-> inner
, MDL
);
475 status
= waiter
-> waitstatus
;
476 omapi_waiter_dereference (&waiter
, MDL
);
480 isc_result_t
omapi_one_dispatch (omapi_object_t
*wo
,
483 fd_set r
, w
, x
, rr
, ww
, xx
;
487 struct timeval now
, to
;
488 omapi_io_object_t
*io
, *prev
, *next
;
489 omapi_waiter_object_t
*waiter
;
490 omapi_object_t
*tmp
= (omapi_object_t
*)0;
492 if (!wo
|| wo
-> type
!= omapi_type_waiter
)
493 waiter
= (omapi_waiter_object_t
*)0;
495 waiter
= (omapi_waiter_object_t
*)wo
;
499 /* First, see if the timeout has expired, and if so return. */
501 gettimeofday (&now
, (struct timezone
*)0);
502 cur_tv
.tv_sec
= now
.tv_sec
;
503 cur_tv
.tv_usec
= now
.tv_usec
;
504 if (now
.tv_sec
> t
-> tv_sec
||
505 (now
.tv_sec
== t
-> tv_sec
&& now
.tv_usec
>= t
-> tv_usec
))
506 return ISC_R_TIMEDOUT
;
508 /* We didn't time out, so figure out how long until
510 to
.tv_sec
= t
-> tv_sec
- now
.tv_sec
;
511 to
.tv_usec
= t
-> tv_usec
- now
.tv_usec
;
512 if (to
.tv_usec
< 0) {
513 to
.tv_usec
+= 1000000;
517 /* It is possible for the timeout to get set larger than
518 the largest time select() is willing to accept.
519 Restricting the timeout to a maximum of one day should
520 work around this. -DPN. (Ref: Bug #416) */
521 if (to
.tv_sec
> (60 * 60 * 24))
522 to
.tv_sec
= 60 * 60 * 24;
525 /* If the object we're waiting on has reached completion,
527 if (waiter
&& waiter
-> ready
)
528 return ISC_R_SUCCESS
;
531 /* If we have no I/O state, we can't proceed. */
532 if (!(io
= omapi_io_states
.next
))
535 /* Set up the read and write masks. */
539 for (; io
; io
= io
-> next
) {
540 /* Check for a read socket. If we shouldn't be
541 trying to read for this I/O object, either there
542 won't be a readfd function, or it'll return -1. */
543 if (io
-> readfd
&& io
-> inner
&&
544 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
550 /* Same deal for write fdets. */
551 if (io
-> writefd
&& io
-> inner
&&
552 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
559 /* poll if all reader are dry */
567 count
= select(max
+ 1, &r
, &w
, &x
, &now
);
570 trigger_event(&rw_queue_empty
);
571 /* Wait for a packet or a timeout... XXX */
575 count
= select(max
+ 1, &r
, &w
, &x
, t
? &to
: NULL
);
578 /* Get the current time... */
579 gettimeofday (&cur_tv
, (struct timezone
*)0);
581 /* We probably have a bad file descriptor. Figure out which one.
582 When we find it, call the reaper function on it, which will
583 maybe make it go away, and then try again. */
586 omapi_io_object_t
*prev
= (omapi_io_object_t
*)0;
587 io
= (omapi_io_object_t
*)0;
588 if (omapi_io_states
.next
)
589 omapi_io_reference (&io
, omapi_io_states
.next
, MDL
);
595 t0
.tv_sec
= t0
.tv_usec
= 0;
597 if (io
-> readfd
&& io
-> inner
&&
598 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
600 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
603 log_error ("Bad descriptor %d.", desc
);
604 for (obj
= (omapi_object_t
*)io
;
608 for (; obj
; obj
= obj
-> inner
) {
612 ov
= (omapi_value_t
*)0;
613 omapi_get_value_str (obj
,
616 if (ov
&& ov
-> value
&&
617 (ov
-> value
-> type
==
618 omapi_datatype_string
)) {
620 ov
-> value
-> u
.buffer
.value
;
621 len
= ov
-> value
-> u
.buffer
.len
;
626 log_error ("Object %lx %s%s%.*s",
632 omapi_value_dereference (&ov
, MDL
);
634 (*(io
-> reaper
)) (io
-> inner
);
636 omapi_io_dereference (&prev
-> next
, MDL
);
638 omapi_io_reference (&prev
-> next
,
642 (&omapi_io_states
.next
, MDL
);
645 (&omapi_io_states
.next
,
648 omapi_io_dereference (&io
, MDL
);
655 t0
.tv_sec
= t0
.tv_usec
= 0;
657 /* Same deal for write fdets. */
658 if (io
-> writefd
&& io
-> inner
&&
659 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
661 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
666 omapi_io_dereference (&prev
, MDL
);
667 omapi_io_reference (&prev
, io
, MDL
);
668 omapi_io_dereference (&io
, MDL
);
670 omapi_io_reference (&io
, prev
-> next
, MDL
);
673 omapi_io_dereference (&prev
, MDL
);
677 for (io
= omapi_io_states
.next
; io
; io
= io
-> next
) {
680 omapi_object_reference (&tmp
, io
-> inner
, MDL
);
681 /* Check for a read descriptor, and if there is one,
682 see if we got input on that socket. */
684 (desc
= (*(io
-> readfd
)) (tmp
)) >= 0) {
685 if (FD_ISSET (desc
, &r
))
686 ((*(io
-> reader
)) (tmp
));
689 /* Same deal for write descriptors. */
691 (desc
= (*(io
-> writefd
)) (tmp
)) >= 0)
693 if (FD_ISSET (desc
, &w
))
694 ((*(io
-> writer
)) (tmp
));
696 omapi_object_dereference (&tmp
, MDL
);
699 /* Now check for I/O handles that are no longer valid,
700 and remove them from the list. */
703 if (omapi_io_states
.next
!= NULL
) {
704 omapi_io_reference(&io
, omapi_io_states
.next
, MDL
);
707 if ((io
->inner
== NULL
) ||
708 ((io
->reaper
!= NULL
) &&
709 ((io
->reaper
)(io
->inner
) != ISC_R_SUCCESS
)))
712 omapi_io_object_t
*tmp
= NULL
;
713 /* Save a reference to the next
714 pointer, if there is one. */
715 if (io
->next
!= NULL
) {
716 omapi_io_reference(&tmp
, io
->next
, MDL
);
717 omapi_io_dereference(&io
->next
, MDL
);
720 omapi_io_dereference(&prev
->next
, MDL
);
722 omapi_io_reference(&prev
->next
,
725 omapi_io_dereference(&omapi_io_states
.next
,
729 (&omapi_io_states
.next
,
738 omapi_io_dereference(&tmp
, MDL
);
743 omapi_io_dereference(&prev
, MDL
);
745 omapi_io_reference(&prev
, io
, MDL
);
751 * But using our reference counting voodoo.
754 if (io
->next
!= NULL
) {
755 omapi_io_reference(&next
, io
->next
, MDL
);
757 omapi_io_dereference(&io
, MDL
);
759 omapi_io_reference(&io
, next
, MDL
);
760 omapi_io_dereference(&next
, MDL
);
764 omapi_io_dereference(&prev
, MDL
);
767 return ISC_R_SUCCESS
;
770 isc_result_t
omapi_io_set_value (omapi_object_t
*h
,
772 omapi_data_string_t
*name
,
773 omapi_typed_data_t
*value
)
775 if (h
-> type
!= omapi_type_io_object
)
776 return DHCP_R_INVALIDARG
;
778 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
779 return (*(h
-> inner
-> type
-> set_value
))
780 (h
-> inner
, id
, name
, value
);
781 return ISC_R_NOTFOUND
;
784 isc_result_t
omapi_io_get_value (omapi_object_t
*h
,
786 omapi_data_string_t
*name
,
787 omapi_value_t
**value
)
789 if (h
-> type
!= omapi_type_io_object
)
790 return DHCP_R_INVALIDARG
;
792 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
793 return (*(h
-> inner
-> type
-> get_value
))
794 (h
-> inner
, id
, name
, value
);
795 return ISC_R_NOTFOUND
;
798 /* omapi_io_destroy (object, MDL);
800 * Find the requested IO [object] and remove it from the list of io
801 * states, causing the cleanup functions to destroy it. Note that we must
802 * hold a reference on the object while moving its ->next reference and
803 * removing the reference in the chain to the target object...otherwise it
804 * may be cleaned up from under us.
806 isc_result_t
omapi_io_destroy (omapi_object_t
*h
, const char *file
, int line
)
808 omapi_io_object_t
*obj
= NULL
, *p
, *last
= NULL
, **holder
;
810 if (h
-> type
!= omapi_type_io_object
)
811 return DHCP_R_INVALIDARG
;
813 /* remove from the list of I/O states */
814 for (p
= omapi_io_states
.next
; p
; p
= p
-> next
) {
815 if (p
== (omapi_io_object_t
*)h
) {
816 omapi_io_reference (&obj
, p
, MDL
);
819 holder
= &last
-> next
;
821 holder
= &omapi_io_states
.next
;
823 omapi_io_dereference (holder
, MDL
);
826 omapi_io_reference (holder
, obj
-> next
, MDL
);
827 omapi_io_dereference (&obj
-> next
, MDL
);
830 return omapi_io_dereference (&obj
, MDL
);
835 return ISC_R_NOTFOUND
;
838 isc_result_t
omapi_io_signal_handler (omapi_object_t
*h
,
839 const char *name
, va_list ap
)
841 if (h
-> type
!= omapi_type_io_object
)
842 return DHCP_R_INVALIDARG
;
844 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
845 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
847 return ISC_R_NOTFOUND
;
850 isc_result_t
omapi_io_stuff_values (omapi_object_t
*c
,
854 if (i
-> type
!= omapi_type_io_object
)
855 return DHCP_R_INVALIDARG
;
857 if (i
-> inner
&& i
-> inner
-> type
-> stuff_values
)
858 return (*(i
-> inner
-> type
-> stuff_values
)) (c
, id
,
860 return ISC_R_SUCCESS
;
863 isc_result_t
omapi_waiter_signal_handler (omapi_object_t
*h
,
864 const char *name
, va_list ap
)
866 omapi_waiter_object_t
*waiter
;
868 if (h
-> type
!= omapi_type_waiter
)
869 return DHCP_R_INVALIDARG
;
871 if (!strcmp (name
, "ready")) {
872 waiter
= (omapi_waiter_object_t
*)h
;
874 waiter
-> waitstatus
= ISC_R_SUCCESS
;
875 return ISC_R_SUCCESS
;
878 if (!strcmp(name
, "status")) {
879 waiter
= (omapi_waiter_object_t
*)h
;
881 waiter
->waitstatus
= va_arg(ap
, isc_result_t
);
882 return ISC_R_SUCCESS
;
885 if (!strcmp (name
, "disconnect")) {
886 waiter
= (omapi_waiter_object_t
*)h
;
888 waiter
-> waitstatus
= DHCP_R_CONNRESET
;
889 return ISC_R_SUCCESS
;
892 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
893 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
895 return ISC_R_NOTFOUND
;
898 /** @brief calls a given function on every object
900 * @param func function to be called
901 * @param p parameter to be passed to each function instance
903 * @return result (ISC_R_SUCCESS if successful, error code otherwise)
905 isc_result_t
omapi_io_state_foreach (isc_result_t (*func
) (omapi_object_t
*,
909 omapi_io_object_t
*io
= NULL
;
911 omapi_io_object_t
*next
= NULL
;
914 * This just calls func on every inner object on the list. It would
915 * be much simpler in general case, but one of the operations could be
916 * release of the objects. Therefore we need to ref count the io and
920 if (omapi_io_states
.next
) {
921 omapi_object_reference((omapi_object_t
**)&io
,
922 (omapi_object_t
*)omapi_io_states
.next
,
927 /* If there's a next object, save it */
929 omapi_object_reference((omapi_object_t
**)&next
,
930 (omapi_object_t
*)io
->next
, MDL
);
933 status
= (*func
) (io
->inner
, p
);
934 if (status
!= ISC_R_SUCCESS
) {
935 /* Something went wrong. Let's stop using io & next pointer
937 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
939 omapi_object_dereference((omapi_object_t
**)&next
, MDL
);
944 /* Update the io pointer and free the next pointer */
945 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
947 omapi_object_reference((omapi_object_t
**)&io
,
948 (omapi_object_t
*)next
,
950 omapi_object_dereference((omapi_object_t
**)&next
, MDL
);
955 * The only way to get here is when next is NULL. There's no need
958 return ISC_R_SUCCESS
;