]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge Coverity fixes.
authorMichael R Sweet <msweet@msweet.org>
Wed, 22 May 2024 19:30:42 +0000 (15:30 -0400)
committerMichael R Sweet <msweet@msweet.org>
Wed, 22 May 2024 19:30:42 +0000 (15:30 -0400)
cups/debug.c
cups/dest.c
cups/dnssd.c
cups/string.c
cups/tls-gnutls.c
cups/tls-openssl.c

index 3143780cd3c206a6a170ec930348df361fe19bb5..8151cc896639a7d43354c63545502196b7819b5e 100644 (file)
@@ -82,6 +82,7 @@ void
 _cups_debug_printf(const char *format, /* I - Printf-style format string */
                    ...)                        /* I - Additional arguments as needed */
 {
+  int                  result = 0;     /* Filter result */
   va_list              ap;             /* Pointer to arguments */
   struct timeval       curtime;        /* Current time */
   char                 buffer[2048];   /* Output buffer */
@@ -94,8 +95,7 @@ _cups_debug_printf(const char *format,        /* I - Printf-style format string */
   */
 
   if (!debug_init)
-    _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"),
-                    getenv("CUPS_DEBUG_FILTER"), 0);
+    _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), getenv("CUPS_DEBUG_FILTER"), 0);
 
   if (_cups_debug_fd < 0)
     return;
@@ -112,17 +112,13 @@ _cups_debug_printf(const char *format,    /* I - Printf-style format string */
   if (level > _cups_debug_level)
     return;
 
+  cupsMutexLock(&debug_init_mutex);
   if (debug_filter)
-  {
-    int        result;                         /* Filter result */
-
-    cupsMutexLock(&debug_init_mutex);
     result = regexec(debug_filter, format, 0, NULL, 0);
-    cupsMutexUnlock(&debug_init_mutex);
+  cupsMutexUnlock(&debug_init_mutex);
 
-    if (result)
-      return;
-  }
+  if (result)
+    return;
 
  /*
   * Format the message...
@@ -166,6 +162,7 @@ _cups_debug_printf(const char *format,      /* I - Printf-style format string */
 void
 _cups_debug_puts(const char *s)                /* I - String to output */
 {
+  int                  result = 0;     /* Filter result */
   struct timeval       curtime;        /* Current time */
   char                 buffer[2048];   /* Output buffer */
   ssize_t              bytes;          /* Number of bytes in buffer */
@@ -177,8 +174,7 @@ _cups_debug_puts(const char *s)             /* I - String to output */
   */
 
   if (!debug_init)
-    _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"),
-                    getenv("CUPS_DEBUG_FILTER"), 0);
+    _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"), getenv("CUPS_DEBUG_FILTER"), 0);
 
   if (_cups_debug_fd < 0)
     return;
@@ -195,17 +191,13 @@ _cups_debug_puts(const char *s)           /* I - String to output */
   if (level > _cups_debug_level)
     return;
 
+  cupsMutexLock(&debug_init_mutex);
   if (debug_filter)
-  {
-    int        result;                         /* Filter result */
-
-    cupsMutexLock(&debug_init_mutex);
     result = regexec(debug_filter, s, 0, NULL, 0);
-    cupsMutexUnlock(&debug_init_mutex);
+  cupsMutexUnlock(&debug_init_mutex);
 
-    if (result)
-      return;
-  }
+  if (result)
+    return;
 
  /*
   * Format the message...
index 021caf7a5ab41262de6f8cf8d5b07cae6428cef0..8e0713f4ed9182e6afb861ba35d64d5348b66ff8 100644 (file)
@@ -2697,7 +2697,11 @@ cups_dest_query_cb(
 
   dkey.dest.name = name;
 
-  if ((device = cupsArrayFind(data->devices, &dkey)) != NULL && device->state == _CUPS_DNSSD_NEW)
+  cupsRWLockRead(&data->rwlock);
+  device = cupsArrayFind(data->devices, &dkey);
+  cupsRWUnlock(&data->rwlock);
+
+  if (device && device->state == _CUPS_DNSSD_NEW)
   {
     // Found it, pull out the make and model from the TXT record and save it...
     const uint8_t      *txt,           // Pointer into data
index ae042619d730176dbf2d2c1823af3a768337929e..f124c32afd3f2246511ac84f95f179c53a529ad0 100644 (file)
@@ -8,7 +8,6 @@
 //
 
 #include "cups-private.h"
-#include "debug-internal.h"
 #include "dnssd.h"
 
 #ifdef __APPLE__
@@ -209,6 +208,182 @@ cupsDNSSDAssembleFullName(
 }
 
 
+//
+// 'cupsDNSSDBrowseDelete()' - Cancel and delete a browse request.
+//
+
+void
+cupsDNSSDBrowseDelete(
+    cups_dnssd_browse_t *browse)       // I - Browse request
+{
+  if (browse)
+  {
+    cups_dnssd_t *dnssd = browse->dnssd;
+
+    DEBUG_puts("2cupsDNSSDBrowseDelete: Write locking rwlock.");
+    cupsRWLockWrite(&dnssd->rwlock);
+
+    cupsArrayRemove(dnssd->browses, browse);
+
+    DEBUG_puts("2cupsDNSSDBrowseDelete: Unlocking rwlock.");
+    cupsRWUnlock(&dnssd->rwlock);
+  }
+}
+
+
+//
+// 'cupsDNSSDBrowseGetContext()' - Get the DNS-SD context for the browse request.
+//
+
+cups_dnssd_t *                         // O - Context or `NULL`
+cupsDNSSDBrowseGetContext(
+    cups_dnssd_browse_t *browse)       // I - Browse request
+{
+  return (browse ? browse->dnssd : NULL);
+}
+
+
+//
+// 'cupsDNSSDBrowseNew()' - Create a new DNS-SD browse request.
+//
+// This function creates a new DNS-SD browse request for the specified service
+// types and optional domain and interface index.  The "types" argument can be a
+// single service type ("_ipp._tcp") or a service type and comma-delimited list
+// of sub-types ("_ipp._tcp,_print,_universal").
+//
+// Newly discovered services are reported using the required browse callback
+// function, with the "flags" argument set to `CUPS_DNSSD_FLAGS_ADD` for newly
+// discovered services, `CUPS_DNSSD_FLAGS_NONE` for removed services, or
+// `CUPS_DNSSD_FLAGS_ERROR` on an error:
+//
+// ```
+// void
+// browse_cb(
+//     cups_dnssd_browse_t *browse,
+//     void                *cb_data,
+//     cups_dnssd_flags_t  flags,
+//     uint32_t            if_index,
+//     const char          *name,
+//     const char          *regtype,
+//     const char          *domain)
+// {
+//     // Process added/removed service
+// }
+// ```
+//
+
+cups_dnssd_browse_t *                  // O - Browse request or `NULL` on error
+cupsDNSSDBrowseNew(
+    cups_dnssd_t           *dnssd,     // I - DNS-SD context
+    uint32_t               if_index,   // I - Interface index, `CUPS_DNSSD_IF_INDEX_ANY`, or `CUPS_DNSSD_IF_INDEX_LOCAL`
+    const char             *types,     // I - Service types
+    const char             *domain,    // I - Domain name or `NULL` for default
+    cups_dnssd_browse_cb_t browse_cb,  // I - Browse callback function
+    void                   *cb_data)   // I - Browse callback data
+{
+  cups_dnssd_browse_t  *browse;        // Browse request
+
+
+  // Range check input...
+  if (!dnssd || !types || !browse_cb)
+    return (NULL);
+
+  // Allocate memory for the browser...
+  if ((browse = (cups_dnssd_browse_t *)calloc(1, sizeof(cups_dnssd_browse_t))) == NULL)
+    return (NULL);
+
+  browse->dnssd   = dnssd;
+  browse->cb      = browse_cb;
+  browse->cb_data = cb_data;
+
+  DEBUG_puts("2cupsDNSSDBrowseNew: Write locking rwlock.");
+  cupsRWLockWrite(&dnssd->rwlock);
+
+  if (!dnssd->browses)
+  {
+    // Create an array of browsers...
+    if ((dnssd->browses = cupsArrayNew3(NULL, NULL, NULL, 0, NULL, (cups_afree_cb_t)delete_browse)) == NULL)
+    {
+      // Unable to create...
+      free(browse);
+      browse = NULL;
+      goto done;
+    }
+  }
+
+#ifdef HAVE_MDNSRESPONDER
+  DNSServiceErrorType error;           // Error, if any
+
+  browse->ref = dnssd->ref;
+  if ((error = DNSServiceBrowse(&browse->ref, kDNSServiceFlagsShareConnection, if_index, types, domain, (DNSServiceBrowseReply)mdns_browse_cb, browse)) != kDNSServiceErr_NoError)
+  {
+    report_error(dnssd, "Unable to create DNS-SD browse request: %s", mdns_strerror(error));
+    free(browse);
+    browse = NULL;
+    goto done;
+  }
+
+#elif _WIN32
+
+#else // HAVE_AVAHI
+  if (!dnssd->in_callback)
+  {
+    DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex.");
+    cupsMutexLock(&dnssd->mutex);
+  }
+
+  browse->num_browsers = 1;
+  browse->browsers[0]  = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, /*domain*/NULL, /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse);
+
+  if (!browse->browsers[0])
+  {
+    report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client)));
+    free(browse);
+    browse = NULL;
+
+    if (!dnssd->in_callback)
+    {
+      DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
+      cupsMutexUnlock(&dnssd->mutex);
+    }
+
+    goto done;
+  }
+
+  if (!domain && dnssd->num_domains > 0)
+  {
+    // Add browsers for all domains...
+    size_t     i;                      // Looping var
+
+    for (i = 0; i < dnssd->num_domains; i ++)
+    {
+      if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, dnssd->domains[i], /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL)
+        browse->num_browsers ++;
+    }
+  }
+
+  if (!dnssd->in_callback)
+  {
+    DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
+    cupsMutexUnlock(&dnssd->mutex);
+
+    avahi_simple_poll_wakeup(dnssd->poll);
+  }
+#endif // HAVE_MDNSRESPONDER
+
+  DEBUG_printf("2cupsDNSSDBrowseNew: Adding browse=%p", (void *)browse);
+  cupsArrayAdd(dnssd->browses, browse);
+
+  done:
+
+  DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking rwlock.");
+  cupsRWUnlock(&dnssd->rwlock);
+
+  return (browse);
+}
+
+
+
 //
 // 'cupsDNSSDCopyComputerName()' - Copy the current human-readable name for the system.
 //
@@ -377,127 +552,6 @@ cupsDNSSDDecodeTXT(
 }
 
 
-//
-// 'cupsDNSSDSeparateFullName()' - Separate a full service name into an instance
-//                                 name, registration type, and domain.
-//
-// This function separates a full service name such as
-// "Example\032Name._ipp._tcp.local.") into its instance name ("Example Name"),
-// registration type ("_ipp._tcp"), and domain ("local.").
-//
-
-bool                                   // O - `true` on success, `false` on error
-cupsDNSSDSeparateFullName(
-    const char *fullname,              // I - Full service name
-    char       *name,                  // I - Instance name buffer
-    size_t     namesize,               // I - Size of instance name buffer
-    char       *type,                  // I - Registration type buffer
-    size_t     typesize,               // I - Size of registration type buffer
-    char       *domain,                        // I - Domain name buffer
-    size_t     domainsize)             // I - Size of domain name buffer
-{
-  // Range check input..
-  if (!fullname || !name || !namesize || !type || !typesize || !domain || !domainsize)
-  {
-    if (name)
-      *name = '\0';
-    if (type)
-      *type = '\0';
-    if (domain)
-      *domain = '\0';
-
-    return (false);
-  }
-
-#if _WIN32 || defined(HAVE_MDNSRESPONDER)
-  bool ret = true;                     // Return value
-  char *ptr,                           // Pointer into name/type/domain
-       *end;                           // Pointer to end of name/type/domain
-
-  // Get the service name...
-  for (ptr = name, end = name + namesize - 1; *fullname; fullname ++)
-  {
-    if (*fullname == '.')
-    {
-      // Service type separator...
-      break;
-    }
-    else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
-    {
-      // Escaped character
-      if (ptr < end)
-        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
-      else
-        ret = false;
-
-      fullname += 3;
-    }
-    else if (ptr < end)
-      *ptr++ = *fullname;
-    else
-      ret = false;
-  }
-  *ptr = '\0';
-
-  if (*fullname)
-    fullname ++;
-
-  // Get the type...
-  for (ptr = type, end = type + typesize - 1; *fullname; fullname ++)
-  {
-    if (*fullname == '.' && fullname[1] != '_')
-    {
-      // Service type separator...
-      break;
-    }
-    else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
-    {
-      // Escaped character
-      if (ptr < end)
-        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
-      else
-        ret = false;
-
-      fullname += 3;
-    }
-    else if (ptr < end)
-      *ptr++ = *fullname;
-    else
-      ret = false;
-  }
-  *ptr = '\0';
-
-  if (*fullname)
-    fullname ++;
-
-  // Get the domain...
-  for (ptr = domain, end = domain + domainsize - 1; *fullname; fullname ++)
-  {
-    if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
-    {
-      // Escaped character
-      if (ptr < end)
-        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
-      else
-        ret = false;
-
-      fullname += 3;
-    }
-    else if (ptr < end)
-      *ptr++ = *fullname;
-    else
-      ret = false;
-  }
-  *ptr = '\0';
-
-  return (ret);
-
-#else // HAVE_AVAHI
-  return (!avahi_service_name_split(fullname, name, namesize, type, typesize, domain, domainsize));
-#endif // _WIN32 || HAVE_MDNSRESPONDER
-}
-
-
 //
 // 'cupsDNSSDDelete()' - Delete a DNS-SD context and all its requests.
 //
@@ -556,7 +610,17 @@ size_t                                     // O - Number of host name changes
 cupsDNSSDGetConfigChanges(
     cups_dnssd_t *dnssd)               // I - DNS-SD context
 {
-  return (dnssd ? dnssd->config_changes : 0);
+  size_t       config_changes = 0;
+
+
+  if (dnssd)
+  {
+    cupsRWLockRead(&dnssd->rwlock);
+    config_changes = dnssd->config_changes;
+    cupsRWUnlock(&dnssd->rwlock);
+  }
+
+  return (config_changes);
 }
 
 
@@ -584,277 +648,101 @@ cupsDNSSDNew(
   {
     DEBUG_puts("2cupsDNSSDNew: Unable to allocate memory, returning NULL.");
     return (NULL);
-  }
-
-  // Save the error callback...
-  dnssd->cb      = error_cb;
-  dnssd->cb_data = cb_data;
-
-  // Initialize the rwlock...
-  cupsRWInit(&dnssd->rwlock);
-
-  // Setup the DNS-SD connection and monitor thread...
-#ifdef HAVE_MDNSRESPONDER
-  DNSServiceErrorType error;           // Error code
-
-  if ((error = DNSServiceCreateConnection(&dnssd->ref)) != kDNSServiceErr_NoError)
-  {
-    // Unable to create connection...
-    report_error(dnssd, "Unable to initialize DNS-SD: %s", mdns_strerror(error));
-    cupsDNSSDDelete(dnssd);
-    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
-    return (NULL);
-  }
-
-  // Monitor for hostname changes...
-  httpGetHostname(NULL, dnssd->hostname, sizeof(dnssd->hostname));
-  dnssd->hostname_ref = dnssd->ref;
-  if ((error = DNSServiceQueryRecord(&dnssd->hostname_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "1.0.0.127.in-addr.arpa.", kDNSServiceType_PTR, kDNSServiceClass_IN, (DNSServiceQueryRecordReply)mdns_hostname_cb, dnssd)) != kDNSServiceErr_NoError)
-  {
-    report_error(dnssd, "Unable to query PTR record for local hostname: %s", mdns_strerror(error));
-    dnssd->hostname_ref = NULL;
-  }
-
-  // Start the background monitoring thread...
-  if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))mdns_monitor, dnssd)) == 0)
-  {
-    report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno));
-    cupsDNSSDDelete(dnssd);
-    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
-    return (NULL);
-  }
-
-  DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor);
-
-#elif _WIN32
-
-#else // HAVE_AVAHI
-  int error;                           // Error code
-
-  // Initialize the mutex used to control access to the socket
-  cupsMutexInit(&dnssd->mutex);
-
-  // Create a polled interface for Avahi requests...
-  if ((dnssd->poll = avahi_simple_poll_new()) == NULL)
-  {
-    // Unable to create the background thread...
-    report_error(dnssd, "Unable to initialize DNS-SD: %s", strerror(errno));
-    cupsDNSSDDelete(dnssd);
-    DEBUG_puts("2cupsDNSSDNew: Unable to create simple poll - returning NULL.");
-    return (NULL);
-  }
-
-  avahi_simple_poll_set_func(dnssd->poll, (AvahiPollFunc)avahi_poll_cb, dnssd);
-
-  DEBUG_printf("2cupsDNSSDNew: dnssd->poll=%p", (void *)dnssd->poll);
-
-  if ((dnssd->client = avahi_client_new(avahi_simple_poll_get(dnssd->poll), AVAHI_CLIENT_NO_FAIL, (AvahiClientCallback)avahi_client_cb, dnssd, &error)) == NULL)
-  {
-    // Unable to create the client...
-    report_error(dnssd, "Unable to initialize DNS-SD: %s", avahi_strerror(error));
-    avahi_simple_poll_free(dnssd->poll);
-    cupsDNSSDDelete(dnssd);
-    DEBUG_puts("2cupsDNSSDNew: Unable to create Avahi client - returning NULL.");
-    return (NULL);
-  }
-
-  DEBUG_printf("2cupsDNSSDNew: dnssd->client=%p", (void *)dnssd->client);
-
-  if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))avahi_monitor, dnssd)) == 0)
-  {
-    report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno));
-    cupsDNSSDDelete(dnssd);
-    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
-    return (NULL);
-  }
-
-  DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor);
-
-  dnssd->dbrowser = avahi_domain_browser_new(dnssd->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, /*domain*/NULL, AVAHI_DOMAIN_BROWSER_BROWSE, /*flags*/0, (AvahiDomainBrowserCallback)avahi_domain_cb, dnssd);
-#endif // HAVE_MDNSRESPONDER
-
-  DEBUG_printf("2cupsDNSSDNew: Returning %p.", (void *)dnssd);
-
-  return (dnssd);
-}
-
-
-//
-// 'cupsDNSSDBrowseDelete()' - Cancel and delete a browse request.
-//
-
-void
-cupsDNSSDBrowseDelete(
-    cups_dnssd_browse_t *browse)       // I - Browse request
-{
-  if (browse)
-  {
-    cups_dnssd_t *dnssd = browse->dnssd;
-
-    DEBUG_puts("2cupsDNSSDBrowseDelete: Write locking rwlock.");
-    cupsRWLockWrite(&dnssd->rwlock);
-
-    cupsArrayRemove(dnssd->browses, browse);
-
-    DEBUG_puts("2cupsDNSSDBrowseDelete: Unlocking rwlock.");
-    cupsRWUnlock(&dnssd->rwlock);
-  }
-}
-
-
-//
-// 'cupsDNSSDBrowseGetContext()' - Get the DNS-SD context for the browse request.
-//
-
-cups_dnssd_t *                         // O - Context or `NULL`
-cupsDNSSDBrowseGetContext(
-    cups_dnssd_browse_t *browse)       // I - Browse request
-{
-  return (browse ? browse->dnssd : NULL);
-}
-
-
-//
-// 'cupsDNSSDBrowseNew()' - Create a new DNS-SD browse request.
-//
-// This function creates a new DNS-SD browse request for the specified service
-// types and optional domain and interface index.  The "types" argument can be a
-// single service type ("_ipp._tcp") or a service type and comma-delimited list
-// of sub-types ("_ipp._tcp,_print,_universal").
-//
-// Newly discovered services are reported using the required browse callback
-// function, with the "flags" argument set to `CUPS_DNSSD_FLAGS_ADD` for newly
-// discovered services, `CUPS_DNSSD_FLAGS_NONE` for removed services, or
-// `CUPS_DNSSD_FLAGS_ERROR` on an error:
-//
-// ```
-// void
-// browse_cb(
-//     cups_dnssd_browse_t *browse,
-//     void                *cb_data,
-//     cups_dnssd_flags_t  flags,
-//     uint32_t            if_index,
-//     const char          *name,
-//     const char          *regtype,
-//     const char          *domain)
-// {
-//     // Process added/removed service
-// }
-// ```
-//
-
-cups_dnssd_browse_t *                  // O - Browse request or `NULL` on error
-cupsDNSSDBrowseNew(
-    cups_dnssd_t           *dnssd,     // I - DNS-SD context
-    uint32_t               if_index,   // I - Interface index, `CUPS_DNSSD_IF_INDEX_ANY`, or `CUPS_DNSSD_IF_INDEX_LOCAL`
-    const char             *types,     // I - Service types
-    const char             *domain,    // I - Domain name or `NULL` for default
-    cups_dnssd_browse_cb_t browse_cb,  // I - Browse callback function
-    void                   *cb_data)   // I - Browse callback data
-{
-  cups_dnssd_browse_t  *browse;        // Browse request
-
-
-  // Range check input...
-  if (!dnssd || !types || !browse_cb)
-    return (NULL);
-
-  // Allocate memory for the browser...
-  if ((browse = (cups_dnssd_browse_t *)calloc(1, sizeof(cups_dnssd_browse_t))) == NULL)
-    return (NULL);
+  }
 
-  browse->dnssd   = dnssd;
-  browse->cb      = browse_cb;
-  browse->cb_data = cb_data;
+  // Save the error callback...
+  dnssd->cb      = error_cb;
+  dnssd->cb_data = cb_data;
 
-  DEBUG_puts("2cupsDNSSDBrowseNew: Write locking rwlock.");
-  cupsRWLockWrite(&dnssd->rwlock);
+  // Initialize the rwlock...
+  cupsRWInit(&dnssd->rwlock);
 
-  if (!dnssd->browses)
+  // Setup the DNS-SD connection and monitor thread...
+#ifdef HAVE_MDNSRESPONDER
+  DNSServiceErrorType error;           // Error code
+
+  if ((error = DNSServiceCreateConnection(&dnssd->ref)) != kDNSServiceErr_NoError)
   {
-    // Create an array of browsers...
-    if ((dnssd->browses = cupsArrayNew3(NULL, NULL, NULL, 0, NULL, (cups_afree_cb_t)delete_browse)) == NULL)
-    {
-      // Unable to create...
-      free(browse);
-      browse = NULL;
-      goto done;
-    }
+    // Unable to create connection...
+    report_error(dnssd, "Unable to initialize DNS-SD: %s", mdns_strerror(error));
+    cupsDNSSDDelete(dnssd);
+    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
+    return (NULL);
   }
 
-#ifdef HAVE_MDNSRESPONDER
-  DNSServiceErrorType error;           // Error, if any
+  // Monitor for hostname changes...
+  httpGetHostname(NULL, dnssd->hostname, sizeof(dnssd->hostname));
+  dnssd->hostname_ref = dnssd->ref;
+  if ((error = DNSServiceQueryRecord(&dnssd->hostname_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "1.0.0.127.in-addr.arpa.", kDNSServiceType_PTR, kDNSServiceClass_IN, (DNSServiceQueryRecordReply)mdns_hostname_cb, dnssd)) != kDNSServiceErr_NoError)
+  {
+    report_error(dnssd, "Unable to query PTR record for local hostname: %s", mdns_strerror(error));
+    dnssd->hostname_ref = NULL;
+  }
 
-  browse->ref = dnssd->ref;
-  if ((error = DNSServiceBrowse(&browse->ref, kDNSServiceFlagsShareConnection, if_index, types, domain, (DNSServiceBrowseReply)mdns_browse_cb, browse)) != kDNSServiceErr_NoError)
+  // Start the background monitoring thread...
+  if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))mdns_monitor, dnssd)) == 0)
   {
-    report_error(dnssd, "Unable to create DNS-SD browse request: %s", mdns_strerror(error));
-    free(browse);
-    browse = NULL;
-    goto done;
+    report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno));
+    cupsDNSSDDelete(dnssd);
+    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
+    return (NULL);
   }
 
+  DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor);
+
 #elif _WIN32
 
 #else // HAVE_AVAHI
-  if (!dnssd->in_callback)
-  {
-    DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex.");
-    cupsMutexLock(&dnssd->mutex);
-  }
+  int error;                           // Error code
 
-  browse->num_browsers = 1;
-  browse->browsers[0]  = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, /*domain*/NULL, /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse);
+  // Initialize the mutex used to control access to the socket
+  cupsMutexInit(&dnssd->mutex);
 
-  if (!browse->browsers[0])
+  // Create a polled interface for Avahi requests...
+  if ((dnssd->poll = avahi_simple_poll_new()) == NULL)
   {
-    report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client)));
-    free(browse);
-    browse = NULL;
+    // Unable to create the background thread...
+    report_error(dnssd, "Unable to initialize DNS-SD: %s", strerror(errno));
+    cupsDNSSDDelete(dnssd);
+    DEBUG_puts("2cupsDNSSDNew: Unable to create simple poll - returning NULL.");
+    return (NULL);
+  }
 
-    if (!dnssd->in_callback)
-    {
-      DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
-      cupsMutexUnlock(&dnssd->mutex);
-    }
+  avahi_simple_poll_set_func(dnssd->poll, (AvahiPollFunc)avahi_poll_cb, dnssd);
 
-    goto done;
-  }
+  DEBUG_printf("2cupsDNSSDNew: dnssd->poll=%p", (void *)dnssd->poll);
 
-  if (!domain && dnssd->num_domains > 0)
+  if ((dnssd->client = avahi_client_new(avahi_simple_poll_get(dnssd->poll), AVAHI_CLIENT_NO_FAIL, (AvahiClientCallback)avahi_client_cb, dnssd, &error)) == NULL)
   {
-    // Add browsers for all domains...
-    size_t     i;                      // Looping var
-
-    for (i = 0; i < dnssd->num_domains; i ++)
-    {
-      if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, types, dnssd->domains[i], /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL)
-        browse->num_browsers ++;
-    }
+    // Unable to create the client...
+    report_error(dnssd, "Unable to initialize DNS-SD: %s", avahi_strerror(error));
+    avahi_simple_poll_free(dnssd->poll);
+    cupsDNSSDDelete(dnssd);
+    DEBUG_puts("2cupsDNSSDNew: Unable to create Avahi client - returning NULL.");
+    return (NULL);
   }
 
-  if (!dnssd->in_callback)
-  {
-    DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
-    cupsMutexUnlock(&dnssd->mutex);
+  DEBUG_printf("2cupsDNSSDNew: dnssd->client=%p", (void *)dnssd->client);
 
-    avahi_simple_poll_wakeup(dnssd->poll);
+  if ((dnssd->monitor = cupsThreadCreate((void *(*)(void *))avahi_monitor, dnssd)) == 0)
+  {
+    report_error(dnssd, "Unable to create DNS-SD thread: %s", strerror(errno));
+    cupsDNSSDDelete(dnssd);
+    DEBUG_puts("2cupsDNSSDNew: Unable to create DNS-SD thread - returning NULL.");
+    return (NULL);
   }
-#endif // HAVE_MDNSRESPONDER
 
-  DEBUG_printf("2cupsDNSSDBrowseNew: Adding browse=%p", (void *)browse);
-  cupsArrayAdd(dnssd->browses, browse);
+  DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor);
 
-  done:
+  dnssd->dbrowser = avahi_domain_browser_new(dnssd->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, /*domain*/NULL, AVAHI_DOMAIN_BROWSER_BROWSE, /*flags*/0, (AvahiDomainBrowserCallback)avahi_domain_cb, dnssd);
+#endif // HAVE_MDNSRESPONDER
 
-  DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking rwlock.");
-  cupsRWUnlock(&dnssd->rwlock);
+  DEBUG_printf("2cupsDNSSDNew: Returning %p.", (void *)dnssd);
 
-  return (browse);
+  return (dnssd);
 }
 
 
-
 //
 // 'cupsDNSSDQueryDelete()' - Cancel and delete a query request.
 //
@@ -929,7 +817,7 @@ cupsDNSSDQueryNew(
   cups_dnssd_query_t   *query;         // Query request
 
 
-  DEBUG_printf("cupsDNSSDQueryNew(dnssd=%p, if_index=%u, fullname=\"%s\", rrtype=%u, query_cb=%p, cb_data=%p)", (void *)dnssd, if_index, fullname, rrtype, query_cb, cb_data);
+  DEBUG_printf("cupsDNSSDQueryNew(dnssd=%p, if_index=%u, fullname=\"%s\", rrtype=%u, query_cb=%p, cb_data=%p)", (void *)dnssd, if_index, fullname, rrtype, (void *)query_cb, cb_data);
 
   // Range check input...
   if (!dnssd || !fullname || !query_cb)
@@ -1066,7 +954,7 @@ cupsDNSSDResolveGetContext(
 //     const char           *fullname,
 //     const char           *host,
 //     uint16_t             port,
-//     int                  num_txt,
+//     size_t               num_txt,
 //     cups_option_t        *txt)
 // {
 //     // Process resolved service
@@ -1115,8 +1003,7 @@ cupsDNSSDResolveNew(
   {
     report_error(dnssd, "Unable to create DNS-SD query request: %s", mdns_strerror(error));
     free(resolve);
-    resolve = NULL;
-    goto done;
+    return (NULL);
   }
 
 #elif _WIN32
@@ -1142,8 +1029,7 @@ cupsDNSSDResolveNew(
   {
     report_error(dnssd, "Unable to create DNS-SD resolve request: %s", avahi_strerror(avahi_client_errno(dnssd->client)));
     free(resolve);
-    resolve = NULL;
-    goto done;
+    return (NULL);
   }
 #endif // HAVE_MDNSRESPONDER
 
@@ -1160,6 +1046,7 @@ cupsDNSSDResolveNew(
       DEBUG_printf("2cupsDNSSDResolveNew: Unable to allocate memory: %s", strerror(errno));
       free(resolve);
       resolve = NULL;
+
       goto done;
     }
   }
@@ -1167,15 +1054,136 @@ cupsDNSSDResolveNew(
   DEBUG_printf("2cupsDNSSDResolveNew: Adding resolver %p.", (void *)resolve);
   cupsArrayAdd(dnssd->resolves, resolve);
 
+  done:
+
   DEBUG_puts("2cupsDNSSDResolveNew: Unlocking rwlock.");
   cupsRWUnlock(&dnssd->rwlock);
 
-  done:
-
   return (resolve);
 }
 
 
+//
+// 'cupsDNSSDSeparateFullName()' - Separate a full service name into an instance
+//                                 name, registration type, and domain.
+//
+// This function separates a full service name such as
+// "Example\032Name._ipp._tcp.local.") into its instance name ("Example Name"),
+// registration type ("_ipp._tcp"), and domain ("local.").
+//
+
+bool                                   // O - `true` on success, `false` on error
+cupsDNSSDSeparateFullName(
+    const char *fullname,              // I - Full service name
+    char       *name,                  // I - Instance name buffer
+    size_t     namesize,               // I - Size of instance name buffer
+    char       *type,                  // I - Registration type buffer
+    size_t     typesize,               // I - Size of registration type buffer
+    char       *domain,                        // I - Domain name buffer
+    size_t     domainsize)             // I - Size of domain name buffer
+{
+  // Range check input..
+  if (!fullname || !name || !namesize || !type || !typesize || !domain || !domainsize)
+  {
+    if (name)
+      *name = '\0';
+    if (type)
+      *type = '\0';
+    if (domain)
+      *domain = '\0';
+
+    return (false);
+  }
+
+#if _WIN32 || defined(HAVE_MDNSRESPONDER)
+  bool ret = true;                     // Return value
+  char *ptr,                           // Pointer into name/type/domain
+       *end;                           // Pointer to end of name/type/domain
+
+  // Get the service name...
+  for (ptr = name, end = name + namesize - 1; *fullname; fullname ++)
+  {
+    if (*fullname == '.')
+    {
+      // Service type separator...
+      break;
+    }
+    else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
+    {
+      // Escaped character
+      if (ptr < end)
+        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
+      else
+        ret = false;
+
+      fullname += 3;
+    }
+    else if (ptr < end)
+      *ptr++ = *fullname;
+    else
+      ret = false;
+  }
+  *ptr = '\0';
+
+  if (*fullname)
+    fullname ++;
+
+  // Get the type...
+  for (ptr = type, end = type + typesize - 1; *fullname; fullname ++)
+  {
+    if (*fullname == '.' && fullname[1] != '_')
+    {
+      // Service type separator...
+      break;
+    }
+    else if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
+    {
+      // Escaped character
+      if (ptr < end)
+        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
+      else
+        ret = false;
+
+      fullname += 3;
+    }
+    else if (ptr < end)
+      *ptr++ = *fullname;
+    else
+      ret = false;
+  }
+  *ptr = '\0';
+
+  if (*fullname)
+    fullname ++;
+
+  // Get the domain...
+  for (ptr = domain, end = domain + domainsize - 1; *fullname; fullname ++)
+  {
+    if (*fullname == '\\' && isdigit(fullname[1] & 255) && isdigit(fullname[2] & 255) && isdigit(fullname[3] & 255))
+    {
+      // Escaped character
+      if (ptr < end)
+        *ptr++ = (fullname[1] - '0') * 100 + (fullname[2] - '0') * 10 + fullname[3] - '0';
+      else
+        ret = false;
+
+      fullname += 3;
+    }
+    else if (ptr < end)
+      *ptr++ = *fullname;
+    else
+      ret = false;
+  }
+  *ptr = '\0';
+
+  return (ret);
+
+#else // HAVE_AVAHI
+  return (!avahi_service_name_split(fullname, name, namesize, type, typesize, domain, domainsize));
+#endif // _WIN32 || HAVE_MDNSRESPONDER
+}
+
+
 //
 // 'cupsDNSSDServiceAdd()' - Add a service instance.
 //
@@ -2389,7 +2397,7 @@ avahi_resolve_cb(
     cups_dnssd_resolve_t   *resolve)   // I - Resolve request
 {
   AvahiStringList *txtpair;            // Current pair
-  int          num_txt = 0;            // Number of TXT key/value pairs
+  size_t       num_txt = 0;            // Number of TXT key/value pairs
   cups_option_t        *txt = NULL;            // TXT key/value pairs
   char         fullname[1024];         // Full service name
 
index fac91560fe7f4e07654a9ccfe10dfd6d8790fdb8..4d5e09172d2a821c27798473c307934c5e8a7f66 100644 (file)
@@ -753,17 +753,6 @@ _cupsStrFree(const char *s)                /* I - String to free */
   if (!s)
     return;
 
- /*
-  * Check the string pool...
-  *
-  * We don't need to lock the mutex yet, as we only want to know if
-  * the stringpool is initialized.  The rest of the code will still
-  * work if it is initialized before we lock...
-  */
-
-  if (!stringpool)
-    return;
-
  /*
   * See if the string is already in the pool...
   */
@@ -772,8 +761,7 @@ _cupsStrFree(const char *s)         /* I - String to free */
 
   key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
 
-  if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL &&
-      item == key)
+  if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && item == key)
   {
    /*
     * Found it, dereference...
@@ -823,6 +811,8 @@ _cupsStrRetain(const char *s)               /* I - String to retain */
   {
     item = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
 
+    cupsMutexLock(&sp_mutex);
+
 #ifdef DEBUG_GUARDS
     if (item->guard != _CUPS_STR_GUARD)
     {
@@ -831,8 +821,6 @@ _cupsStrRetain(const char *s)               /* I - String to retain */
     }
 #endif /* DEBUG_GUARDS */
 
-    cupsMutexLock(&sp_mutex);
-
     item->ref_count ++;
 
     cupsMutexUnlock(&sp_mutex);
index b161bfea49ebfef813f60dab2bed8533cae858d8..87d493b1eced9d08647efcafbe14a7af65dca638 100644 (file)
@@ -1473,6 +1473,7 @@ _httpTLSRead(http_t *http,                // I - Connection to server
 bool                                   // O - `true` on success, `false` on failure
 _httpTLSStart(http_t *http)            // I - Connection to server
 {
+  const char           *keypath;       // Certificate store path
   char                 hostname[256],  // Hostname
                        *hostptr;       // Pointer into hostname
   int                  status;         // Status of handshake
@@ -1505,7 +1506,11 @@ _httpTLSStart(http_t *http)              // I - Connection to server
     DEBUG_printf("4_httpTLSStart: tls_options=%x", tls_options);
   }
 
-  if (http->mode == _HTTP_MODE_SERVER && !tls_keypath)
+  cupsMutexLock(&tls_mutex);
+  keypath = tls_keypath;
+  cupsMutexUnlock(&tls_mutex);
+
+  if (http->mode == _HTTP_MODE_SERVER && !keypath)
   {
     DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
     http->error  = errno = EINVAL;
index 67493a19b62a6363987076009ba7d6224851f824..bf5819dc018a09b9587dd1866f84f49b16bc58f3 100644 (file)
@@ -1496,6 +1496,7 @@ _httpTLSRead(http_t *http,                // I - Connection to server
 bool                                   // O - `true` on success, `false` on failure
 _httpTLSStart(http_t *http)            // I - Connection to server
 {
+  const char   *keypath;               // Certificate store path
   BIO          *bio;                   // Basic input/output context
   SSL_CTX      *context;               // Encryption context
   char         hostname[256],          // Hostname
@@ -1526,7 +1527,11 @@ _httpTLSStart(http_t *http)              // I - Connection to server
     DEBUG_printf("4_httpTLSStart: tls_options=%x", tls_options);
   }
 
-  if (http->mode == _HTTP_MODE_SERVER && !tls_keypath)
+  cupsMutexLock(&tls_mutex);
+  keypath = tls_keypath;
+  cupsMutexUnlock(&tls_mutex);
+
+  if (http->mode == _HTTP_MODE_SERVER && !keypath)
   {
     DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
     http->error  = errno = EINVAL;
@@ -1600,13 +1605,13 @@ _httpTLSStart(http_t *http)             // I - Connection to server
     if (isdigit(hostname[0] & 255) || hostname[0] == '[')
       hostname[0] = '\0';              // Don't allow numeric addresses
 
+    cupsMutexLock(&tls_mutex);
+
     if (hostname[0])
       cn = hostname;
     else
       cn = tls_common_name;
 
-    cupsMutexLock(&tls_mutex);
-
     if (cn)
     {
       // First look in the CUPS keystore...
@@ -1709,9 +1714,10 @@ _httpTLSStart(http_t *http)              // I - Connection to server
     BIO_meth_set_puts(tls_bio_method, http_bio_puts);
     BIO_meth_set_write(tls_bio_method, http_bio_write);
   }
-  cupsMutexUnlock(&tls_mutex);
 
   bio = BIO_new(tls_bio_method);
+  cupsMutexUnlock(&tls_mutex);
+
   BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
 
   http->tls = SSL_new(context);