6 * Copyright (c) 1996-2000 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:
13 * http://www.isc.org/isc-license-1.0.html.
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.
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
23 #include <omapip/omapip_p.h>
25 static omapi_io_object_t omapi_io_states
;
28 /* Register an I/O handle so that we can do asynchronous I/O on it. */
30 isc_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
)
35 isc_result_t (*writer
)
37 isc_result_t (*reaper
)
41 omapi_io_object_t
*obj
, *p
;
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
;
53 obj
= dmalloc (sizeof *obj
, MDL
);
55 return ISC_R_NOMEMORY
;
56 memset (obj
, 0, sizeof *obj
);
58 rc_register_mdl (&obj
, obj
, obj
-> refcnt
);
59 obj
-> type
= omapi_type_io_object
;
61 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
62 if (status
!= ISC_R_SUCCESS
) {
63 omapi_object_dereference ((omapi_object_t
**)&obj
, MDL
);
67 status
= omapi_object_reference (&h
-> outer
,
68 (omapi_object_t
*)obj
, MDL
);
69 if (status
!= ISC_R_SUCCESS
) {
70 omapi_object_dereference ((omapi_object_t
**)&obj
, MDL
);
74 /* Find the last I/O state, if there are any. */
75 for (p
= omapi_io_states
.next
;
76 p
&& p
-> next
; p
= p
-> next
)
81 omapi_io_states
.next
= obj
;
83 obj
-> readfd
= readfd
;
84 obj
-> writefd
= writefd
;
85 obj
-> reader
= reader
;
86 obj
-> writer
= writer
;
87 obj
-> reaper
= reaper
;
91 isc_result_t
omapi_dispatch (struct timeval
*t
)
93 return omapi_wait_for_completion ((omapi_object_t
*)&omapi_io_states
,
97 isc_result_t
omapi_wait_for_completion (omapi_object_t
*object
,
101 omapi_waiter_object_t
*waiter
;
102 omapi_object_t
*inner
;
105 waiter
= dmalloc (sizeof *waiter
, MDL
);
107 return ISC_R_NOMEMORY
;
108 memset (waiter
, 0, sizeof *waiter
);
109 waiter
-> refcnt
= 1;
110 rc_register_mdl (&waiter
, waiter
, waiter
-> refcnt
);
111 waiter
-> type
= omapi_type_waiter
;
113 /* Paste the waiter object onto the inner object we're
115 for (inner
= object
; inner
-> inner
; inner
= inner
-> inner
)
118 status
= omapi_object_reference (&waiter
-> outer
, inner
, MDL
);
119 if (status
!= ISC_R_SUCCESS
) {
120 omapi_object_dereference ((omapi_object_t
**)&waiter
,
125 status
= omapi_object_reference (&inner
-> inner
,
126 (omapi_object_t
*)waiter
,
128 if (status
!= ISC_R_SUCCESS
) {
129 omapi_object_dereference ((omapi_object_t
**)&waiter
,
134 waiter
= (omapi_waiter_object_t
*)0;
137 status
= omapi_one_dispatch ((omapi_object_t
*)waiter
, t
);
138 if (status
!= ISC_R_SUCCESS
)
140 } while (!waiter
|| !waiter
-> ready
);
142 if (waiter
-> outer
) {
143 if (waiter
-> outer
-> inner
) {
144 omapi_object_dereference (&waiter
-> outer
-> inner
,
147 omapi_object_reference
148 (&waiter
-> outer
-> inner
,
149 waiter
-> inner
, MDL
);
151 omapi_object_dereference (&waiter
-> outer
, MDL
);
154 omapi_object_dereference (&waiter
-> inner
, MDL
);
156 omapi_object_dereference ((omapi_object_t
**)&waiter
, MDL
);
157 return ISC_R_SUCCESS
;
160 isc_result_t
omapi_one_dispatch (omapi_object_t
*wo
,
167 struct timeval now
, to
;
168 omapi_io_object_t
*io
, *prev
;
170 omapi_waiter_object_t
*waiter
;
172 if (!wo
|| wo
-> type
!= omapi_type_waiter
)
173 waiter
= (omapi_waiter_object_t
*)0;
175 waiter
= (omapi_waiter_object_t
*)wo
;
179 /* First, see if the timeout has expired, and if so return. */
181 gettimeofday (&now
, (struct timezone
*)0);
182 cur_time
= now
.tv_sec
;
183 if (now
.tv_sec
> t
-> tv_sec
||
184 (now
.tv_sec
== t
-> tv_sec
&& now
.tv_usec
>= t
-> tv_usec
))
185 return ISC_R_TIMEDOUT
;
187 /* We didn't time out, so figure out how long until
189 to
.tv_sec
= t
-> tv_sec
- now
.tv_sec
;
190 to
.tv_usec
= t
-> tv_usec
- now
.tv_usec
;
191 if (to
.tv_usec
< 0) {
192 to
.tv_usec
+= 1000000;
197 /* If the object we're waiting on has reached completion,
199 if (waiter
&& waiter
-> ready
)
200 return ISC_R_SUCCESS
;
202 /* If we have no I/O state, we can't proceed. */
203 if (!(io
= omapi_io_states
.next
))
206 /* Set up the read and write masks. */
210 for (; io
; io
= io
-> next
) {
211 /* Check for a read socket. If we shouldn't be
212 trying to read for this I/O object, either there
213 won't be a readfd function, or it'll return -1. */
215 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
221 /* Same deal for write fdets. */
223 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
230 /* Wait for a packet or a timeout... XXX */
231 count
= select (max
+ 1, &r
, &w
, &x
, t
? &to
: (struct timeval
*)0);
233 /* Get the current time... */
234 gettimeofday (&now
, (struct timezone
*)0);
235 cur_time
= now
.tv_sec
;
237 /* Not likely to be transitory... */
239 return ISC_R_UNEXPECTED
;
241 for (io
= omapi_io_states
.next
; io
; io
= io
-> next
) {
242 /* Check for a read descriptor, and if there is one,
243 see if we got input on that socket. */
245 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
246 if (FD_ISSET (desc
, &r
))
247 status
= ((*(io
-> reader
)) (io
-> inner
));
248 /* XXX what to do with status? */
251 /* Same deal for write descriptors. */
253 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0)
255 if (FD_ISSET (desc
, &w
))
256 status
= ((*(io
-> writer
)) (io
-> inner
));
257 /* XXX what to do with status? */
261 /* Now check for I/O handles that are no longer valid,
262 and remove them from the list. */
263 prev
= (omapi_io_object_t
*)0;
264 for (io
= omapi_io_states
.next
; io
; io
= io
-> next
) {
266 status
= (*(io
-> reaper
)) (io
-> inner
);
267 if (status
!= ISC_R_SUCCESS
) {
268 omapi_io_object_t
*tmp
=
269 (omapi_io_object_t
*)0;
270 /* Save a reference to the next
271 pointer, if there is one. */
273 omapi_object_reference
274 ((omapi_object_t
**)&tmp
,
275 (omapi_object_t
*)io
-> next
,
278 omapi_object_dereference
279 (((omapi_object_t
**)
280 &prev
-> next
), MDL
);
282 omapi_object_reference
283 (((omapi_object_t
**)
285 (omapi_object_t
*)tmp
,
288 omapi_object_dereference
289 (((omapi_object_t
**)
290 &omapi_io_states
.next
),
293 omapi_object_reference
294 (((omapi_object_t
**)
295 &omapi_io_states
.next
),
296 (omapi_object_t
*)tmp
,
305 omapi_object_dereference
306 ((omapi_object_t
**)&tmp
, MDL
);
312 return ISC_R_SUCCESS
;
315 isc_result_t
omapi_io_set_value (omapi_object_t
*h
,
317 omapi_data_string_t
*name
,
318 omapi_typed_data_t
*value
)
320 if (h
-> type
!= omapi_type_io_object
)
321 return ISC_R_INVALIDARG
;
323 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
324 return (*(h
-> inner
-> type
-> set_value
))
325 (h
-> inner
, id
, name
, value
);
326 return ISC_R_NOTFOUND
;
329 isc_result_t
omapi_io_get_value (omapi_object_t
*h
,
331 omapi_data_string_t
*name
,
332 omapi_value_t
**value
)
334 if (h
-> type
!= omapi_type_io_object
)
335 return ISC_R_INVALIDARG
;
337 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
338 return (*(h
-> inner
-> type
-> get_value
))
339 (h
-> inner
, id
, name
, value
);
340 return ISC_R_NOTFOUND
;
343 isc_result_t
omapi_io_destroy (omapi_object_t
*h
, const char *file
, int line
)
345 omapi_io_object_t
*obj
, *p
, *last
;
347 if (h
-> type
!= omapi_type_io_object
)
348 return ISC_R_INVALIDARG
;
350 obj
= (omapi_io_object_t
*)h
;
352 /* only ios for interface objects? */
353 if (strcmp (obj
-> inner
-> type
->name
, "interface") == 0) {
354 /* remove from the list of I/O states */
355 for (p
= omapi_io_states
.next
; p
; p
= p
-> next
) {
357 last
-> next
= p
-> next
;
364 * omapi_object_dereference ((omapi_object_t **)&obj, MDL);
368 return ISC_R_SUCCESS
;
371 isc_result_t
omapi_io_signal_handler (omapi_object_t
*h
,
372 const char *name
, va_list ap
)
374 if (h
-> type
!= omapi_type_io_object
)
375 return ISC_R_INVALIDARG
;
377 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
378 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
380 return ISC_R_NOTFOUND
;
383 isc_result_t
omapi_io_stuff_values (omapi_object_t
*c
,
387 if (i
-> type
!= omapi_type_io_object
)
388 return ISC_R_INVALIDARG
;
390 if (i
-> inner
&& i
-> inner
-> type
-> stuff_values
)
391 return (*(i
-> inner
-> type
-> stuff_values
)) (c
, id
,
393 return ISC_R_SUCCESS
;
396 isc_result_t
omapi_waiter_signal_handler (omapi_object_t
*h
,
397 const char *name
, va_list ap
)
399 omapi_waiter_object_t
*waiter
;
401 if (h
-> type
!= omapi_type_waiter
)
402 return ISC_R_INVALIDARG
;
404 if (!strcmp (name
, "ready")) {
405 waiter
= (omapi_waiter_object_t
*)h
;
407 return ISC_R_SUCCESS
;
410 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
411 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
413 return ISC_R_NOTFOUND
;