//
#include "cups-private.h"
-#include "debug-internal.h"
#include "dnssd.h"
#ifdef __APPLE__
}
+//
+// '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.
//
}
-//
-// '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.
//
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);
}
{
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.
//
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)
// const char *fullname,
// const char *host,
// uint16_t port,
-// int num_txt,
+// size_t num_txt,
// cups_option_t *txt)
// {
// // Process resolved service
{
report_error(dnssd, "Unable to create DNS-SD query request: %s", mdns_strerror(error));
free(resolve);
- resolve = NULL;
- goto done;
+ return (NULL);
}
#elif _WIN32
{
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
DEBUG_printf("2cupsDNSSDResolveNew: Unable to allocate memory: %s", strerror(errno));
free(resolve);
resolve = NULL;
+
goto done;
}
}
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.
//
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