From: Michael R Sweet Date: Fri, 4 Apr 2025 16:20:59 +0000 (-0400) Subject: Fix "unreliable" discovery with ippfind as used by driverless backend (Issue #1211) X-Git-Tag: v2.4.12~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8304d6b34778331a680a7abfce0529e65e3fd962;p=thirdparty%2Fcups.git Fix "unreliable" discovery with ippfind as used by driverless backend (Issue #1211) - Export _cupsGetClock private API. - Use _cupsGetClock in ippfind. - Drop "avahi_have_data" and adopt CUPS 2.5/3.0 processing strategy. --- diff --git a/CHANGES.md b/CHANGES.md index 640ddbfc67..027db1e723 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ Changes in CUPS v2.4.12 (YYYY-MM-DD) - Fixed attributes returned by the Create-Xxx-Subscriptions requests (Issue #1204) - Fixed `ippDateToTime` when using a non GMT/UTC timezone (Issue #1208) +- Fixed DNS-SD discovery with `ippfind` (Issue #1211) Changes in CUPS v2.4.11 (2024-09-30) diff --git a/cups/libcups2.def b/cups/libcups2.def index 268522259d..da75298b3c 100644 --- a/cups/libcups2.def +++ b/cups/libcups2.def @@ -16,6 +16,7 @@ _cupsEncodeOption _cupsEncodingName _cupsFilePeekAhead _cupsGet1284Values +_cupsGetClock _cupsGetDestResource _cupsGetDests _cupsGetPassword diff --git a/tools/ippfind.c b/tools/ippfind.c index 2893cd1701..69fa51e378 100644 --- a/tools/ippfind.c +++ b/tools/ippfind.c @@ -3,7 +3,7 @@ * commands such as IPP and Bonjour conformance tests. This tool is * inspired by the UNIX "find" command, thus its name. * - * Copyright © 2020-2024 by OpenPrinting. + * Copyright © 2020-2025 by OpenPrinting. * Copyright © 2020 by the IEEE-ISTO Printer Working Group * Copyright © 2008-2018 by Apple Inc. * @@ -11,10 +11,6 @@ * information. */ -/* - * Include necessary headers. - */ - #define _CUPS_NO_DEPRECATED #include #ifdef _WIN32 @@ -129,7 +125,6 @@ typedef struct ippfind_srv_s /* Service information */ static DNSServiceRef dnssd_ref; /* Master service reference */ #elif defined(HAVE_AVAHI) static AvahiClient *avahi_client = NULL;/* Client information */ -static int avahi_got_data = 0; /* Got data from poll? */ static AvahiSimplePoll *avahi_poll = NULL; /* Poll information */ #endif /* HAVE_MDNSRESPONDER */ @@ -139,6 +134,7 @@ static int address_family = AF_UNSPEC; static int bonjour_error = 0; /* Error browsing/resolving? */ static double bonjour_timeout = 1.0; /* Timeout in seconds */ static int ipp_version = 20; /* IPP version for LIST */ +static double last_update = 0.0; /* Last update time */ /* @@ -170,7 +166,6 @@ static int eval_expr(ippfind_srv_t *service, static int exec_program(ippfind_srv_t *service, int num_args, char **args); static ippfind_srv_t *get_service(cups_array_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4); -static double get_time(void); static int list_service(ippfind_srv_t *service); static ippfind_expr_t *new_expr(ippfind_op_t op, int invert, const char *value, const char *regex, @@ -1308,14 +1303,12 @@ main(int argc, /* I - Number of command-line args */ */ if (bonjour_timeout > 1.0) - endtime = get_time() + bonjour_timeout; + endtime = _cupsGetClock() + bonjour_timeout; else - endtime = get_time() + 300.0; + endtime = _cupsGetClock() + 300.0; - while (get_time() < endtime) + while (_cupsGetClock() < endtime) { - int process = 0; /* Process services? */ - #ifdef HAVE_MDNSRESPONDER int fd = DNSServiceRefSockFD(dnssd_ref); /* File descriptor for DNS-SD */ @@ -1337,18 +1330,8 @@ main(int argc, /* I - Number of command-line args */ DNSServiceProcessResult(dnssd_ref); } - else - { - /* - * Time to process services... - */ - - process = 1; - } #elif defined(HAVE_AVAHI) - avahi_got_data = 0; - if (avahi_simple_poll_iterate(avahi_poll, 500) > 0) { /* @@ -1359,108 +1342,103 @@ main(int argc, /* I - Number of command-line args */ return (IPPFIND_EXIT_BONJOUR); } - if (!avahi_got_data) - { - /* - * Time to process services... - */ - - process = 1; - } #endif /* HAVE_MDNSRESPONDER */ - if (process) - { - /* - * Process any services that we have found... - */ + /* + * Process any services that we have found... + */ - int active = 0, /* Number of active resolves */ - processed = 0; /* Number of processed services */ + int active = 0, /* Number of active resolves */ + processed = 0; /* Number of processed services */ - for (service = (ippfind_srv_t *)cupsArrayFirst(services); - service; - service = (ippfind_srv_t *)cupsArrayNext(services)) - { - if (service->is_processed) - processed ++; + for (service = (ippfind_srv_t *)cupsArrayFirst(services); + service; + service = (ippfind_srv_t *)cupsArrayNext(services)) + { + if (service->is_processed) + processed ++; - if (!service->ref && !service->is_resolved) - { - /* - * Found a service, now resolve it (but limit to 50 active resolves...) - */ + if (!service->ref && !service->is_resolved) + { + /* + * Found a service, now resolve it (but limit to 50 active resolves...) + */ - if (active < 50) - { + if (active < 50) + { #ifdef HAVE_MDNSRESPONDER - service->ref = dnssd_ref; - err = DNSServiceResolve(&(service->ref), - kDNSServiceFlagsShareConnection, 0, - service->name, service->regtype, - service->domain, resolve_callback, - service); + service->ref = dnssd_ref; + err = DNSServiceResolve(&(service->ref), + kDNSServiceFlagsShareConnection, 0, + service->name, service->regtype, + service->domain, resolve_callback, + service); #elif defined(HAVE_AVAHI) - service->ref = avahi_service_resolver_new(avahi_client, - AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, - service->name, - service->regtype, - service->domain, - AVAHI_PROTO_UNSPEC, 0, - resolve_callback, - service); - if (service->ref) - err = 0; - else - err = avahi_client_errno(avahi_client); + service->ref = avahi_service_resolver_new(avahi_client, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + service->name, + service->regtype, + service->domain, + AVAHI_PROTO_UNSPEC, 0, + resolve_callback, + service); + if (service->ref) + err = 0; + else + err = avahi_client_errno(avahi_client); #endif /* HAVE_MDNSRESPONDER */ - if (err) - { - _cupsLangPrintf(stderr, - _("ippfind: Unable to browse or resolve: %s"), - dnssd_error_string(err)); - return (IPPFIND_EXIT_BONJOUR); - } + if (err) + { + _cupsLangPrintf(stderr, + _("ippfind: Unable to browse or resolve: %s"), + dnssd_error_string(err)); + return (IPPFIND_EXIT_BONJOUR); + } - active ++; - } - } - else if (service->is_resolved && !service->is_processed) - { - /* - * Resolved, not process this service against the expressions... - */ + active ++; + } + } + else if (service->is_resolved && !service->is_processed) + { + /* + * Resolved, not process this service against the expressions... + */ - if (service->ref) - { + if (service->ref) + { #ifdef HAVE_MDNSRESPONDER - DNSServiceRefDeallocate(service->ref); + DNSServiceRefDeallocate(service->ref); #else - avahi_service_resolver_free(service->ref); + avahi_service_resolver_free(service->ref); #endif /* HAVE_MDNSRESPONDER */ - service->ref = NULL; - } + service->ref = NULL; + } - if (eval_expr(service, expressions)) - status = IPPFIND_EXIT_TRUE; + if (eval_expr(service, expressions)) + status = IPPFIND_EXIT_TRUE; - service->is_processed = 1; - } - else if (service->ref) - active ++; + service->is_processed = 1; } + else if (service->ref) + active ++; + } - /* - * If we have processed all services we have discovered, then we are done. - */ + /* + * If we have processed all services we have discovered, then we are done. + */ - if (processed == cupsArrayCount(services) && bonjour_timeout <= 1.0) - break; - } + if (processed > 0 && (processed == cupsArrayCount(services) || (_cupsGetClock() - last_update) >= 2.5) && bonjour_timeout <= 1.0) + break; + + /* + * Give the browsers/resolvers some time... + */ + + usleep(250000); } if (bonjour_error) @@ -1490,6 +1468,8 @@ browse_callback( * Only process "add" data... */ + last_update = _cupsGetClock(); + (void)sdRef; (void)interfaceIndex; @@ -1522,6 +1502,8 @@ browse_local_callback( ippfind_srv_t *service; /* Service */ + last_update = _cupsGetClock(); + /* * Only process "add" data... */ @@ -1565,6 +1547,8 @@ browse_callback( ippfind_srv_t *service; /* Service information */ + last_update = _cupsGetClock(); + (void)interface; (void)protocol; (void)context; @@ -2190,31 +2174,6 @@ get_service(cups_array_t *services, /* I - Service array */ } -/* - * 'get_time()' - Get the current time-of-day in seconds. - */ - -static double -get_time(void) -{ -#ifdef _WIN32 - struct _timeb curtime; /* Current Windows time */ - - _ftime(&curtime); - - return (curtime.time + 0.001 * curtime.millitm); - -#else - struct timeval curtime; /* Current UNIX time */ - - if (gettimeofday(&curtime, NULL)) - return (0.0); - else - return (curtime.tv_sec + 0.000001 * curtime.tv_usec); -#endif /* _WIN32 */ -} - - /* * 'list_service()' - List the contents of a service. */ @@ -2517,7 +2476,7 @@ new_expr(ippfind_op_t op, /* I - Operation */ * * Note: This function is needed because avahi_simple_poll_iterate is broken * and always uses a timeout of 0 (!) milliseconds. - * (Avahi Ticket #364) + * (Avahi Github issue #127) */ static int /* O - Number of file descriptors matching */ @@ -2527,18 +2486,10 @@ poll_callback( int timeout, /* I - Timeout in milliseconds (unused) */ void *context) /* I - User data (unused) */ { - int val; /* Return value */ - - (void)timeout; (void)context; - val = poll(pollfds, num_pollfds, 500); - - if (val > 0) - avahi_got_data = 1; - - return (val); + return (poll(pollfds, num_pollfds, 500)); } #endif /* HAVE_AVAHI */ @@ -2569,6 +2520,8 @@ resolve_callback( /* Service */ + last_update = _cupsGetClock(); + /* * Only process "add" data... */ @@ -2650,6 +2603,8 @@ resolve_callback( AvahiStringList *current; /* Current TXT key/value pair */ + last_update = _cupsGetClock(); + (void)address; if (event != AVAHI_RESOLVER_FOUND)