From 31b8620fa3f4cf804009c5643063d456d87b569185e62982ebdbf1c6429e7929 Mon Sep 17 00:00:00 2001 From: Johannes Meixner Date: Wed, 12 Apr 2017 14:14:55 +0000 Subject: [PATCH 1/2] Accepting request 487560 from home:alarrosa:branches:Printing - 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) OBS-URL: https://build.opensuse.org/request/show/487560 OBS-URL: https://build.opensuse.org/package/show/Printing/cups?expand=0&rev=324 --- ....3-cupsEnumDests-react-to-all-for-now.diff | 53 +++++++++++++++++++ cups.changes | 10 ++++ cups.spec | 14 +++-- 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff diff --git a/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff b/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff new file mode 100644 index 0000000..e394a04 --- /dev/null +++ b/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff @@ -0,0 +1,53 @@ +Index: cups-2.1.3/cups/dest.c +=================================================================== +--- cups-2.1.3.orig/cups/dest.c ++++ cups-2.1.3/cups/dest.c +@@ -84,6 +84,7 @@ typedef struct _cups_dnssd_data_s /* Enu + AvahiSimplePoll *simple_poll; /* Polling interface */ + AvahiClient *client; /* Client information */ + int got_data; /* Did we get data? */ ++ int remaining_browsers; /* Remaining avahi browsers running */ + # endif /* HAVE_DNSSD */ + cups_dest_cb_t cb; /* Callback */ + void *user_data; /* User data pointer */ +@@ -920,6 +921,7 @@ cupsEnumDests( + 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); ++ data.remaining_browsers = 1; + + # ifdef HAVE_DNSSD + if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError) +@@ -977,6 +979,7 @@ cupsEnumDests( + ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, + 0, cups_dnssd_browse_cb, &data); ++ data.remaining_browsers++; + # endif /* HAVE_SSL */ + # endif /* HAVE_DNSSD */ + +@@ -985,7 +988,7 @@ cupsEnumDests( + else + remaining = msec; + +- while (remaining > 0 && (!cancel || !*cancel)) ++ while (data.remaining_browsers > 0 && remaining > 0 && (!cancel || !*cancel)) + { + /* + * Check for input... +@@ -2762,10 +2765,13 @@ cups_dnssd_browse_cb( + } + break; + +- case AVAHI_BROWSER_REMOVE: + case AVAHI_BROWSER_ALL_FOR_NOW: ++ data->remaining_browsers--; ++ break; ++ ++ case AVAHI_BROWSER_REMOVE: + case AVAHI_BROWSER_CACHE_EXHAUSTED: +- break; ++ break; + } + } + diff --git a/cups.changes b/cups.changes index e4fec56..4ea25b2 100644 --- a/cups.changes +++ b/cups.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +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) + ------------------------------------------------------------------- Wed Mar 29 13:41:15 UTC 2017 - kukuk@suse.com diff --git a/cups.spec b/cups.spec index 89b5759..c45400c 100644 --- a/cups.spec +++ b/cups.spec @@ -45,6 +45,8 @@ Patch10: cups-2.1.0-choose-uri-template.patch 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 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff bsc#955432 -- React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +Patch13: cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff # 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 +135,9 @@ browsing". This is now handled by cups-browsed service. %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 +159,8 @@ browsing". This is now handled by cups-browsed service. %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 +170,6 @@ Summary: CUPS Client Programs # 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 +192,13 @@ browsing". This is now handled by cups-browsed service. %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 +260,8 @@ browsing". This is now handled by cups-browsed service. %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 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +%patch13 -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 From 6f9127aa903cfc1e4cc273ad376ca879775a76a8a1d726ec83456c441a254615 Mon Sep 17 00:00:00 2001 From: Johannes Meixner Date: Fri, 21 Apr 2017 08:44:45 +0000 Subject: [PATCH 2/2] Accepting request 489647 from home:alarrosa:branches:Printing - 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. OBS-URL: https://build.opensuse.org/request/show/489647 OBS-URL: https://build.opensuse.org/package/show/Printing/cups?expand=0&rev=326 --- ...mplementation-to-return-early-if-all.patch | 366 ++++++++++++++++++ 0002-Save-work-on-Avahi-code.patch | 226 +++++++++++ 0003-Avahi-fixes-for-cupsEnumDests.patch | 186 +++++++++ ....3-cupsEnumDests-react-to-all-for-now.diff | 53 --- cups.changes | 12 + cups.spec | 14 +- 6 files changed, 801 insertions(+), 56 deletions(-) create mode 100644 0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch create mode 100644 0002-Save-work-on-Avahi-code.patch create mode 100644 0003-Avahi-fixes-for-cupsEnumDests.patch delete mode 100644 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff diff --git a/0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch b/0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch new file mode 100644 index 0000000..d2e8441 --- /dev/null +++ b/0001-Update-cupsEnumDests-implementation-to-return-early-if-all.patch @@ -0,0 +1,366 @@ +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 + 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. + */ diff --git a/0002-Save-work-on-Avahi-code.patch b/0002-Save-work-on-Avahi-code.patch new file mode 100644 index 0000000..14a20cb --- /dev/null +++ b/0002-Save-work-on-Avahi-code.patch @@ -0,0 +1,226 @@ +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; + } diff --git a/0003-Avahi-fixes-for-cupsEnumDests.patch b/0003-Avahi-fixes-for-cupsEnumDests.patch new file mode 100644 index 0000000..08f8b7e --- /dev/null +++ b/0003-Avahi-fixes-for-cupsEnumDests.patch @@ -0,0 +1,186 @@ +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. + */ + diff --git a/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff b/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff deleted file mode 100644 index e394a04..0000000 --- a/cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff +++ /dev/null @@ -1,53 +0,0 @@ -Index: cups-2.1.3/cups/dest.c -=================================================================== ---- cups-2.1.3.orig/cups/dest.c -+++ cups-2.1.3/cups/dest.c -@@ -84,6 +84,7 @@ typedef struct _cups_dnssd_data_s /* Enu - AvahiSimplePoll *simple_poll; /* Polling interface */ - AvahiClient *client; /* Client information */ - int got_data; /* Did we get data? */ -+ int remaining_browsers; /* Remaining avahi browsers running */ - # endif /* HAVE_DNSSD */ - cups_dest_cb_t cb; /* Callback */ - void *user_data; /* User data pointer */ -@@ -920,6 +921,7 @@ cupsEnumDests( - 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); -+ data.remaining_browsers = 1; - - # ifdef HAVE_DNSSD - if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError) -@@ -977,6 +979,7 @@ cupsEnumDests( - ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, - 0, cups_dnssd_browse_cb, &data); -+ data.remaining_browsers++; - # endif /* HAVE_SSL */ - # endif /* HAVE_DNSSD */ - -@@ -985,7 +988,7 @@ cupsEnumDests( - else - remaining = msec; - -- while (remaining > 0 && (!cancel || !*cancel)) -+ while (data.remaining_browsers > 0 && remaining > 0 && (!cancel || !*cancel)) - { - /* - * Check for input... -@@ -2762,10 +2765,13 @@ cups_dnssd_browse_cb( - } - break; - -- case AVAHI_BROWSER_REMOVE: - case AVAHI_BROWSER_ALL_FOR_NOW: -+ data->remaining_browsers--; -+ break; -+ -+ case AVAHI_BROWSER_REMOVE: - case AVAHI_BROWSER_CACHE_EXHAUSTED: -- break; -+ break; - } - } - diff --git a/cups.changes b/cups.changes index 4ea25b2..14ff878 100644 --- a/cups.changes +++ b/cups.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +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 diff --git a/cups.spec b/cups.spec index c45400c..059677b 100644 --- a/cups.spec +++ b/cups.spec @@ -45,8 +45,12 @@ Patch10: cups-2.1.0-choose-uri-template.patch 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 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff bsc#955432 -- React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay -Patch13: cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff +# 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 @@ -260,8 +264,12 @@ browsing". This is now handled by cups-browsed service. %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 cups-2.1.3-cupsEnumDests-react-to-all-for-now.diff React properly to avahi's ALL_FOR_NOW signal to reduce unneeded delay +# 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