4
* Avahi poll implementation for the CUPS scheduler.
6
* Copyright (C) 2010, 2011 Red Hat, Inc.
8
* Tim Waugh <twaugh@redhat.com>
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
14
* Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
17
* Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
21
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32
* OF THE POSSIBILITY OF SUCH DAMAGE.
36
* watch_read_cb - Read callback for file descriptor
37
* watch_write_cb - Write callback for file descriptor
38
* watched_fd_add_select() - Call cupsdAddSelect() as needed
39
* watch_new() - Create a new file descriptor watch
40
* watch_free() - Free a file descriptor watch
41
* watch_update() - Update watched events for a file descriptor
42
* watch_get_events() - Get events that happened for a file descriptor
43
* timeout_cb() - Run a timed Avahi callback
44
* timeout_new() - Set a wakeup time
45
* timeout_update() - Update the expiration time for a timeout
46
* timeout_free() - Free a timeout
47
* compare_watched_fds() - Compare watched file descriptors for array sorting
48
* avahi_cups_poll_new() - Create a new Avahi main loop object for CUPS
49
* avahi_cups_poll_free() - Free an Avahi main loop object for CUPS
50
* avahi_cups_poll_get() - Get the abstract poll API structure
55
#ifdef HAVE_AVAHI /* Applies to entire file... */
58
* Include necessary headers...
63
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
65
#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
68
# include <avahi-common/timeval.h>
69
#endif /* HAVE_AVAHI */
74
AvahiCupsPoll *cups_poll;
77
AvahiWatchEvent occurred;
78
cups_array_t *watches;
83
cupsd_watched_fd_t *watched_fd;
85
AvahiWatchEvent events;
86
AvahiWatchCallback callback;
92
AvahiCupsPoll *cups_poll;
93
AvahiTimeoutCallback callback;
95
cupsd_timeout_t *cupsd_timeout;
102
static AvahiWatch * watch_new(const AvahiPoll *api,
104
AvahiWatchEvent events,
105
AvahiWatchCallback callback,
107
static void watch_free(AvahiWatch *watch);
108
static void watch_update(AvahiWatch *watch,
109
AvahiWatchEvent events);
110
static AvahiWatchEvent watch_get_events(AvahiWatch *watch);
114
* 'watch_read_cb' - Read callback for file descriptor
118
watch_read_cb (void *userdata)
121
cupsd_watched_fd_t *watched_fd = userdata;
122
watched_fd->occurred |= AVAHI_WATCH_IN;
123
for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
125
watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
127
if (watch->events & watched_fd->occurred)
129
(watch->callback) (watch, watched_fd->fd,
130
AVAHI_WATCH_IN, watch->userdata);
131
watched_fd->occurred &= ~AVAHI_WATCH_IN;
139
* 'watch_write_cb' - Write callback for file descriptor
143
watch_write_cb (void *userdata)
146
cupsd_watched_fd_t *watched_fd = userdata;
147
watched_fd->occurred |= AVAHI_WATCH_OUT;
148
for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
150
watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
152
if (watch->events & watched_fd->occurred)
154
(watch->callback) (watch, watched_fd->fd,
155
AVAHI_WATCH_OUT, watch->userdata);
156
watched_fd->occurred &= ~AVAHI_WATCH_OUT;
164
* 'watched_fd_add_select' - Call cupsdAddSelect() as needed
167
static int /* O - Watches? */
168
watched_fd_add_select (cupsd_watched_fd_t *watched_fd)
171
cupsd_selfunc_t read_cb = NULL, write_cb = NULL;
174
for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches);
176
watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches))
179
if (watch->events & (AVAHI_WATCH_IN |
183
read_cb = (cupsd_selfunc_t)watch_read_cb;
184
if (write_cb != NULL)
188
if (watch->events & AVAHI_WATCH_OUT)
190
write_cb = (cupsd_selfunc_t)watch_write_cb;
196
if (read_cb || write_cb)
197
cupsdAddSelect (watched_fd->fd, read_cb, write_cb, watched_fd);
199
cupsdRemoveSelect (watched_fd->fd);
201
return (any_watches);
205
* 'watch_new' - Create a new file descriptor watch
209
watch_new (const AvahiPoll *api,
211
AvahiWatchEvent events,
212
AvahiWatchCallback callback,
215
cupsd_watched_fd_t key, *watched_fd;
216
AvahiCupsPoll *cups_poll = api->userdata;
217
AvahiWatch *watch = malloc(sizeof(AvahiWatch));
221
watch->events = events;
222
watch->callback = callback;
223
watch->userdata = userdata;
226
watched_fd = cupsArrayFind (cups_poll->watched_fds, &key);
227
if (watched_fd == NULL)
229
watched_fd = malloc(sizeof(cupsd_watched_fd_t));
230
if (watched_fd == NULL)
237
watched_fd->occurred = 0;
238
watched_fd->cups_poll = cups_poll;
239
watched_fd->watches = cupsArrayNew (NULL, NULL);
240
cupsArrayAdd (cups_poll->watched_fds, watched_fd);
243
watch->watched_fd = watched_fd;
244
cupsArrayAdd(watched_fd->watches, watch);
245
watched_fd_add_select (watched_fd);
251
* 'watch_free' - Free a file descriptor watch
255
watch_free (AvahiWatch *watch)
257
cupsd_watched_fd_t *watched_fd = watch->watched_fd;
258
AvahiCupsPoll *cups_poll = watched_fd->cups_poll;
260
cupsArrayRemove (watched_fd->watches, watch);
263
if (!watched_fd_add_select (watched_fd))
265
/* No more watches */
266
cupsArrayRemove (cups_poll->watched_fds, watched_fd);
273
* 'watch_update' - Update watched events for a file descriptor
277
watch_update (AvahiWatch *watch,
278
AvahiWatchEvent events)
280
watch->events = events;
281
watched_fd_add_select (watch->watched_fd);
286
* 'watch_get_events' - Get events that happened for a file descriptor
289
static AvahiWatchEvent
290
watch_get_events (AvahiWatch *watch)
292
return (watch->watched_fd->occurred);
297
* 'timeout_cb()' - Run a timed Avahi callback
301
timeout_cb (cupsd_timeout_t *cupsd_timeout, void *userdata)
303
AvahiTimeout *timeout = userdata;
304
(timeout->callback) (timeout, timeout->userdata);
309
* 'timeout_new' - Set a wakeup time
312
static AvahiTimeout *
313
timeout_new (const AvahiPoll *api,
314
const struct timeval *tv,
315
AvahiTimeoutCallback callback,
318
AvahiTimeout *timeout;
319
AvahiCupsPoll *cups_poll = api->userdata;
321
timeout = malloc(sizeof(AvahiTimeout));
325
timeout->cups_poll = cups_poll;
326
timeout->callback = callback;
327
timeout->userdata = userdata;
328
timeout->cupsd_timeout = cupsdAddTimeout (tv,
329
(cupsd_timeoutfunc_t)timeout_cb,
331
cupsArrayAdd (cups_poll->timeouts, timeout);
337
* 'timeout_update' - Update the expiration time for a timeout
341
timeout_update (AvahiTimeout *timeout,
342
const struct timeval *tv)
344
cupsdUpdateTimeout (timeout->cupsd_timeout, tv);
349
* ' timeout_free' - Free a timeout
353
timeout_free (AvahiTimeout *timeout)
355
cupsArrayRemove (timeout->cups_poll->timeouts, timeout);
356
cupsdRemoveTimeout (timeout->cupsd_timeout);
362
* 'compare_watched_fds' - Compare watched file descriptors for array sorting
365
compare_watched_fds(cupsd_watched_fd_t *p0,
366
cupsd_watched_fd_t *p1)
369
* Compare by fd (no two elements have the same fd)
372
if (p0->fd == p1->fd)
375
return (p0->fd < p1->fd ? -1 : 1);
380
* 'avahi_cups_poll_new' - Create a new Avahi main loop object for CUPS
384
avahi_cups_poll_new (void)
386
AvahiCupsPoll *cups_poll = malloc(sizeof(AvahiCupsPoll));
387
if (cups_poll == NULL)
390
cups_poll->watched_fds = cupsArrayNew ((cups_array_func_t)compare_watched_fds,
392
cups_poll->timeouts = cupsArrayNew (NULL, NULL);
394
cups_poll->api.userdata = cups_poll;
395
cups_poll->api.watch_new = watch_new;
396
cups_poll->api.watch_free = watch_free;
397
cups_poll->api.watch_update = watch_update;
398
cups_poll->api.watch_get_events = watch_get_events;
400
cups_poll->api.timeout_new = timeout_new;
401
cups_poll->api.timeout_update = timeout_update;
402
cups_poll->api.timeout_free = timeout_free;
409
* 'avahi_cups_poll_free' - Free an Avahi main loop object for CUPS
412
avahi_cups_poll_free (AvahiCupsPoll *cups_poll)
414
cupsd_watched_fd_t *watched_fd;
416
for (watched_fd = (cupsd_watched_fd_t*)cupsArrayFirst(cups_poll->watched_fds);
418
watched_fd = (cupsd_watched_fd_t*)cupsArrayNext(cups_poll->watched_fds))
419
cupsArrayClear (watched_fd->watches);
421
cupsArrayClear (cups_poll->watched_fds);
422
cupsArrayClear (cups_poll->timeouts);
427
* 'avahi_cups_poll_get' - Get the abstract poll API structure
431
avahi_cups_poll_get (AvahiCupsPoll *cups_poll)
433
return (&cups_poll->api);
437
#endif /* HAVE_AVAHI ... from top of file */