From a2187a63425a3d6c05de1e1cbf8c26fd39a1aced Mon Sep 17 00:00:00 2001 From: Michael R Sweet
Date: Wed, 19 Apr 2017 15:29:42 -0400 Subject: [PATCH] Update cupsEnumDests implementation to return early if all
Hello community, here is the log from the commit of package cups for openSUSE:Factory checked in at 2017-05-03 15:53:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cups (Old) and /work/SRC/openSUSE:Factory/.cups.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "cups" Wed May 3 15:53:05 2017 rev:138 rq:491776 version:2.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/cups/cups.changes 2017-04-12 17:09:03.808014252 +0200 +++ /work/SRC/openSUSE:Factory/.cups.new/cups.changes 2017-05-03 15:53:07.250694792 +0200 @@ -1,0 +2,22 @@ +Thu Apr 20 16:26:52 UTC 2017 - alarrosa@suse.com + +- Drop cups-1.7.5-cupsEnumDests-react-to-all-for-now.diff and add + 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch, + 0002-Save-work-on-Avahi-code.patch and + 0003-Avahi-fixes-for-cupsEnumDests.patch which is what upstream + finally commited to cups 2.2 sources in response to + https://github.com/apple/cups/pull/4989 in order to fix cupsEnumDests + to react to the ALL_FOR_NOW avahi event (and also include a similar + fix for the dnssd case). Related to bsc#955432. + +------------------------------------------------------------------- +Mon Apr 10 17:37:16 UTC 2017 - alarrosa@suse.com + +- Add cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff . + Avahi sends an ALL_FOR_NOW event when it finishes sending + its cache contents. This patch makes cupsEnumDests finish + when the signal is received so it doesn't block the caller + doing nothing until the timeout finishes (related to bsc#955432, + submitted upstream at https://github.com/apple/cups/pull/4989) + +------------------------------------------------------------------- New: ---- 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch 0002-Save-work-on-Avahi-code.patch 0003-Avahi-fixes-for-cupsEnumDests.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cups.spec ++++++ --- /var/tmp/diff_new_pack.7RKfiL/_old 2017-05-03 15:53:08.526514677 +0200 +++ /var/tmp/diff_new_pack.7RKfiL/_new 2017-05-03 15:53:08.530514112 +0200 @@ -45,6 +45,12 @@ Patch11: cups-2.1.0-default-webcontent-path.patch # Patch12 cups-2.1.0-cups-systemd-socket.patch Use systemd socket activation properly: Patch12: cups-2.1.0-cups-systemd-socket.patch +# Patch13 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch bsc#955432 -- React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +Patch13: 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch +# Patch14 0002-Save-work-on-Avahi-code.patch bsc#955432 -- React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +Patch14: 0002-Save-work-on-Avahi-code.patch +# Patch15 0003-Avahi-fixes-for-cupsEnumDests.patch bsc#955432 -- React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +Patch15: 0003-Avahi-fixes-for-cupsEnumDests.patch # Patch100...Patch999 is for private patches from SUSE which are not intended for upstream: # Patch100 cups-pam.diff adds conf/pam.suse regarding support for PAM for SUSE: Patch100: cups-pam.diff @@ -133,9 +139,9 @@ %package libs Summary: Libraries for CUPS -# Prerequire /sbin/ldconfig which is used in the traditional bash scriptlets for post/postun: License: GPL-2.0 and LGPL-2.1 Group: Hardware/Printing +# Prerequire /sbin/ldconfig which is used in the traditional bash scriptlets for post/postun: Requires(pre): /sbin/ldconfig %if 0%{?suse_version} >= 1330 Requires(pre): group(lp) @@ -157,6 +163,8 @@ %package client Summary: CUPS Client Programs +License: GPL-2.0 +Group: Hardware/Printing # Require the exact matching version-release of the cups-libs sub-package because # non-matching CUPS libraries may let CUPS software crash (e.g. segfault) # because all CUPS software is built from the one same CUPS source tar ball @@ -166,8 +174,6 @@ # on the same package repository where the cups package is because # all are built simulaneously from the same cups source package # and all required packages are provided on the same repository: -License: GPL-2.0 -Group: Hardware/Printing Requires: cups-libs = %{version}-%{release} # Conflicts with other print spoolers which provide same binaries like /usr/bin/lp and so on: Conflicts: lprng @@ -190,13 +196,13 @@ %package devel Summary: Development Environment for CUPS +License: GPL-2.0 +Group: Development/Libraries/C and C++ # Do not require the exact matching version-release of cups-libs # but only a cups-libs package with matching version because # for building third-party software which uses only the CUPS public API # there are no CUPS-internal dependencies via CUPS private API calls # (the latter would require the exact matching cups-libs version-release): -License: GPL-2.0 -Group: Development/Libraries/C and C++ Requires: cups-libs = %{version} Requires: glibc-devel @@ -258,6 +264,12 @@ %patch11 -b default-webcontent-path.prig # Patch12 cups-2.1.0-cups-systemd-socket.patch Use systemd socket activation properly: %patch12 -b cups-systemd-socket.orig +# Patch13 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +%patch13 -p1 +# Patch14 0002-Save-work-on-Avahi-code.patch React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +%patch14 -p1 +# Patch15 0003-Avahi-fixes-for-cupsEnumDests.patch React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +%patch15 -p1 # Patch100...Patch999 is for private patches from SUSE which are not intended for upstream: # Patch100 cups-pam.diff adds conf/pam.suse regarding support for PAM for SUSE: %patch100 ++++++ 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch ++++++ printers have been discovered (Issue #4989) Also update the code to generate the same queue names as cupsd does for IPP Everywhere printers. --- CHANGES.txt | 4 +- cups/dest.c | 169 +++++++++++++++++++++++++++++++++++++++++++------------- cups/testdest.c | 4 +- 3 files changed, 136 insertions(+), 41 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index b06a9ee..54f2a7f 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -101,9 +101,10 @@ typedef struct _cups_dnssd_device_s /* Enumerated device */ # else /* HAVE_AVAHI */ AvahiRecordBrowser *ref; /* Browser for query */ # endif /* HAVE_DNSSD */ - char *domain, /* Domain name */ - *fullName, /* Full name */ - *regtype; /* Registration type */ + char *fullName, /* Full name */ +// *serviceName, /* Service name */ + *regtype, /* Registration type */ + *domain; /* Domain name */ cups_ptype_t type; /* Device registration type */ cups_dest_t dest; /* Destination record */ } _cups_dnssd_device_t; @@ -202,6 +203,7 @@ static void cups_dnssd_query_cb(AvahiRecordBrowser *browser, AvahiLookupResultFlags flags, void *context); # endif /* HAVE_DNSSD */ +static void cups_dnssd_queue_name(char *name, const char *serviceName, size_t namesize); static const char *cups_dnssd_resolve(cups_dest_t *dest, const char *uri, int msec, int *cancel, cups_dest_cb_t cb, void *user_data); @@ -920,14 +922,13 @@ _cupsCreateDest(const char *name, /* I - Printer name */ int /* O - 1 on success, 0 on failure */ cupsEnumDests( - unsigned flags, /* I - Enumeration flags */ - int msec, /* I - Timeout in milliseconds, - * -1 for indefinite */ - int *cancel, /* I - Pointer to "cancel" variable */ - cups_ptype_t type, /* I - Printer type bits */ - cups_ptype_t mask, /* I - Mask for printer type bits */ - cups_dest_cb_t cb, /* I - Callback function */ - void *user_data) /* I - User data */ + unsigned flags, /* I - Enumeration flags */ + int msec, /* I - Timeout in milliseconds, -1 for indefinite */ + int *cancel, /* I - Pointer to "cancel" variable */ + cups_ptype_t type, /* I - Printer type bits */ + cups_ptype_t mask, /* I - Mask for printer type bits */ + cups_dest_cb_t cb, /* I - Callback function */ + void *user_data) /* I - User data */ { int i, /* Looping var */ num_dests; /* Number of destinations */ @@ -939,6 +940,7 @@ cupsEnumDests( *user_default; /* User default printer */ #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) int count, /* Number of queries started */ + completed, /* Number of completed queries */ remaining; /* Remainder of timeout */ _cups_dnssd_data_t data; /* Data for callback */ _cups_dnssd_device_t *device; /* Current device */ @@ -1007,29 +1009,70 @@ cupsEnumDests( dest->is_default = 1; } +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + data.type = type; + data.mask = mask; + data.cb = cb; + data.user_data = user_data; + data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_func_t)cups_dnssd_free_device); +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + for (i = num_dests, dest = dests; i > 0 && (!cancel || !*cancel); i --, dest ++) + { + const char *device_uri; /* Device URI */ + if (!(*cb)(user_data, i > 1 ? CUPS_DEST_FLAGS_MORE : CUPS_DEST_FLAGS_NONE, dest)) break; + if (!dest->instance && (device_uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL && !strncmp(device_uri, "dnssd://", 8)) + { + /* + * Add existing queue using service name, etc. so we don't list it again... + */ + + char scheme[32], /* URI scheme */ + userpass[32], /* Username:password */ + serviceName[256], /* Service name (host field) */ + resource[256], /* Resource (options) */ + *regtype, /* Registration type */ + *replyDomain; /* Registration domain */ + int port; /* Port number (not used) */ + + if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), serviceName, sizeof(serviceName), &port, resource, sizeof(resource)) >= HTTP_URI_STATUS_OK) + { + if ((regtype = strstr(serviceName, "._ipp")) != NULL) + { + *regtype++ = '\0'; + + if ((replyDomain = strstr(regtype, "._tcp.")) != NULL) + { + replyDomain[5] = '\0'; + replyDomain += 6; + + if ((device = cups_dnssd_get_device(&data, serviceName, regtype, replyDomain)) != NULL) + device->state = _CUPS_DNSSD_ACTIVE; + } + } + } + } + } + cupsFreeDests(num_dests, dests); if (i > 0 || msec == 0) + { + cupsArrayDelete(data.devices); return (1); + } #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) /* * Get Bonjour-shared printers... */ - data.type = type; - data.mask = mask; - data.cb = cb; - data.user_data = user_data; - data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_func_t)cups_dnssd_free_device); - # ifdef HAVE_DNSSD if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError) return (0); @@ -1105,27 +1148,25 @@ cupsEnumDests( pfd.fd = main_fd; pfd.events = POLLIN; - nfds = poll(&pfd, 1, remaining > 250 ? 250 : remaining); + nfds = poll(&pfd, 1, remaining > 500 ? 500 : remaining); # else FD_ZERO(&input); FD_SET(main_fd, &input); timeout.tv_sec = 0; - timeout.tv_usec = remaining > 250 ? 250000 : remaining * 1000; + timeout.tv_usec = remaining > 500 ? 500000 : remaining * 1000; nfds = select(main_fd + 1, &input, NULL, NULL, &timeout); # endif /* HAVE_POLL */ if (nfds > 0) DNSServiceProcessResult(data.main_ref); - else if (nfds == 0) - remaining -= 250; # else /* HAVE_AVAHI */ data.got_data = 0; - if ((error = avahi_simple_poll_iterate(data.simple_poll, 250)) > 0) + if ((error = avahi_simple_poll_iterate(data.simple_poll, 500)) > 0) { /* * We've been told to exit the loop. Perhaps the connection to @@ -1135,18 +1176,21 @@ cupsEnumDests( break; } - if (!data.got_data) - remaining -= 250; # endif /* HAVE_DNSSD */ + remaining -= 500; + for (device = (_cups_dnssd_device_t *)cupsArrayFirst(data.devices), - count = 0; + count = 0, completed = 0; device; device = (_cups_dnssd_device_t *)cupsArrayNext(data.devices)) { if (device->ref) count ++; + if (device->state == _CUPS_DNSSD_ACTIVE) + completed ++; + if (!device->ref && device->state == _CUPS_DNSSD_NEW) { DEBUG_printf(("1cupsEnumDests: Querying '%s'.", device->fullName)); @@ -1196,8 +1240,11 @@ cupsEnumDests( } else if (device->ref && device->state == _CUPS_DNSSD_PENDING) { + completed ++; + if ((device->type & mask) == type) { + DEBUG_printf(("1cupsEnumDests: Add callback for \"%s\".", device->dest.name)); if (!(*cb)(user_data, CUPS_DEST_FLAGS_NONE, &device->dest)) { remaining = -1; @@ -1208,6 +1255,9 @@ cupsEnumDests( device->state = _CUPS_DNSSD_ACTIVE; } } + + if (completed == cupsArrayCount(data.devices)) + break; } cupsArrayDelete(data.devices); @@ -2964,8 +3014,9 @@ cups_dnssd_get_device( { _cups_dnssd_device_t key, /* Search key */ *device; /* Device */ - char fullName[kDNSServiceMaxDomainName]; + char fullName[kDNSServiceMaxDomainName], /* Full name for query */ + name[128]; /* Queue name */ DEBUG_printf(("5cups_dnssd_get_device(data=%p, serviceName=\"%s\", " @@ -2974,7 +3025,9 @@ cups_dnssd_get_device( * See if this is an existing device... */ - key.dest.name = (char *)serviceName; + cups_dnssd_queue_name(name, serviceName, sizeof(name)); + + key.dest.name = name; if ((device = cupsArrayFind(data->devices, &key)) != NULL) { @@ -3035,10 +3088,12 @@ cups_dnssd_get_device( replyDomain)); device = calloc(sizeof(_cups_dnssd_device_t), 1); - device->dest.name = _cupsStrAlloc(serviceName); + device->dest.name = _cupsStrAlloc(name); device->domain = _cupsStrAlloc(replyDomain); device->regtype = _cupsStrAlloc(regtype); + device->dest.num_options = cupsAddOption("printer-info", serviceName, 0, &device->dest.options); + cupsArrayAdd(data->devices, device); } @@ -3047,11 +3102,9 @@ cups_dnssd_get_device( */ # ifdef HAVE_DNSSD - DNSServiceConstructFullName(fullName, device->dest.name, device->regtype, - device->domain); + DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain); # else /* HAVE_AVAHI */ - avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName, - regtype, replyDomain); + avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName, regtype, replyDomain); # endif /* HAVE_DNSSD */ _cupsStrFree(device->fullName); @@ -3070,6 +3123,8 @@ cups_dnssd_get_device( if (device->state == _CUPS_DNSSD_ACTIVE) { + DEBUG_printf(("6cups_dnssd_get_device: Remove callback for \"%s\".", device->dest.name)); + (*data->cb)(data->user_data, CUPS_DEST_FLAGS_REMOVED, &device->dest); device->state = _CUPS_DNSSD_NEW; } @@ -3128,7 +3183,10 @@ cups_dnssd_local_cb( } if (device->state == _CUPS_DNSSD_ACTIVE) + { + DEBUG_printf(("6cups_dnssd_local_cb: Remove callback for \"%s\".", device->dest.name)); (*data->cb)(data->user_data, CUPS_DEST_FLAGS_REMOVED, &device->dest); + } device->state = _CUPS_DNSSD_LOCAL; } @@ -3214,7 +3272,8 @@ cups_dnssd_query_cb( # endif /* HAVE_DNSSD */ _cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context; /* Enumeration data */ - char name[1024], /* Service name */ + char serviceName[256],/* Service name */ + name[128], /* Queue name */ *ptr; /* Pointer into string */ _cups_dnssd_device_t dkey, /* Search key */ *device; /* Device */ @@ -3255,14 +3314,16 @@ cups_dnssd_query_cb( * Lookup the service in the devices array. */ - dkey.dest.name = name; - - cups_dnssd_unquote(name, fullName, sizeof(name)); + cups_dnssd_unquote(serviceName, fullName, sizeof(serviceName)); - if ((ptr = strstr(name, "._")) != NULL) + if ((ptr = strstr(serviceName, "._")) != NULL) *ptr = '\0'; - if ((device = cupsArrayFind(data->devices, &dkey)) != NULL) + cups_dnssd_queue_name(name, serviceName, sizeof(name)); + + dkey.dest.name = name; + + if ((device = cupsArrayFind(data->devices, &dkey)) != NULL && device->state == _CUPS_DNSSD_NEW) { /* * Found it, pull out the make and model from the TXT record and save it... @@ -3620,6 +3681,38 @@ cups_dnssd_unquote(char *dst, /* I - Destination buffer */ #endif /* HAVE_DNSSD */ +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) +/* + * 'cups_dnssd_queue_name()' - Create a local queue name based on the service name. + */ + +static void +cups_dnssd_queue_name( + char *name, /* I - Name buffer */ + const char *serviceName, /* I - Service name */ + size_t namesize) /* I - Size of name buffer */ +{ + const char *ptr; /* Pointer into serviceName */ + char *nameptr; /* Pointer into name */ + + + for (nameptr = name, ptr = serviceName; *ptr && nameptr < (name + namesize - 1); ptr ++) + { + /* + * Sanitize the printer name... + */ + + if (_cups_isalnum(*ptr)) + *nameptr++ = *ptr; + else if (nameptr == name || nameptr[-1] != '_') + *nameptr++ = '_'; + } + + *nameptr = '\0'; +} +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + + /* * 'cups_find_dest()' - Find a destination using a binary search. */ ++++++ 0002-Save-work-on-Avahi-code.patch ++++++
From 657c5b5f91e6d5120c4ad7b118cf9098dd27f03d Mon Sep 17 00:00:00 2001 From: Michael R Sweet
Date: Thu, 20 Apr 2017 09:11:45 -0400 Subject: [PATCH] Save work on Avahi code
--- cups/dest.c | 64 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index 54f2a7f..c1a0913 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -85,6 +85,7 @@ typedef struct _cups_dnssd_data_s /* Enumeration data */ AvahiSimplePoll *simple_poll; /* Polling interface */ AvahiClient *client; /* Client information */ int got_data; /* Did we get data? */ + int browsers; /* How many browsers are running? */ # endif /* HAVE_DNSSD */ cups_dest_cb_t cb; /* Callback */ void *user_data; /* User data pointer */ @@ -102,7 +103,6 @@ typedef struct _cups_dnssd_device_s /* Enumerated device */ AvahiRecordBrowser *ref; /* Browser for query */ # endif /* HAVE_DNSSD */ char *fullName, /* Full name */ -// *serviceName, /* Service name */ *regtype, /* Registration type */ *domain; /* Domain name */ cups_ptype_t type; /* Device registration type */ @@ -1021,12 +1021,15 @@ cupsEnumDests( i > 0 && (!cancel || !*cancel); i --, dest ++) { +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) const char *device_uri; /* Device URI */ +#endif /* HAVE_DNSSD || HAVE_AVAHI */ if (!(*cb)(user_data, i > 1 ? CUPS_DEST_FLAGS_MORE : CUPS_DEST_FLAGS_NONE, dest)) break; +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (!dest->instance && (device_uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL && !strncmp(device_uri, "dnssd://", 8)) { /* @@ -1058,13 +1061,17 @@ cupsEnumDests( } } } +#endif /* HAVE_DNSSD || HAVE_AVAHI */ } cupsFreeDests(num_dests, dests); if (i > 0 || msec == 0) { +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) cupsArrayDelete(data.devices); +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + return (1); } @@ -1122,10 +1129,12 @@ cupsEnumDests( return (1); } + data.browsers ++; ipp_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, cups_dnssd_browse_cb, &data); # ifdef HAVE_SSL + data.browsers ++; ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, 0, cups_dnssd_browse_cb, &data); @@ -1166,7 +1175,7 @@ cupsEnumDests( # else /* HAVE_AVAHI */ data.got_data = 0; - if ((error = avahi_simple_poll_iterate(data.simple_poll, 500)) > 0) + if ((error = avahi_simple_poll_iterate(data.simple_poll, 1000)) > 0) { /* * We've been told to exit the loop. Perhaps the connection to @@ -1176,6 +1185,7 @@ cupsEnumDests( break; } + DEBUG_printf(("1cupsEnumDests: got_data=%d", data.got_data)); # endif /* HAVE_DNSSD */ remaining -= 500; @@ -1227,14 +1237,14 @@ cupsEnumDests( cups_dnssd_query_cb, &data)) != NULL) { + DEBUG_printf(("1cupsEnumDests: browser ref=%p", device->ref)); count ++; } else { device->state = _CUPS_DNSSD_ERROR; - DEBUG_printf(("1cupsEnumDests: Query failed: %s", - avahi_strerror(avahi_client_errno(data.client)))); + DEBUG_printf(("1cupsEnumDests: Query failed: %s", avahi_strerror(avahi_client_errno(data.client)))); } # endif /* HAVE_DNSSD */ } @@ -1256,8 +1266,17 @@ cupsEnumDests( } } +# ifdef HAVE_AVAHI + DEBUG_printf(("1cupsEnumDests: browsers=%d, completed=%d, count=%d, devices count=%d", data.browsers, completed, count, cupsArrayCount(data.devices))); + + if (data.browsers == 0 && completed == cupsArrayCount(data.devices)) + break; +# else + DEBUG_printf(("1cupsEnumDests: completed=%d, count=%d, devices count=%d", completed, count, cupsArrayCount(data.devices))); + if (completed == cupsArrayCount(data.devices)) break; +# endif /* HAVE_AVAHI */ } cupsArrayDelete(data.devices); @@ -2889,11 +2908,12 @@ cups_dnssd_browse_cb( (void)protocol; (void)context; + DEBUG_printf(("cups_dnssd_browse_cb(..., name=\"%s\", type=\"%s\", domain=\"%s\", ...);", name, type, domain)); + switch (event) { case AVAHI_BROWSER_FAILURE: - DEBUG_printf(("cups_dnssd_browse_cb: %s", - avahi_strerror(avahi_client_errno(client)))); + DEBUG_printf(("cups_dnssd_browse_cb: %s", avahi_strerror(avahi_client_errno(client)))); avahi_simple_poll_quit(data->simple_poll); break; @@ -2908,8 +2928,7 @@ cups_dnssd_browse_cb( * This comes from the local machine so ignore it. */ - DEBUG_printf(("cups_dnssd_browse_cb: Ignoring local service \"%s\".", - name)); + DEBUG_printf(("cups_dnssd_browse_cb: Ignoring local service \"%s\".", name)); } else { @@ -2921,9 +2940,13 @@ cups_dnssd_browse_cb( } break; - case AVAHI_BROWSER_REMOVE: - case AVAHI_BROWSER_ALL_FOR_NOW: - case AVAHI_BROWSER_CACHE_EXHAUSTED: + case AVAHI_BROWSER_REMOVE : + case AVAHI_BROWSER_CACHE_EXHAUSTED : + break; + + case AVAHI_BROWSER_ALL_FOR_NOW : + DEBUG_puts("cups_dnssd_browse_cb: ALL_FOR_NOW"); + data->browsers --; break; } } @@ -2945,6 +2968,8 @@ cups_dnssd_client_cb( (void)client; + DEBUG_printf(("cups_dnssd_client_cb(client=%p, state=%d, context=%p)", client, state, context)); + /* * If the connection drops, quit. */ @@ -3214,16 +3239,22 @@ cups_dnssd_poll_cb( int val; /* Return value */ + DEBUG_printf(("cups_dnssd_poll_cb(pollfds=%p, num_pollfds=%d, timeout=%d, context=%p)", pollfds, num_pollfds, timeout, context)); + (void)timeout; - val = poll(pollfds, num_pollfds, 250); + val = poll(pollfds, num_pollfds, 500); + + DEBUG_printf(("cups_dnssd_poll_cb: poll() returned %d", val)); if (val < 0) { DEBUG_printf(("cups_dnssd_poll_cb: %s", strerror(errno))); } else if (val > 0) + { data->got_data = 1; + } return (val); } @@ -3290,11 +3321,7 @@ cups_dnssd_query_cb( return; # else /* HAVE_AVAHI */ - DEBUG_printf(("5cups_dnssd_query_cb(browser=%p, interfaceIndex=%d, " - "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, " - "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)", - browser, interfaceIndex, protocol, event, fullName, rrclass, - rrtype, rdata, (unsigned)rdlen, flags, context)); + DEBUG_printf(("cups_dnssd_query_cb(browser=%p, interfaceIndex=%d, protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)", browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context)); /* * Only process "add" data... @@ -3303,8 +3330,7 @@ cups_dnssd_query_cb( if (event != AVAHI_BROWSER_NEW) { if (event == AVAHI_BROWSER_FAILURE) - DEBUG_printf(("cups_dnssd_query_cb: %s", - avahi_strerror(avahi_client_errno(client)))); + DEBUG_printf(("cups_dnssd_query_cb: %s", avahi_strerror(avahi_client_errno(client)))); return; } ++++++ 0003-Avahi-fixes-for-cupsEnumDests.patch ++++++
From 3fae3b337df0be1a766857be741173d8a9915da7 Mon Sep 17 00:00:00 2001 From: Michael R Sweet
Date: Thu, 20 Apr 2017 10:12:40 -0400 Subject: [PATCH] Avahi fixes for cupsEnumDests (Issue #4989)
Also fix timeouts to track elapsed time so the timeout is more accurate. --- cups/dest.c | 70 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/cups/dest.c b/cups/dest.c index c1a0913..48758bf 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -60,6 +60,10 @@ # define kUseLastPrinter CFSTR("UseLastPrinter") #endif /* __APPLE__ */ +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) +# define _CUPS_DNSSD_MAXTIME 500 /* Milliseconds for maximum quantum of time */ +#endif /* HAVE_DNSSD || HAVE_AVAHI */ + /* * Types... @@ -211,6 +215,7 @@ static int cups_dnssd_resolve_cb(void *context); static void cups_dnssd_unquote(char *dst, const char *src, size_t dstsize); #endif /* HAVE_DNSSD || HAVE_AVAHI */ +static int cups_elapsed(struct timeval *t); static int cups_find_dest(const char *name, const char *instance, int num_dests, cups_dest_t *dests, int prev, int *rdiff); @@ -942,6 +947,7 @@ cupsEnumDests( int count, /* Number of queries started */ completed, /* Number of completed queries */ remaining; /* Remainder of timeout */ + struct timeval curtime; /* Current time */ _cups_dnssd_data_t data; /* Data for callback */ _cups_dnssd_device_t *device; /* Current device */ # ifdef HAVE_DNSSD @@ -1129,15 +1135,12 @@ cupsEnumDests( return (1); } - data.browsers ++; - ipp_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, - 0, cups_dnssd_browse_cb, &data); + data.browsers = 1; + ipp_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, cups_dnssd_browse_cb, &data); + # ifdef HAVE_SSL data.browsers ++; - ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, - 0, cups_dnssd_browse_cb, &data); + ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, 0, cups_dnssd_browse_cb, &data); # endif /* HAVE_SSL */ # endif /* HAVE_DNSSD */ @@ -1152,19 +1155,23 @@ cupsEnumDests( * Check for input... */ + DEBUG_printf(("1cupsEnumDests: remaining=%d", remaining)); + + cups_elapsed(&curtime); + # ifdef HAVE_DNSSD # ifdef HAVE_POLL pfd.fd = main_fd; pfd.events = POLLIN; - nfds = poll(&pfd, 1, remaining > 500 ? 500 : remaining); + nfds = poll(&pfd, 1, remaining > _CUPS_DNSSD_MAXTIME ? _CUPS_DNSSD_MAXTIME : remaining); # else FD_ZERO(&input); FD_SET(main_fd, &input); timeout.tv_sec = 0; - timeout.tv_usec = remaining > 500 ? 500000 : remaining * 1000; + timeout.tv_usec = 1000 * (remaining > _CUPS_DNSSD_MAXTIME ? _CUPS_DNSSD_MAXTIME : remaining); nfds = select(main_fd + 1, &input, NULL, NULL, &timeout); # endif /* HAVE_POLL */ @@ -1175,7 +1182,7 @@ cupsEnumDests( # else /* HAVE_AVAHI */ data.got_data = 0; - if ((error = avahi_simple_poll_iterate(data.simple_poll, 1000)) > 0) + if ((error = avahi_simple_poll_iterate(data.simple_poll, _CUPS_DNSSD_MAXTIME)) > 0) { /* * We've been told to exit the loop. Perhaps the connection to @@ -1188,7 +1195,7 @@ cupsEnumDests( DEBUG_printf(("1cupsEnumDests: got_data=%d", data.got_data)); # endif /* HAVE_DNSSD */ - remaining -= 500; + remaining -= cups_elapsed(&curtime); for (device = (_cups_dnssd_device_t *)cupsArrayFirst(data.devices), count = 0, completed = 0; @@ -1227,17 +1234,9 @@ cupsEnumDests( } # else /* HAVE_AVAHI */ - if ((device->ref = avahi_record_browser_new(data.client, - AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, - device->fullName, - AVAHI_DNS_CLASS_IN, - AVAHI_DNS_TYPE_TXT, - 0, - cups_dnssd_query_cb, - &data)) != NULL) + if ((device->ref = avahi_record_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, device->fullName, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, cups_dnssd_query_cb, &data)) != NULL) { - DEBUG_printf(("1cupsEnumDests: browser ref=%p", device->ref)); + DEBUG_printf(("1cupsEnumDests: Query ref=%p", device->ref)); count ++; } else @@ -1252,6 +1251,8 @@ cupsEnumDests( { completed ++; + DEBUG_printf(("1cupsEnumDests: Query for \"%s\" is complete.", device->fullName)); + if ((device->type & mask) == type) { DEBUG_printf(("1cupsEnumDests: Add callback for \"%s\".", device->dest.name)); @@ -1267,12 +1268,12 @@ cupsEnumDests( } # ifdef HAVE_AVAHI - DEBUG_printf(("1cupsEnumDests: browsers=%d, completed=%d, count=%d, devices count=%d", data.browsers, completed, count, cupsArrayCount(data.devices))); + DEBUG_printf(("1cupsEnumDests: remaining=%d, browsers=%d, completed=%d, count=%d, devices count=%d", remaining, data.browsers, completed, count, cupsArrayCount(data.devices))); if (data.browsers == 0 && completed == cupsArrayCount(data.devices)) break; # else - DEBUG_printf(("1cupsEnumDests: completed=%d, count=%d, devices count=%d", completed, count, cupsArrayCount(data.devices))); + DEBUG_printf(("1cupsEnumDests: remaining=%d, completed=%d, count=%d, devices count=%d", remaining, completed, count, cupsArrayCount(data.devices))); if (completed == cupsArrayCount(data.devices)) break; @@ -3243,7 +3244,7 @@ cups_dnssd_poll_cb( (void)timeout; - val = poll(pollfds, num_pollfds, 500); + val = poll(pollfds, num_pollfds, _CUPS_DNSSD_MAXTIME); DEBUG_printf(("cups_dnssd_poll_cb: poll() returned %d", val)); @@ -3740,6 +3741,27 @@ cups_dnssd_queue_name( /* + * 'cups_elapsed()' - Return the elapsed time in milliseconds. + */ + +static int /* O - Elapsed time in milliseconds */ +cups_elapsed(struct timeval *t) /* IO - Previous time */ +{ + int msecs; /* Milliseconds */ + struct timeval nt; /* New time */ + + + gettimeofday(&nt, NULL); + + msecs = 1000 * (nt.tv_sec - t->tv_sec) + (nt.tv_usec - t->tv_usec) / 1000; + + *t = nt; + + return (msecs); +} + + +/* * 'cups_find_dest()' - Find a destination using a binary search. */