diff -up cups-1.7.2/scheduler/avahi.c.avahi-no-threaded cups-1.7.2/scheduler/avahi.c --- cups-1.7.2/scheduler/avahi.c.avahi-no-threaded 2014-04-14 13:56:52.632617316 +0200 +++ cups-1.7.2/scheduler/avahi.c 2014-04-14 13:56:52.631617331 +0200 @@ -0,0 +1,441 @@ +/* + * "$Id$" + * + * Avahi poll implementation for the CUPS scheduler. + * + * Copyright (C) 2010, 2011 Red Hat, Inc. + * Authors: + * Tim Waugh + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contents: + * + * watch_read_cb - Read callback for file descriptor + * watch_write_cb - Write callback for file descriptor + * watched_fd_add_select() - Call cupsdAddSelect() as needed + * watch_new() - Create a new file descriptor watch + * watch_free() - Free a file descriptor watch + * watch_update() - Update watched events for a file descriptor + * watch_get_events() - Get events that happened for a file descriptor + * timeout_cb() - Run a timed Avahi callback + * timeout_new() - Set a wakeup time + * timeout_update() - Update the expiration time for a timeout + * timeout_free() - Free a timeout + * compare_watched_fds() - Compare watched file descriptors for array sorting + * avahi_cups_poll_new() - Create a new Avahi main loop object for CUPS + * avahi_cups_poll_free() - Free an Avahi main loop object for CUPS + * avahi_cups_poll_get() - Get the abstract poll API structure + */ + +#include + +#ifdef HAVE_AVAHI /* Applies to entire file... */ + +/* + * Include necessary headers... + */ + +#include "cupsd.h" + +#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) +# include +#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ + +#ifdef HAVE_AVAHI +# include +#endif /* HAVE_AVAHI */ + + +typedef struct +{ + AvahiCupsPoll *cups_poll; + + int fd; + AvahiWatchEvent occurred; + cups_array_t *watches; +} cupsd_watched_fd_t; + +struct AvahiWatch +{ + cupsd_watched_fd_t *watched_fd; + + AvahiWatchEvent events; + AvahiWatchCallback callback; + void *userdata; +}; + +struct AvahiTimeout +{ + AvahiCupsPoll *cups_poll; + AvahiTimeoutCallback callback; + void *userdata; + cupsd_timeout_t *cupsd_timeout; +}; + +/* + * Local functions... + */ + +static AvahiWatch * watch_new(const AvahiPoll *api, + int fd, + AvahiWatchEvent events, + AvahiWatchCallback callback, + void *userdata); +static void watch_free(AvahiWatch *watch); +static void watch_update(AvahiWatch *watch, + AvahiWatchEvent events); +static AvahiWatchEvent watch_get_events(AvahiWatch *watch); + + +/* + * 'watch_read_cb' - Read callback for file descriptor + */ + +static void +watch_read_cb (void *userdata) +{ + AvahiWatch *watch; + cupsd_watched_fd_t *watched_fd = userdata; + watched_fd->occurred |= AVAHI_WATCH_IN; + for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); + watch; + watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) + { + if (watch->events & watched_fd->occurred) + { + (watch->callback) (watch, watched_fd->fd, + AVAHI_WATCH_IN, watch->userdata); + watched_fd->occurred &= ~AVAHI_WATCH_IN; + break; + } + } +} + + +/* + * 'watch_write_cb' - Write callback for file descriptor + */ + +static void +watch_write_cb (void *userdata) +{ + AvahiWatch *watch; + cupsd_watched_fd_t *watched_fd = userdata; + watched_fd->occurred |= AVAHI_WATCH_OUT; + for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); + watch; + watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) + { + if (watch->events & watched_fd->occurred) + { + (watch->callback) (watch, watched_fd->fd, + AVAHI_WATCH_OUT, watch->userdata); + watched_fd->occurred &= ~AVAHI_WATCH_OUT; + break; + } + } +} + + +/* + * 'watched_fd_add_select' - Call cupsdAddSelect() as needed + */ + +static int /* O - Watches? */ +watched_fd_add_select (cupsd_watched_fd_t *watched_fd) +{ + AvahiWatch *watch; + cupsd_selfunc_t read_cb = NULL, write_cb = NULL; + int any_watches = 0; + + for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); + watch; + watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) + { + any_watches = 1; + if (watch->events & (AVAHI_WATCH_IN | + AVAHI_WATCH_ERR | + AVAHI_WATCH_HUP)) + { + read_cb = (cupsd_selfunc_t)watch_read_cb; + if (write_cb != NULL) + break; + } + + if (watch->events & AVAHI_WATCH_OUT) + { + write_cb = (cupsd_selfunc_t)watch_write_cb; + if (read_cb != NULL) + break; + } + } + + if (read_cb || write_cb) + cupsdAddSelect (watched_fd->fd, read_cb, write_cb, watched_fd); + else + cupsdRemoveSelect (watched_fd->fd); + + return (any_watches); +} + +/* + * 'watch_new' - Create a new file descriptor watch + */ + +static AvahiWatch * +watch_new (const AvahiPoll *api, + int fd, + AvahiWatchEvent events, + AvahiWatchCallback callback, + void *userdata) +{ + cupsd_watched_fd_t key, *watched_fd; + AvahiCupsPoll *cups_poll = api->userdata; + AvahiWatch *watch = malloc(sizeof(AvahiWatch)); + if (watch == NULL) + return (NULL); + + watch->events = events; + watch->callback = callback; + watch->userdata = userdata; + + key.fd = fd; + watched_fd = cupsArrayFind (cups_poll->watched_fds, &key); + if (watched_fd == NULL) + { + watched_fd = malloc(sizeof(cupsd_watched_fd_t)); + if (watched_fd == NULL) + { + free (watch); + return (NULL); + } + + watched_fd->fd = fd; + watched_fd->occurred = 0; + watched_fd->cups_poll = cups_poll; + watched_fd->watches = cupsArrayNew (NULL, NULL); + cupsArrayAdd (cups_poll->watched_fds, watched_fd); + } + + watch->watched_fd = watched_fd; + cupsArrayAdd(watched_fd->watches, watch); + watched_fd_add_select (watched_fd); + return (watch); +} + + +/* + * 'watch_free' - Free a file descriptor watch + */ + +static void +watch_free (AvahiWatch *watch) +{ + cupsd_watched_fd_t *watched_fd = watch->watched_fd; + AvahiCupsPoll *cups_poll = watched_fd->cups_poll; + + cupsArrayRemove (watched_fd->watches, watch); + free (watch); + + if (!watched_fd_add_select (watched_fd)) + { + /* No more watches */ + cupsArrayRemove (cups_poll->watched_fds, watched_fd); + free (watched_fd); + } +} + + +/* + * 'watch_update' - Update watched events for a file descriptor + */ + +static void +watch_update (AvahiWatch *watch, + AvahiWatchEvent events) +{ + watch->events = events; + watched_fd_add_select (watch->watched_fd); +} + + +/* + * 'watch_get_events' - Get events that happened for a file descriptor + */ + +static AvahiWatchEvent +watch_get_events (AvahiWatch *watch) +{ + return (watch->watched_fd->occurred); +} + + +/* + * 'timeout_cb()' - Run a timed Avahi callback + */ + +static void +timeout_cb (cupsd_timeout_t *cupsd_timeout, void *userdata) +{ + AvahiTimeout *timeout = userdata; + (timeout->callback) (timeout, timeout->userdata); +} + + +/* + * 'timeout_new' - Set a wakeup time + */ + +static AvahiTimeout * +timeout_new (const AvahiPoll *api, + const struct timeval *tv, + AvahiTimeoutCallback callback, + void *userdata) +{ + AvahiTimeout *timeout; + AvahiCupsPoll *cups_poll = api->userdata; + + timeout = malloc(sizeof(AvahiTimeout)); + if (timeout == NULL) + return (NULL); + + timeout->cups_poll = cups_poll; + timeout->callback = callback; + timeout->userdata = userdata; + timeout->cupsd_timeout = cupsdAddTimeout (tv, + (cupsd_timeoutfunc_t)timeout_cb, + timeout); + cupsArrayAdd (cups_poll->timeouts, timeout); + return (timeout); +} + + +/* + * 'timeout_update' - Update the expiration time for a timeout + */ + +static void +timeout_update (AvahiTimeout *timeout, + const struct timeval *tv) +{ + cupsdUpdateTimeout (timeout->cupsd_timeout, tv); +} + + +/* + * ' timeout_free' - Free a timeout + */ + +static void +timeout_free (AvahiTimeout *timeout) +{ + cupsArrayRemove (timeout->cups_poll->timeouts, timeout); + cupsdRemoveTimeout (timeout->cupsd_timeout); + free (timeout); +} + + +/* + * 'compare_watched_fds' - Compare watched file descriptors for array sorting + */ +static int +compare_watched_fds(cupsd_watched_fd_t *p0, + cupsd_watched_fd_t *p1) +{ + /* + * Compare by fd (no two elements have the same fd) + */ + + if (p0->fd == p1->fd) + return 0; + + return (p0->fd < p1->fd ? -1 : 1); +} + + +/* + * 'avahi_cups_poll_new' - Create a new Avahi main loop object for CUPS + */ + +AvahiCupsPoll * +avahi_cups_poll_new (void) +{ + AvahiCupsPoll *cups_poll = malloc(sizeof(AvahiCupsPoll)); + if (cups_poll == NULL) + return (NULL); + + cups_poll->watched_fds = cupsArrayNew ((cups_array_func_t)compare_watched_fds, + NULL); + cups_poll->timeouts = cupsArrayNew (NULL, NULL); + + cups_poll->api.userdata = cups_poll; + cups_poll->api.watch_new = watch_new; + cups_poll->api.watch_free = watch_free; + cups_poll->api.watch_update = watch_update; + cups_poll->api.watch_get_events = watch_get_events; + + cups_poll->api.timeout_new = timeout_new; + cups_poll->api.timeout_update = timeout_update; + cups_poll->api.timeout_free = timeout_free; + + return (cups_poll); +} + + +/* + * 'avahi_cups_poll_free' - Free an Avahi main loop object for CUPS + */ +void +avahi_cups_poll_free (AvahiCupsPoll *cups_poll) +{ + cupsd_watched_fd_t *watched_fd; + + for (watched_fd = (cupsd_watched_fd_t*)cupsArrayFirst(cups_poll->watched_fds); + watched_fd; + watched_fd = (cupsd_watched_fd_t*)cupsArrayNext(cups_poll->watched_fds)) + cupsArrayClear (watched_fd->watches); + + cupsArrayClear (cups_poll->watched_fds); + cupsArrayClear (cups_poll->timeouts); +} + + +/* + * 'avahi_cups_poll_get' - Get the abstract poll API structure + */ + +const AvahiPoll * +avahi_cups_poll_get (AvahiCupsPoll *cups_poll) +{ + return (&cups_poll->api); +} + + +#endif /* HAVE_AVAHI ... from top of file */ + +/* + * End of "$Id$". + */ diff -up cups-1.7.2/scheduler/avahi.h.avahi-no-threaded cups-1.7.2/scheduler/avahi.h --- cups-1.7.2/scheduler/avahi.h.avahi-no-threaded 2014-04-14 13:56:52.632617316 +0200 +++ cups-1.7.2/scheduler/avahi.h 2014-04-14 13:56:52.632617316 +0200 @@ -0,0 +1,69 @@ +/* + * "$Id$" + * + * Avahi poll implementation for the CUPS scheduler. + * + * Copyright (C) 2010, 2011 Red Hat, Inc. + * Authors: + * Tim Waugh + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#ifdef HAVE_AVAHI +# include +# include +#endif /* HAVE_AVAHI */ + +#ifdef HAVE_AUTHORIZATION_H +# include +#endif /* HAVE_AUTHORIZATION_H */ + + +#ifdef HAVE_AVAHI +typedef struct +{ + AvahiPoll api; + cups_array_t *watched_fds; + cups_array_t *timeouts; +} AvahiCupsPoll; +#endif /* HAVE_AVAHI */ + +/* + * Prototypes... + */ + +#ifdef HAVE_AVAHI +extern AvahiCupsPoll * avahi_cups_poll_new(void); +extern void avahi_cups_poll_free(AvahiCupsPoll *cups_poll); +extern const AvahiPoll *avahi_cups_poll_get(AvahiCupsPoll *cups_poll); +#endif /* HAVE_AVAHI */ + + +/* + * End of "$Id$". + */ diff -up cups-1.7.2/scheduler/cupsd.h.avahi-no-threaded cups-1.7.2/scheduler/cupsd.h --- cups-1.7.2/scheduler/cupsd.h.avahi-no-threaded 2013-05-29 13:51:34.000000000 +0200 +++ cups-1.7.2/scheduler/cupsd.h 2014-04-14 13:56:52.632617316 +0200 @@ -119,6 +119,7 @@ extern const char *cups_hstrerror(int); #include "colorman.h" #include "conf.h" #include "banners.h" +#include "avahi.h" #include "dirsvc.h" #include "network.h" #include "subscriptions.h" @@ -139,6 +140,15 @@ extern const char *cups_hstrerror(int); typedef void (*cupsd_selfunc_t)(void *data); +#ifdef HAVE_AVAHI +/* + * Timeout callback function type... + */ + +typedef struct _cupsd_timeout_s cupsd_timeout_t; +typedef void (*cupsd_timeoutfunc_t)(cupsd_timeout_t *timeout, void *data); +#endif /* HAVE_AVAHI */ + /* * Globals... @@ -165,6 +175,11 @@ VAR int Launchd VALUE(0); /* Running from launchd */ #endif /* HAVE_LAUNCH_H */ +#ifdef HAVE_AVAHI +VAR cups_array_t *Timeouts; /* Timed callbacks for main loop */ +#endif /* HAVE_AVAHI */ + + /* * Prototypes... @@ -229,6 +244,17 @@ extern void cupsdStopSelect(void); extern void cupsdStartServer(void); extern void cupsdStopServer(void); +#ifdef HAVE_AVAHI +extern void cupsdInitTimeouts(void); +extern cupsd_timeout_t *cupsdAddTimeout (const struct timeval *tv, + cupsd_timeoutfunc_t cb, + void *data); +extern cupsd_timeout_t *cupsdNextTimeout (long *delay); +extern void cupsdRunTimeout (cupsd_timeout_t *timeout); +extern void cupsdUpdateTimeout (cupsd_timeout_t *timeout, + const struct timeval *tv); +extern void cupsdRemoveTimeout (cupsd_timeout_t *timeout); +#endif /* HAVE_AVAHI */ /* * End of "$Id: cupsd.h 10996 2013-05-29 11:51:34Z msweet $". diff -up cups-1.7.2/scheduler/dirsvc.c.avahi-no-threaded cups-1.7.2/scheduler/dirsvc.c --- cups-1.7.2/scheduler/dirsvc.c.avahi-no-threaded 2014-03-05 22:11:32.000000000 +0100 +++ cups-1.7.2/scheduler/dirsvc.c 2014-04-14 14:21:11.121344106 +0200 @@ -195,7 +195,7 @@ cupsdStartBrowsing(void) cupsdUpdateDNSSDName(); # else /* HAVE_AVAHI */ - if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL) + if ((DNSSDMaster = avahi_cups_poll_new()) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create DNS-SD thread."); @@ -206,7 +206,7 @@ cupsdStartBrowsing(void) { int error; /* Error code, if any */ - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); + DNSSDClient = avahi_client_new(avahi_cups_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); if (DNSSDClient == NULL) { @@ -217,11 +217,9 @@ cupsdStartBrowsing(void) if (FatalErrors & CUPSD_FATAL_BROWSE) cupsdEndProcess(getpid(), 0); - avahi_threaded_poll_free(DNSSDMaster); + avahi_cups_poll_free(DNSSDMaster); DNSSDMaster = NULL; } - else - avahi_threaded_poll_start(DNSSDMaster); } # endif /* HAVE_DNSSD */ } @@ -606,7 +604,7 @@ dnssdClientCallback( * Renew Avahi client... */ - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); + DNSSDClient = avahi_client_new(avahi_cups_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); if (!DNSSDClient) { @@ -670,13 +668,7 @@ dnssdDeregisterInstance( DNSServiceRefDeallocate(*srv); # else /* HAVE_AVAHI */ - if (!from_callback) - avahi_threaded_poll_lock(DNSSDMaster); - avahi_entry_group_free(*srv); - - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ *srv = NULL; @@ -997,16 +989,10 @@ dnssdRegisterInstance( (void)commit; # else /* HAVE_AVAHI */ - if (!from_callback) - avahi_threaded_poll_lock(DNSSDMaster); - if (!*srv) *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL); if (!*srv) { - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); - cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", name, dnssdErrorString(avahi_client_errno(DNSSDClient))); return (0); @@ -1121,9 +1107,6 @@ dnssdRegisterInstance( cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.", name); } - - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ if (error) @@ -1294,12 +1277,10 @@ dnssdStop(void) DNSSDMaster = NULL; # else /* HAVE_AVAHI */ - avahi_threaded_poll_stop(DNSSDMaster); - avahi_client_free(DNSSDClient); DNSSDClient = NULL; - avahi_threaded_poll_free(DNSSDMaster); + avahi_cups_poll_free(DNSSDMaster); DNSSDMaster = NULL; # endif /* HAVE_DNSSD */ diff -up cups-1.7.2/scheduler/dirsvc.h.avahi-no-threaded cups-1.7.2/scheduler/dirsvc.h --- cups-1.7.2/scheduler/dirsvc.h.avahi-no-threaded 2013-05-29 13:51:34.000000000 +0200 +++ cups-1.7.2/scheduler/dirsvc.h 2014-04-14 13:56:52.633617302 +0200 @@ -51,7 +51,7 @@ VAR cups_array_t *DNSSDPrinters VALUE(NU VAR DNSServiceRef DNSSDMaster VALUE(NULL); /* Master DNS-SD service reference */ # else /* HAVE_AVAHI */ -VAR AvahiThreadedPoll *DNSSDMaster VALUE(NULL); +VAR AvahiCupsPoll *DNSSDMaster VALUE(NULL); /* Master polling interface for Avahi */ VAR AvahiClient *DNSSDClient VALUE(NULL); /* Client information */ diff -up cups-1.7.2/scheduler/main.c.avahi-no-threaded cups-1.7.2/scheduler/main.c --- cups-1.7.2/scheduler/main.c.avahi-no-threaded 2014-04-14 13:56:52.600617782 +0200 +++ cups-1.7.2/scheduler/main.c 2014-04-14 13:56:52.634617287 +0200 @@ -134,6 +134,10 @@ main(int argc, /* I - Number of comm int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ +#ifdef HAVE_AVAHI + cupsd_timeout_t *tmo; /* Next scheduled timed callback */ + long tmo_delay; /* Time before it must be called */ +#endif /* HAVE_AVAHI */ #ifdef HAVE_GETEUID @@ -583,6 +587,14 @@ main(int argc, /* I - Number of comm httpInitialize(); +#ifdef HAVE_AVAHI + /* + * Initialize timed callback structures. + */ + + cupsdInitTimeouts(); +#endif /* HAVE_AVAHI */ + cupsdStartServer(); /* @@ -904,6 +916,16 @@ main(int argc, /* I - Number of comm } #endif /* __APPLE__ */ +#ifdef HAVE_AVAHI + /* + * If a timed callback is due, run it. + */ + + tmo = cupsdNextTimeout (&tmo_delay); + if (tmo && tmo_delay == 0) + cupsdRunTimeout (tmo); +#endif /* HAVE_AVAHI */ + #ifndef __APPLE__ /* * Update the network interfaces once a minute... @@ -1884,6 +1906,10 @@ select_timeout(int fds) /* I - Number cupsd_job_t *job; /* Job information */ cupsd_subscription_t *sub; /* Subscription information */ const char *why; /* Debugging aid */ +#ifdef HAVE_AVAHI + cupsd_timeout_t *tmo; /* Timed callback */ + long tmo_delay; /* Seconds before calling it */ +#endif /* HAVE_AVAHI */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout: JobHistoryUpdate=%ld", @@ -1929,6 +1955,19 @@ select_timeout(int fds) /* I - Number } #endif /* __APPLE__ */ +#ifdef HAVE_AVAHI + /* + * See if there are any scheduled timed callbacks to run. + */ + + if ((tmo = cupsdNextTimeout(&tmo_delay)) != NULL && + (now + tmo_delay) < timeout) + { + timeout = tmo_delay; + why = "run a timed callback"; + } +#endif /* HAVE_AVAHI */ + /* * Check whether we are accepting new connections... */ diff -up cups-1.7.2/scheduler/Makefile.avahi-no-threaded cups-1.7.2/scheduler/Makefile --- cups-1.7.2/scheduler/Makefile.avahi-no-threaded 2014-04-14 13:56:52.600617782 +0200 +++ cups-1.7.2/scheduler/Makefile 2014-04-14 13:56:52.631617331 +0200 @@ -17,6 +17,7 @@ include ../Makedefs CUPSDOBJS = \ auth.o \ + avahi.o \ banners.o \ cert.o \ classes.o \ @@ -41,6 +42,7 @@ CUPSDOBJS = \ statbuf.o \ subscriptions.o \ sysman.o \ + timeout.o \ tls.o LIBOBJS = \ filter.o \ diff -up cups-1.7.2/scheduler/timeout.c.avahi-no-threaded cups-1.7.2/scheduler/timeout.c --- cups-1.7.2/scheduler/timeout.c.avahi-no-threaded 2014-04-14 13:56:52.634617287 +0200 +++ cups-1.7.2/scheduler/timeout.c 2014-04-14 13:56:52.634617287 +0200 @@ -0,0 +1,235 @@ +/* + * "$Id$" + * + * Timeout functions for the Common UNIX Printing System (CUPS). + * + * Copyright (C) 2010, 2011 Red Hat, Inc. + * Authors: + * Tim Waugh + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contents: + * + * cupsdInitTimeouts() - Initialise timeout structure. + * cupsdAddTimeout() - Add a timed callback. + * cupsdNextTimeout() - Find the next enabled timed callback. + * cupsdUpdateTimeout() - Adjust the time of a timed callback or disable it. + * cupsdRemoveTimeout() - Discard a timed callback. + * compare_timeouts() - Compare timed callbacks for array sorting. + */ + +#include + +#ifdef HAVE_AVAHI /* Applies to entire file... */ + +/* + * Include necessary headers... + */ + +#include "cupsd.h" + +#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) +# include +#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ + +#ifdef HAVE_AVAHI +# include +#endif /* HAVE_AVAHI */ + + +struct _cupsd_timeout_s +{ + struct timeval when; + int enabled; + cupsd_timeoutfunc_t callback; + void *data; +}; + +/* + * Local functions... + */ + +/* + * 'compare_timeouts()' - Compare timed callbacks for array sorting. + */ + +static int +compare_addrs (void *p0, void *p1) +{ + if (p0 == p1) + return (0); + if (p0 < p1) + return (-1); + return (1); +} + +static int +compare_timeouts (cupsd_timeout_t *p0, cupsd_timeout_t *p1) +{ + int addrsdiff = compare_addrs (p0, p1); + int tvdiff; + + if (addrsdiff == 0) + return (0); + + if (!p0->enabled || !p1->enabled) + { + if (!p0->enabled && !p1->enabled) + return (addrsdiff); + + return (p0->enabled ? -1 : 1); + } + + tvdiff = avahi_timeval_compare (&p0->when, &p1->when); + if (tvdiff != 0) + return (tvdiff); + + return (addrsdiff); +} + + +/* + * 'cupsdInitTimeouts()' - Initialise timeout structures. + */ + +void +cupsdInitTimeouts(void) +{ + Timeouts = cupsArrayNew ((cups_array_func_t)compare_timeouts, NULL); +} + + +/* + * 'cupsdAddTimeout()' - Add a timed callback. + */ + +cupsd_timeout_t * /* O - Timeout handle */ +cupsdAddTimeout(const struct timeval *tv, /* I - Absolute time */ + cupsd_timeoutfunc_t cb, /* I - Callback function */ + void *data) /* I - User data */ +{ + cupsd_timeout_t *timeout; + + timeout = malloc (sizeof(cupsd_timeout_t)); + if (timeout != NULL) + { + timeout->enabled = (tv != NULL); + if (tv) + { + timeout->when.tv_sec = tv->tv_sec; + timeout->when.tv_usec = tv->tv_usec; + } + + timeout->callback = cb; + timeout->data = data; + cupsArrayAdd (Timeouts, timeout); + } + + return timeout; +} + + +/* + * 'cupsdNextTimeout()' - Find the next enabled timed callback. + */ + +cupsd_timeout_t * /* O - Next enabled timeout or NULL */ +cupsdNextTimeout(long *delay) /* O - Seconds before scheduled */ +{ + cupsd_timeout_t *first = cupsArrayFirst (Timeouts); + struct timeval curtime; + + if (first && !first->enabled) + first = NULL; + + if (first && delay) + { + gettimeofday (&curtime, NULL); + if (avahi_timeval_compare (&curtime, &first->when) > 0) + { + *delay = 0; + } else { + *delay = 1 + first->when.tv_sec - curtime.tv_sec; + if (first->when.tv_usec < curtime.tv_usec) + (*delay)--; + } + } + + return (first); +} + + +/* + * 'cupsdRunTimeout()' - Run a timed callback. + */ + +void +cupsdRunTimeout(cupsd_timeout_t *timeout) /* I - Timeout */ +{ + if (!timeout) + return; + timeout->enabled = 0; + if (!timeout->callback) + return; + timeout->callback (timeout, timeout->data); +} + +/* + * 'cupsdUpdateTimeout()' - Adjust the time of a timed callback or disable it. + */ + +void +cupsdUpdateTimeout(cupsd_timeout_t *timeout, /* I - Timeout */ + const struct timeval *tv) /* I - Absolute time or NULL */ +{ + cupsArrayRemove (Timeouts, timeout); + timeout->enabled = (tv != NULL); + if (tv) + { + timeout->when.tv_sec = tv->tv_sec; + timeout->when.tv_usec = tv->tv_usec; + } + cupsArrayAdd (Timeouts, timeout); +} + + +/* + * 'cupsdRemoveTimeout()' - Discard a timed callback. + */ + +void +cupsdRemoveTimeout(cupsd_timeout_t *timeout) /* I - Timeout */ +{ + cupsArrayRemove (Timeouts, timeout); + free (timeout); +} + + +#endif /* HAVE_AVAHI ... from top of file */ + +/* + * End of "$Id$". + */