]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/dispatch.c
Get rid of dns_startup, use lease time instead of constant ttl.
[thirdparty/dhcp.git] / omapip / dispatch.c
CommitLineData
61b844bf
TL
1/* dispatch.c
2
3 I/O dispatcher. */
4
5/*
4bd8800e 6 * Copyright (c) 1996-2000 Internet Software Consortium.
61b844bf
TL
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
6a4c4be8 23#include <omapip/omapip_p.h>
61b844bf
TL
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
4bd8800e 53 obj = dmalloc (sizeof *obj, MDL);
61b844bf
TL
54 if (!obj)
55 return ISC_R_NOMEMORY;
56 memset (obj, 0, sizeof *obj);
61b844bf 57 obj -> refcnt = 1;
37e365b4 58 rc_register_mdl (&obj, obj, obj -> refcnt);
61b844bf
TL
59 obj -> type = omapi_type_io_object;
60
4bd8800e 61 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 62 if (status != ISC_R_SUCCESS) {
4bd8800e 63 omapi_object_dereference ((omapi_object_t **)&obj, MDL);
61b844bf
TL
64 return status;
65 }
66
4bd8800e
TL
67 status = omapi_object_reference (&h -> outer,
68 (omapi_object_t *)obj, MDL);
61b844bf 69 if (status != ISC_R_SUCCESS) {
4bd8800e 70 omapi_object_dereference ((omapi_object_t **)&obj, MDL);
61b844bf
TL
71 return status;
72 }
73
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)
77 ;
78 if (p)
79 p -> next = obj;
80 else
81 omapi_io_states.next = obj;
82
83 obj -> readfd = readfd;
84 obj -> writefd = writefd;
85 obj -> reader = reader;
86 obj -> writer = writer;
87 obj -> reaper = reaper;
88 return ISC_R_SUCCESS;
89}
90
91isc_result_t omapi_dispatch (struct timeval *t)
92{
93 return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
94 t);
95}
96
97isc_result_t omapi_wait_for_completion (omapi_object_t *object,
98 struct timeval *t)
99{
100 isc_result_t status;
101 omapi_waiter_object_t *waiter;
102 omapi_object_t *inner;
103
104 if (object) {
4bd8800e 105 waiter = dmalloc (sizeof *waiter, MDL);
61b844bf
TL
106 if (!waiter)
107 return ISC_R_NOMEMORY;
108 memset (waiter, 0, sizeof *waiter);
109 waiter -> refcnt = 1;
37e365b4 110 rc_register_mdl (&waiter, waiter, waiter -> refcnt);
61b844bf
TL
111 waiter -> type = omapi_type_waiter;
112
113 /* Paste the waiter object onto the inner object we're
114 waiting on. */
115 for (inner = object; inner -> inner; inner = inner -> inner)
116 ;
117
4bd8800e 118 status = omapi_object_reference (&waiter -> outer, inner, MDL);
61b844bf
TL
119 if (status != ISC_R_SUCCESS) {
120 omapi_object_dereference ((omapi_object_t **)&waiter,
4bd8800e 121 MDL);
61b844bf
TL
122 return status;
123 }
124
125 status = omapi_object_reference (&inner -> inner,
126 (omapi_object_t *)waiter,
4bd8800e 127 MDL);
61b844bf
TL
128 if (status != ISC_R_SUCCESS) {
129 omapi_object_dereference ((omapi_object_t **)&waiter,
4bd8800e 130 MDL);
61b844bf
TL
131 return status;
132 }
133 } else
134 waiter = (omapi_waiter_object_t *)0;
135
136 do {
6a4c4be8 137 status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
61b844bf
TL
138 if (status != ISC_R_SUCCESS)
139 return status;
140 } while (!waiter || !waiter -> ready);
141
727ebc3a
TL
142 if (waiter -> outer) {
143 if (waiter -> outer -> inner) {
144 omapi_object_dereference (&waiter -> outer -> inner,
4bd8800e 145 MDL);
727ebc3a
TL
146 if (waiter -> inner)
147 omapi_object_reference
148 (&waiter -> outer -> inner,
4bd8800e 149 waiter -> inner, MDL);
727ebc3a 150 }
4bd8800e 151 omapi_object_dereference (&waiter -> outer, MDL);
727ebc3a
TL
152 }
153 if (waiter -> inner)
4bd8800e 154 omapi_object_dereference (&waiter -> inner, MDL);
727ebc3a 155
4bd8800e 156 omapi_object_dereference ((omapi_object_t **)&waiter, MDL);
61b844bf
TL
157 return ISC_R_SUCCESS;
158}
159
6a4c4be8 160isc_result_t omapi_one_dispatch (omapi_object_t *wo,
61b844bf
TL
161 struct timeval *t)
162{
163 fd_set r, w, x;
164 int max = 0;
165 int count;
166 int desc;
167 struct timeval now, to;
168 omapi_io_object_t *io, *prev;
169 isc_result_t status;
6a4c4be8
TL
170 omapi_waiter_object_t *waiter;
171
172 if (!wo || wo -> type != omapi_type_waiter)
173 waiter = (omapi_waiter_object_t *)0;
174 else
175 waiter = (omapi_waiter_object_t *)wo;
61b844bf
TL
176
177 FD_ZERO (&x);
178
179 /* First, see if the timeout has expired, and if so return. */
180 if (t) {
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;
186
187 /* We didn't time out, so figure out how long until
188 we do. */
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;
193 to.tv_sec--;
194 }
195 }
196
197 /* If the object we're waiting on has reached completion,
198 return now. */
199 if (waiter && waiter -> ready)
200 return ISC_R_SUCCESS;
201
202 /* If we have no I/O state, we can't proceed. */
203 if (!(io = omapi_io_states.next))
204 return ISC_R_NOMORE;
205
206 /* Set up the read and write masks. */
207 FD_ZERO (&r);
208 FD_ZERO (&w);
209
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. */
214 if (io -> readfd &&
215 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
216 FD_SET (desc, &r);
217 if (desc > max)
218 max = desc;
219 }
220
221 /* Same deal for write fdets. */
222 if (io -> writefd &&
223 (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
224 FD_SET (desc, &w);
225 if (desc > max)
226 max = desc;
227 }
228 }
229
230 /* Wait for a packet or a timeout... XXX */
231 count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0);
232
233 /* Get the current time... */
234 gettimeofday (&now, (struct timezone *)0);
235 cur_time = now.tv_sec;
236
237 /* Not likely to be transitory... */
238 if (count < 0)
239 return ISC_R_UNEXPECTED;
240
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. */
244 if (io -> readfd &&
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? */
249 }
250
251 /* Same deal for write descriptors. */
252 if (io -> writefd &&
253 (desc = (*(io -> writefd)) (io -> inner)) >= 0)
254 {
255 if (FD_ISSET (desc, &w))
256 status = ((*(io -> writer)) (io -> inner));
257 /* XXX what to do with status? */
258 }
259 }
260
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) {
265 if (io -> reaper) {
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. */
272 if (io -> next)
273 omapi_object_reference
274 ((omapi_object_t **)&tmp,
275 (omapi_object_t *)io -> next,
4bd8800e 276 MDL);
61b844bf
TL
277 if (prev) {
278 omapi_object_dereference
279 (((omapi_object_t **)
4bd8800e 280 &prev -> next), MDL);
61b844bf
TL
281 if (tmp)
282 omapi_object_reference
283 (((omapi_object_t **)
284 &prev -> next),
285 (omapi_object_t *)tmp,
4bd8800e 286 MDL);
61b844bf
TL
287 } else {
288 omapi_object_dereference
289 (((omapi_object_t **)
290 &omapi_io_states.next),
4bd8800e 291 MDL);
61b844bf
TL
292 if (tmp)
293 omapi_object_reference
294 (((omapi_object_t **)
295 &omapi_io_states.next),
296 (omapi_object_t *)tmp,
4bd8800e 297 MDL);
61b844bf
TL
298 else
299 omapi_signal_in
300 ((omapi_object_t *)
301 &omapi_io_states,
302 "ready");
303 }
304 if (tmp)
305 omapi_object_dereference
4bd8800e 306 ((omapi_object_t **)&tmp, MDL);
61b844bf
TL
307 }
308 }
309 prev = io;
310 }
311
312 return ISC_R_SUCCESS;
313}
314
315isc_result_t omapi_io_set_value (omapi_object_t *h,
316 omapi_object_t *id,
317 omapi_data_string_t *name,
318 omapi_typed_data_t *value)
319{
320 if (h -> type != omapi_type_io_object)
321 return ISC_R_INVALIDARG;
322
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;
327}
328
329isc_result_t omapi_io_get_value (omapi_object_t *h,
330 omapi_object_t *id,
331 omapi_data_string_t *name,
332 omapi_value_t **value)
333{
334 if (h -> type != omapi_type_io_object)
335 return ISC_R_INVALIDARG;
336
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;
341}
342
4bd8800e 343isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
61b844bf
TL
344{
345 if (h -> type != omapi_type_io_object)
346 return ISC_R_INVALIDARG;
347 return ISC_R_SUCCESS;
348}
349
350isc_result_t omapi_io_signal_handler (omapi_object_t *h,
b1b7b521 351 const char *name, va_list ap)
61b844bf
TL
352{
353 if (h -> type != omapi_type_io_object)
354 return ISC_R_INVALIDARG;
355
356 if (h -> inner && h -> inner -> type -> signal_handler)
357 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
358 name, ap);
359 return ISC_R_NOTFOUND;
360}
361
362isc_result_t omapi_io_stuff_values (omapi_object_t *c,
363 omapi_object_t *id,
364 omapi_object_t *i)
365{
366 if (i -> type != omapi_type_io_object)
367 return ISC_R_INVALIDARG;
368
369 if (i -> inner && i -> inner -> type -> stuff_values)
370 return (*(i -> inner -> type -> stuff_values)) (c, id,
371 i -> inner);
372 return ISC_R_SUCCESS;
373}
374
375isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
b1b7b521 376 const char *name, va_list ap)
61b844bf
TL
377{
378 omapi_waiter_object_t *waiter;
379
380 if (h -> type != omapi_type_waiter)
381 return ISC_R_INVALIDARG;
382
383 if (!strcmp (name, "ready")) {
384 waiter = (omapi_waiter_object_t *)h;
385 waiter -> ready = 1;
386 return ISC_R_SUCCESS;
387 }
388
389 if (h -> inner && h -> inner -> type -> signal_handler)
390 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
391 name, ap);
392 return ISC_R_NOTFOUND;
393}
394