]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Fix "unreliable" discovery with ippfind as used by driverless backend (Issue #1211)
authorMichael R Sweet <msweet@msweet.org>
Fri, 4 Apr 2025 16:20:59 +0000 (12:20 -0400)
committerMichael R Sweet <msweet@msweet.org>
Fri, 4 Apr 2025 16:20:59 +0000 (12:20 -0400)
- Export _cupsGetClock private API.
- Use _cupsGetClock in ippfind.
- Drop "avahi_have_data" and adopt CUPS 2.5/3.0 processing strategy.

CHANGES.md
cups/libcups2.def
tools/ippfind.c

index 640ddbfc671acfe6e7cc1801d58fd5f1ced19e68..027db1e723d64b1b40abc05fb9e547297eaf5880 100644 (file)
@@ -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)
index 268522259d21e178a68e606dee66a15982dbb333..da75298b3cb00aab479743319830e841a9720c0f 100644 (file)
@@ -16,6 +16,7 @@ _cupsEncodeOption
 _cupsEncodingName
 _cupsFilePeekAhead
 _cupsGet1284Values
+_cupsGetClock
 _cupsGetDestResource
 _cupsGetDests
 _cupsGetPassword
index 2893cd1701f6a27996c286fa9e6520e48fff49af..69fa51e3783d73980324c5ccc5e0b0cdb3a37c9e 100644 (file)
@@ -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.
  *
  * information.
  */
 
-/*
- * Include necessary headers.
- */
-
 #define _CUPS_NO_DEPRECATED
 #include <cups/cups-private.h>
 #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)