]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Mirror Win32 DNS-SD changes from libcups project.
authorMichael R Sweet <msweet@msweet.org>
Tue, 18 Mar 2025 18:43:02 +0000 (14:43 -0400)
committerMichael R Sweet <msweet@msweet.org>
Tue, 18 Mar 2025 18:43:02 +0000 (14:43 -0400)
CHANGES.md
cups/dnssd.c
vcnet/cups.sln
vcnet/dns_sd.c [deleted file]
vcnet/dns_sd.h [deleted file]
vcnet/dnssdstub.vcxproj [deleted file]
vcnet/testdnssd.vcxproj [new file with mode: 0644]
vcnet/testdnssd.vcxproj.filters [moved from vcnet/dnssdstub.vcxproj.filters with 67% similarity]
vcnet/testdnssd.vcxproj.user [moved from vcnet/dnssdstub.vcxproj.user with 100% similarity]

index f2582707865c5bc75eef096735493a089c8ca8bf..72aa7c48a441d6a88349422f61ab650be948cc8c 100644 (file)
@@ -37,6 +37,7 @@ Changes in CUPS v2.5b1 (YYYY-MM-DD)
 - Added `cups-oauth` and `cups-x509` utilities (Issue #1184)
 - Updated documentation (Issue #984, Issue #1086, Issue #1182)
 - Updated the configure script to default to installing to /usr/local.
+- Updated CUPS to use the Windows mDNS APIs.
 - Updated CUPS to require TLS support - OpenSSL, GNUTLS and LibreSSL are
   supported.
 - Updated CUPS to require ZLIB.
index d72f0d1f66706f2fb5f1e48d559d72cf44a3c81f..696593e85454268fcf09535a4a2c079f5df43641 100644 (file)
@@ -1,7 +1,7 @@
 //
 // DNS-SD API functions for CUPS.
 //
-// Copyright © 2022-2024 by OpenPrinting.
+// Copyright © 2022-2025 by OpenPrinting.
 //
 // Licensed under Apache License v2.0.  See the file "LICENSE" for more
 // information.
@@ -25,6 +25,7 @@
 #  endif // _WIN32
 #elif _WIN32
 #  include <windns.h>
+#  pragma comment(lib, "dnsapi.lib")     // Link in dnsapi library...
 #else // HAVE_AVAHI
 #  include <avahi-client/client.h>
 #  include <avahi-client/lookup.h>
 #endif // HAVE_MDNSRESPONDER
 
 
+//
+// Constants...
+//
+
+#define _CUPS_DNSSD_MAX                50      // Maximum number of browsers/services/etc.
+
+
 //
 // Private structures...
 //
@@ -46,7 +54,7 @@
 struct _cups_dnssd_s                   // DNS-SD context
 {
   cups_rwlock_t                rwlock;         // R/W lock for context
-  size_t               config_changes; // Number of hostname/network changes
+  size_t                       config_changes; // Number of hostname/network changes
   cups_dnssd_error_cb_t        cb;             // Error callback function
   void                 *cb_data;       // Error callback data
   cups_array_t         *browses,       // Browse requests
@@ -58,19 +66,21 @@ struct _cups_dnssd_s                        // DNS-SD context
   DNSServiceRef                ref;            // Master service reference
   char                 hostname[256];  // Current mDNS hostname
   DNSServiceRef                hostname_ref;   // Hostname monitoring reference
-  cups_thread_t                monitor;        // Monitoring thread
+  cups_thread_t                monitor;                // Monitoring thread
 
 #elif _WIN32
+  char                 hostname[256];  // Current mDNS hostname
 
 #else // HAVE_AVAHI
   cups_mutex_t         mutex;          // Avahi poll mutex
   bool                 in_callback;    // Doing a callback?
-  AvahiClient          *client;        // Avahi client connection
+  AvahiClient          *client;                // Avahi client connection
   AvahiSimplePoll      *poll;          // Avahi poll class
-  cups_thread_t                monitor;        // Monitoring thread
+  cups_thread_t                monitor;                // Monitoring thread
   AvahiDomainBrowser   *dbrowser;      // Domain browser
-  size_t               num_domains;    // Number of domains
-  char                 domains[32][256];// Domains
+  size_t                       num_domains;    // Number of domains
+  char                 domains[_CUPS_DNSSD_MAX][256];
+                                       // Domains
 #endif // HAVE_MDNSRESPONDER
 };
 
@@ -82,10 +92,20 @@ struct _cups_dnssd_browse_s         // DNS-SD browse request
 
 #ifdef HAVE_MDNSRESPONDER
   DNSServiceRef                ref;            // Browse reference
+
 #elif _WIN32
+  size_t                       num_browsers;   // Number of browsers
+  struct
+  {                                    // Browsers
+    WCHAR              name[256];              // Browse name as a UTF-16 string
+    DNS_SERVICE_BROWSE_REQUEST req;            // Browse request
+    DNS_SERVICE_CANCEL cancel;                 // Cancellation structure
+  }                    browsers[_CUPS_DNSSD_MAX];
+
 #else // HAVE_AVAHI
-  size_t               num_browsers;   // Number of browsers
-  AvahiServiceBrowser  *browsers[33];  // Browsers
+  size_t                       num_browsers;   // Number of browsers
+  AvahiServiceBrowser  *browsers[_CUPS_DNSSD_MAX];
+                                       // Browsers
 #endif // HAVE_MDNSRESPONDER
 };
 
@@ -97,7 +117,13 @@ struct _cups_dnssd_query_s          // DNS-SD query request
 
 #ifdef HAVE_MDNSRESPONDER
   DNSServiceRef                ref;            // Query reference
+
 #elif _WIN32
+  WCHAR                        fullname[256];  // Query full name as a UTF-16 string
+  MDNS_QUERY_REQUEST   req;            // Query request
+  MDNS_QUERY_HANDLE    handle;         // Query handle
+  DNS_QUERY_RESULT     res;            // Query result
+
 #else // HAVE_AVAHI
   AvahiRecordBrowser   *browser;       // Browser
 #endif // HAVE_MDNSRESPONDER
@@ -111,12 +137,28 @@ struct _cups_dnssd_resolve_s              // DNS-SD resolve request
 
 #ifdef HAVE_MDNSRESPONDER
   DNSServiceRef                ref;            // Resolve reference
+
 #elif _WIN32
+  WCHAR                        fullname[256];  // Full name as a UTF-16 string
+  DNS_SERVICE_RESOLVE_REQUEST req;     // Resolve request
+  DNS_SERVICE_CANCEL   cancel;         // Cancellation structure
+
 #else // HAVE_AVAHI
   AvahiServiceResolver *resolver;      // Resolver
 #endif // HAVE_MDNSRESPONDER
 };
 
+#if _WIN32
+struct _win32_srv_s                  // Service
+{
+  DNS_SERVICE_REGISTER_REQUEST req;    // Registration request
+  DNS_SERVICE_CANCEL   cancel;         // Cancellation structure
+  WCHAR                fullname[256];          // Full service name
+  WCHAR                hostname[256];          // Hostname
+  WCHAR                *txt;                   // TXT key/value string buffer
+};
+#endif // _WIN32
+
 struct _cups_dnssd_service_s           // DNS-SD service registration
 {
   cups_dnssd_t         *dnssd;         // DNS-SD context
@@ -129,9 +171,16 @@ struct _cups_dnssd_service_s               // DNS-SD service registration
 
 #ifdef HAVE_MDNSRESPONDER
   size_t               num_refs;       // Number of service references
-  DNSServiceRef                refs[16];       // Service references
-  DNSRecordRef         loc_refs[16];   // Service location records
+  DNSServiceRef                refs[_CUPS_DNSSD_MAX];
+                                       // Service references
+  DNSRecordRef         loc_refs[_CUPS_DNSSD_MAX];
+                                       // Service location records
+
 #elif _WIN32
+  size_t                       num_srvs;       // Number of services
+  struct _win32_srv_s  srvs[_CUPS_DNSSD_MAX];
+                                       // Services
+
 #else // HAVE_AVAHI
   AvahiEntryGroup      *group;         // Group of services under this name
 #endif // HAVE_MDNSRESPONDER
@@ -159,6 +208,12 @@ static const char  *mdns_strerror(DNSServiceErrorType errorCode);
 static cups_dnssd_flags_t mdns_to_cups(DNSServiceFlags flags, DNSServiceErrorType error);
 
 #elif _WIN32
+static void            win32_browse_cb(DWORD status, PVOID context, PDNS_RECORD record);
+static void            win32_query_cb(PVOID context, PMDNS_QUERY_HANDLE handle, PDNS_QUERY_RESULT result);
+static void            win32_resolve_cb(DWORD status, PVOID context, PDNS_SERVICE_INSTANCE instance);
+static void            win32_service_cb(DWORD status, PVOID context, PDNS_SERVICE_INSTANCE instance);
+static void            win32_utf8cpy(char *dst, const WCHAR *src, size_t dstsize);
+static void            win32_wstrcpy(WCHAR *dst, const char *src, size_t dstsize);
 
 #else // HAVE_AVAHI
 static void            avahi_browse_cb(AvahiServiceBrowser *browser, AvahiIfIndex if_index, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, cups_dnssd_browse_t *browse);
@@ -185,7 +240,7 @@ static void         avahi_service_cb(AvahiEntryGroup *srv, AvahiEntryGroupState state,
 bool                                   // O - `true` on success, `false` on failure
 cupsDNSSDAssembleFullName(
     char       *fullname,              // I - Buffer for full name
-    size_t     fullsize,               // I - Size of buffer
+    size_t     fullsize,                       // I - Size of buffer
     const char *name,                  // I - Service instance name
     const char *type,                  // I - Registration type
     const char *domain)                        // I - Domain
@@ -200,7 +255,28 @@ cupsDNSSDAssembleFullName(
   return (DNSServiceConstructFullName(fullname, name, type, domain) == kDNSServiceErr_NoError);
 
 #elif _WIN32
-  return (false);
+  char         *fullptr,               // Pointer into full name
+               *fullend;               // End of full name
+
+  for (fullptr = fullname, fullend = fullname + fullsize - 1; *name; name ++)
+  {
+    if (*name == ' ' || *name == '\\' || (*name & 0x80))
+    {
+      if ((fullend - fullptr) < 4)
+        return (false);
+
+      snprintf(fullptr, fullend - fullptr + 1, "\\%03d", *name & 255);
+      fullptr += strlen(fullptr);
+    }
+    else
+    {
+      *fullptr++ = *name;
+    }
+  }
+
+  snprintf(fullptr, fullend - fullptr + 1, ".%s.%s", type, domain ? domain : "local");
+
+  return (true);
 
 #else // HAVE_AVAHI
   return (!avahi_service_name_join(fullname, fullsize, name, type, domain));
@@ -324,44 +400,140 @@ cupsDNSSDBrowseNew(
   }
 
 #elif _WIN32
+  DNS_STATUS   status;                 // DNS request status
+  size_t       i,                      // Looping var
+               count;                  // Number of types
+  const char   *base,                  // Base query name
+               *subtype;               // Subtype
+  char         typename[256];          // Current query name
+  cups_array_t *tarray;                // Types array
 
-#else // HAVE_AVAHI
-  if (!dnssd->in_callback)
+
+  if ((tarray = cupsArrayNewStrings(types, ',')) == NULL)
   {
-    DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex.");
-    cupsMutexLock(&dnssd->mutex);
+    report_error(dnssd, "Unable to create types array: %s", strerror(errno));
+    free(browse);
+    browse = NULL;
+    goto done;
   }
 
-  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);
+  base  = (const char *)cupsArrayGetElement(tarray, 0);
+  count = cupsArrayGetCount(tarray);
+
+  if (count == 1)
+    count ++;
 
-  if (!browse->browsers[0])
+  for (i = 1; i < count; i ++)
   {
-    report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client)));
-    free(browse);
-    browse = NULL;
+    subtype = (const char *)cupsArrayGetElement(tarray, i);
 
-    if (!dnssd->in_callback)
+    if (subtype)
+      snprintf(typename, sizeof(typename), "%s._sub.%s.local", subtype, base);
+    else
+      snprintf(typename, sizeof(typename), "%s.local", base);
+
+    browse->browsers[i].req.Version         = DNS_QUERY_REQUEST_VERSION1;
+    browse->browsers[i].req.InterfaceIndex  = if_index;
+    browse->browsers[i].req.pBrowseCallback = win32_browse_cb;
+    browse->browsers[i].req.pQueryContext   = browse;
+    browse->browsers[i].req.QueryName       = browse->browsers[i].name;
+
+    win32_wstrcpy(browse->browsers[i].name, typename, sizeof(browse->browsers[i].name));
+
+    if ((status = DnsServiceBrowse(&browse->browsers[i].req, &browse->browsers[i].cancel)) != DNS_REQUEST_PENDING)
     {
-      DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
-      cupsMutexUnlock(&dnssd->mutex);
+      report_error(dnssd, "Unable to create browser: %u", status);
+      while (i > 0)
+      {
+        i --;
+        DnsServiceBrowseCancel(&browse->browsers[i].cancel);
+      }
+      free(browse);
+      browse = NULL;
+      cupsArrayDelete(tarray);
+      goto done;
     }
+  }
+
+  cupsArrayDelete(tarray);
+
+#else // HAVE_AVAHI
+  size_t       i, j,           // Looping vars
+               count;          // Number of types
+  const char   *base,          // Base query name
+               *subtype;       // Subtype
+  char         typename[256];  // Current query name
+  cups_array_t *tarray;        // Types array
+
 
+  if ((tarray = cupsArrayNewStrings(types, ',')) == NULL)
+  {
+    report_error(dnssd, "Unable to create types array: %s", strerror(errno));
+    free(browse);
+    browse = NULL;
     goto done;
   }
 
-  if (!domain && dnssd->num_domains > 0)
+  base  = (const char *)cupsArrayGetElement(tarray, 0);
+  count = cupsArrayGetCount(tarray);
+
+  if (count == 1)
+    count ++;
+
+  if (!dnssd->in_callback)
+  {
+    DEBUG_puts("2cupsDNSSDBrowseNew: Locking mutex.");
+    cupsMutexLock(&dnssd->mutex);
+  }
+
+  for (i = 1; i < count && browse->num_browsers < _CUPS_DNSSD_MAX; i ++)
   {
-    // Add browsers for all domains...
-    size_t     i;                      // Looping var
+    subtype = (const char *)cupsArrayGetElement(tarray, i);
 
-    for (i = 0; i < dnssd->num_domains; i ++)
+    if (subtype)
+      snprintf(typename, sizeof(typename), "%s._sub.%s.local", subtype, base);
+    else
+      snprintf(typename, sizeof(typename), "%s.local", base);
+
+    if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, typename, domain, /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL)
     {
-      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 ++;
+      browse->num_browsers ++;
+    }
+    else
+    {
+      report_error(dnssd, "Unable to create DNS-SD browse request: %s", avahi_strerror(avahi_client_errno(dnssd->client)));
+      while (browse->num_browsers > 0)
+      {
+        browse->num_browsers --;
+        avahi_service_browser_free(browse->browsers[browse->num_browsers]);
+      }
+      free(browse);
+      browse = NULL;
+
+      cupsArrayDelete(tarray);
+
+      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...
+      for (j = 0; j < dnssd->num_domains && browse->num_browsers < _CUPS_DNSSD_MAX; j ++)
+      {
+       if ((browse->browsers[browse->num_browsers] = avahi_service_browser_new(dnssd->client, avahi_if_index(if_index), AVAHI_PROTO_UNSPEC, typename, dnssd->domains[i], /*flags*/0, (AvahiServiceBrowserCallback)avahi_browse_cb, browse)) != NULL)
+         browse->num_browsers ++;
+      }
     }
   }
 
+  cupsArrayDelete(tarray);
+
   if (!dnssd->in_callback)
   {
     DEBUG_puts("2cupsDNSSDBrowseNew: Unlocking mutex.");
@@ -441,6 +613,11 @@ cupsDNSSDCopyComputerName(
   if ((bufptr = strchr(buffer, '.')) != NULL)
     *bufptr = '\0';
 
+#elif _WIN32
+  DWORD        size = (DWORD)bufsize;          // Size for GetComputerNameA
+
+  GetComputerNameA(buffer, &size);
+
 #else // HAVE_AVAHI
   cupsCopyString(buffer, avahi_client_get_host_name(dnssd->client), bufsize);
 #endif // __APPLE__
@@ -484,6 +661,9 @@ cupsDNSSDCopyHostName(
   DEBUG_puts("2cupsDNSSDCopyHostName: Unlocking rwlock.");
   cupsRWUnlock(&dnssd->rwlock);
 
+#elif _WIN32
+  cupsCopyString(buffer, dnssd->hostname, bufsize);
+
 #else // HAVE_AVAHI
   cupsCopyString(buffer, avahi_client_get_host_name_fqdn(dnssd->client), bufsize);
 #endif // HAVE_MDNSRESPONDER
@@ -691,6 +871,12 @@ cupsDNSSDNew(
   DEBUG_printf("2cupsDNSSDNew: dnssd->monitor=%p", (void *)dnssd->monitor);
 
 #elif _WIN32
+  char compname[256];                  // Computer name
+  DWORD        compsize = sizeof(compname);    // Size of computer name buffer
+
+  GetComputerNameA(compname, &compsize);
+
+  snprintf(dnssd->hostname, sizeof(dnssd->hostname), "%s.local", compname);
 
 #else // HAVE_AVAHI
   int error;                           // Error code
@@ -817,7 +1003,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, (void *)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, query_cb, cb_data);
 
   // Range check input...
   if (!dnssd || !fullname || !query_cb)
@@ -860,6 +1046,24 @@ cupsDNSSDQueryNew(
   }
 
 #elif _WIN32
+  DNS_STATUS   status;         // DNS request status
+
+  win32_wstrcpy(query->fullname, fullname, sizeof(query->fullname));
+
+  query->req.Version        = DNS_QUERY_REQUEST_VERSION1;
+  query->req.InterfaceIndex = if_index;
+  query->req.Query          = query->fullname;
+  query->req.QueryType      = rrtype;
+  query->req.pQueryCallback = win32_query_cb;
+  query->req.pQueryContext  = query;
+
+  if ((status = DnsStartMulticastQuery(&query->req, &query->handle)) != ERROR_SUCCESS)
+  {
+    report_error(dnssd, "Unable to start mDNS query request: %d", status);
+    free(query);
+    query = NULL;
+    goto done;
+  }
 
 #else // HAVE_AVAHI
   if (!dnssd->in_callback)
@@ -954,7 +1158,7 @@ cupsDNSSDResolveGetContext(
 //     const char           *fullname,
 //     const char           *host,
 //     uint16_t             port,
-//     size_t               num_txt,
+//     int                  num_txt,
 //     cups_option_t        *txt)
 // {
 //     // Process resolved service
@@ -1001,12 +1205,31 @@ cupsDNSSDResolveNew(
   resolve->ref = dnssd->ref;
   if ((error = DNSServiceResolve(&resolve->ref, kDNSServiceFlagsShareConnection, if_index, name, type, domain, (DNSServiceResolveReply)mdns_resolve_cb, resolve)) != kDNSServiceErr_NoError)
   {
-    report_error(dnssd, "Unable to create DNS-SD query request: %s", mdns_strerror(error));
+    report_error(dnssd, "Unable to create DNS-SD resolve request: %s", mdns_strerror(error));
     free(resolve);
     return (NULL);
   }
 
 #elif _WIN32
+  DNS_STATUS   status;                 // Status of resolve
+  char         fullname[256];          // Full service name
+
+  snprintf(fullname, sizeof(fullname), "%s.%s.%s", name, type, domain ? domain : "local");
+
+  win32_wstrcpy(resolve->fullname, fullname, sizeof(resolve->fullname));
+
+  resolve->req.Version                    = DNS_QUERY_REQUEST_VERSION1;
+  resolve->req.InterfaceIndex             = if_index;
+  resolve->req.QueryName                  = resolve->fullname;
+  resolve->req.pResolveCompletionCallback = win32_resolve_cb;
+  resolve->req.pQueryContext              = resolve;
+
+  if ((status = DnsServiceResolve(&resolve->req, &resolve->cancel)) != DNS_REQUEST_PENDING)
+  {
+    report_error(dnssd, "Unable to create DNS-SD resolve request: %d", status);
+    free(resolve);
+    return (NULL);
+  }
 
 #else // HAVE_AVAHI
   if (!dnssd->in_callback)
@@ -1076,9 +1299,9 @@ 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
+    size_t     namesize,                       // I - Size of instance name buffer
     char       *type,                  // I - Registration type buffer
-    size_t     typesize,               // I - Size of 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
 {
@@ -1264,6 +1487,110 @@ cupsDNSSDServiceAdd(
   service->num_refs ++;
 
 #elif _WIN32
+  DWORD                status;                 // Status of call
+  struct _win32_srv_s *srv;            // Service
+  int          j,                      // Looping var
+               count;                  // Number of types
+  size_t       length;                 // Length of TXT key/value pairs
+  WCHAR                *ptr,                   // Pointer into TXT buffer
+               *end,                   // End of TXT buffer
+               *keys[256],             // TXT key strings
+               *values[256];           // TXT value strings
+  const char   *base;                  // Base service type
+  char         fullname[256];          // Full service instance name
+  cups_array_t *tarray;                // Types array
+
+  if ((tarray = cupsArrayNewStrings(types, ',')) == NULL)
+  {
+    report_error(service->dnssd, "Unable to create types array: %s", strerror(errno));
+    ret = false;
+    goto done;
+  }
+
+  base  = (const char *)cupsArrayGetElement(tarray, 0);
+  count = cupsArrayGetCount(tarray);
+
+  // TODO: Figure out how WinDNS wants sub-types registered, yields invalid argument error for sub-type
+  for (i = 0; i < count && i < 1; i ++)
+  {
+    // Get the fullname...
+    if (i)
+      snprintf(fullname, sizeof(fullname), "%s.%s._sub.%s.%s", service->name, (const char*)cupsArrayGetElement(tarray, i), base, domain ? domain : "local");
+    else
+      snprintf(fullname, sizeof(fullname), "%s.%s.%s", service->name, base, domain ? domain : "local");
+
+    DEBUG_printf("cupsDNSSDServiceAdd: Adding fullname=\"%s\"", fullname);
+
+    // Get the service...
+    if (service->num_srvs >= _CUPS_DNSSD_MAX)
+    {
+      report_error(service->dnssd, "Too many services for this name.");
+      ret = false;
+      cupsArrayDelete(tarray);
+      goto done;
+    }
+
+    srv = service->srvs + service->num_srvs;
+
+    // Initialize values...
+    srv->req.Version        = DNS_QUERY_REQUEST_VERSION1;
+    srv->req.InterfaceIndex = service->if_index;
+
+    win32_wstrcpy(srv->fullname, fullname, sizeof(srv->fullname));
+    if (host)
+      win32_wstrcpy(srv->hostname, host, sizeof(srv->hostname));
+    else
+      win32_wstrcpy(srv->hostname, service->dnssd->hostname, sizeof(srv->hostname));
+
+    for (j = 0, length = 0; j < num_txt; j ++)
+      length += strlen(txt[j].name) + strlen(txt[j].value) + 2;
+
+    DEBUG_printf("cupsDNSSDServiceAdd: TXT length=%lu", (unsigned long)length);
+
+    if (length > 0)
+    {
+      srv->txt = calloc(length, sizeof(WCHAR));
+
+      for (j = 0, ptr = srv->txt, end = srv->txt + length; j < num_txt; j ++)
+      {
+        win32_wstrcpy(ptr, txt[j].name, (size_t)(end - ptr) * sizeof(WCHAR));
+        keys[j] = ptr;
+        ptr     += strlen(txt[j].name) + 1;
+
+        win32_wstrcpy(ptr, txt[j].value, (size_t)(end - ptr) * sizeof(WCHAR));
+        values[j] = ptr;
+        ptr     += strlen(txt[j].value) + 1;
+      }
+    }
+
+    if ((srv->req.pServiceInstance = DnsServiceConstructInstance(srv->fullname, srv->hostname, /*pIp4*/NULL, /*pIp6*/NULL, port, 0, 0, (DWORD)num_txt, keys, values)) == NULL)
+    {
+      report_error(service->dnssd, "Unable to allocate memory for '%s'.", fullname);
+      ret = false;
+      cupsArrayDelete(tarray);
+      goto done;
+    }
+
+    srv->req.pRegisterCompletionCallback = win32_service_cb;
+    srv->req.pQueryContext               = service;
+    srv->req.unicastEnabled              = domain && strcmp(domain, "local") != 0;
+
+    DEBUG_printf("cupsDNSSDServiceAdd: unicastEnabled=%s", srv->req.unicastEnabled ? "true" : "false");
+
+    if ((status = DnsServiceRegister(&srv->req, &srv->cancel)) != DNS_REQUEST_PENDING)
+    {
+      report_error(service->dnssd, "Unable to register '%s': %d", fullname, status);
+      ret = false;
+      DnsServiceFreeInstance(srv->req.pServiceInstance);
+      cupsArrayDelete(tarray);
+      goto done;
+    }
+
+    // Register...
+    service->num_srvs ++;
+  }
+
+  cupsArrayDelete(tarray);
 
 #else // HAVE_AVAHI
   int                  error;          // Error code
@@ -1622,6 +1949,10 @@ delete_browse(
   DNSServiceRefDeallocate(browse->ref);
 
 #elif _WIN32
+  size_t       i;                      // Looping var
+
+  for (i = 0; i < browse->num_browsers; i ++)
+    DnsServiceBrowseCancel(&browse->browsers[i].cancel);
 
 #else // HAVE_AVAHI
   size_t       i;                      // Looping var
@@ -1646,6 +1977,7 @@ delete_query(
   DNSServiceRefDeallocate(query->ref);
 
 #elif _WIN32
+  DnsStopMulticastQuery(&query->handle);
 
 #else // HAVE_AVAHI
   avahi_record_browser_free(query->browser);
@@ -1665,6 +1997,7 @@ delete_resolve(
   DNSServiceRefDeallocate(resolve->ref);
 
 #elif _WIN32
+  DnsServiceResolveCancel(&resolve->cancel);
 
 #else // HAVE_AVAHI
   avahi_service_resolver_free(resolve->resolver);
@@ -1690,6 +2023,14 @@ delete_service(
     DNSServiceRefDeallocate(service->refs[i]);
 
 #elif _WIN32
+  size_t       i;                      // Looping var
+
+  for (i = 0; i < service->num_srvs; i ++)
+  {
+    DnsServiceRegisterCancel(&service->srvs[i].cancel);
+    DnsServiceFreeInstance(service->srvs[i].req.pServiceInstance);
+    free(service->srvs[i].txt);
+  }
 
 #else // HAVE_AVAHI
   avahi_entry_group_free(service->group);
@@ -2111,6 +2452,265 @@ mdns_to_cups(
 
 
 #elif _WIN32
+//
+// 'win32_browse_cb()' - Handle browse callbacks from WinDNS.
+//
+
+static void
+win32_browse_cb(
+    DWORD       status,                        // I - Status
+    PVOID       context,                       // I - Browser
+    PDNS_RECORD records)                       // I - Record list
+{
+  cups_dnssd_browse_t *browse = (cups_dnssd_browse_t *)context;
+  PDNS_RECORD record;                  // Current DNS record
+  char       fullname[256],            // Full service instance name
+             name[256] = "",           // Service name
+             type[256] = "",           // Service type
+             domain[256] = "";         // Domain name
+
+
+  for (record = records; record; record = record->pNext)
+  {
+    if (record->wType == DNS_TYPE_PTR)
+    {
+      win32_utf8cpy(fullname, record->Data.PTR.pNameHost, sizeof(fullname));
+      cupsDNSSDSeparateFullName(fullname, name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+      break;
+    }
+  }
+
+  (browse->cb)(browse, browse->cb_data, status == ERROR_SUCCESS ? CUPS_DNSSD_FLAGS_NONE : CUPS_DNSSD_FLAGS_ERROR, /*if_index*/0, name, type, domain);
+
+  DnsRecordListFree(records, DnsFreeRecordList);
+}
+
+
+//
+// 'win32_query_cb()' - Handle query callbacks from WinDNS.
+//
+
+static void
+win32_query_cb(
+    PVOID              context,                // I - Pointer to query
+    PMDNS_QUERY_HANDLE handle,         // I - Query handle
+    PDNS_QUERY_RESULT  result)         // I - Query result
+{
+  cups_dnssd_query_t  *query = (cups_dnssd_query_t *)context;
+                                       // Query
+  char               fullname[256];    // Full instance name of query
+
+
+  win32_utf8cpy(fullname, query->fullname, sizeof(fullname));
+
+  if (result && result->pQueryRecords)
+  {
+    PDNS_RECORD record;                        // Current DNS record
+
+    for (record = result->pQueryRecords; record; record = record->pNext)
+      (query->cb)(query, query->cb_data, CUPS_DNSSD_FLAGS_NONE, /*if_index*/0, fullname, record->wType, &record->Data, record->wDataLength);
+
+    DnsRecordListFree(result->pQueryRecords, DnsFreeRecordList);
+  }
+}
+
+
+//
+// 'win32_resolve_cb()' - Handle resolve callbacks from WinDNS.
+//
+
+static void
+win32_resolve_cb(
+    DWORD                 status,      // I - Status
+    PVOID                 context,     // I - Resolver
+    PDNS_SERVICE_INSTANCE instance)    // I - Service instance
+{
+  cups_dnssd_resolve_t *resolve = (cups_dnssd_resolve_t *)context;
+                                       // Resolver
+
+
+  if (status == ERROR_SUCCESS)
+  {
+    char               fullname[256],  // Full instance name
+                       hostname[256],  // Hostname
+                       txtname[256],   // TXT name
+                       txtvalue[256];  // TXT value
+    DWORD              i;              // Looping var
+    int                        num_txt = 0;    // Number of TXT values
+    cups_option_t      *txt = NULL;    // TXT values
+
+    win32_utf8cpy(fullname, instance->pszInstanceName, sizeof(fullname));
+    win32_utf8cpy(hostname, instance->pszHostName, sizeof(hostname));
+
+    for (i = 0; i < instance->dwPropertyCount; i ++)
+    {
+      win32_utf8cpy(txtname, instance->keys[i], sizeof(txtname));
+      win32_utf8cpy(txtvalue, instance->values[i], sizeof(txtvalue));
+
+      num_txt = cupsAddOption(txtname, txtvalue, num_txt, &txt);
+    }
+
+    (resolve->cb)(resolve, resolve->cb_data, CUPS_DNSSD_FLAGS_NONE, instance->dwInterfaceIndex, fullname, hostname, instance->wPort, num_txt, txt);
+
+    cupsFreeOptions(num_txt, txt);
+  }
+  else
+  {
+    (resolve->cb)(resolve, resolve->cb_data, CUPS_DNSSD_FLAGS_ERROR, /*if_index*/0, /*fullname*/NULL, /*host*/NULL, /*port*/0, /*num_txt*/0, /*txt*/NULL);
+  }
+}
+
+
+//
+// 'win32_service_cb()' - Handle service registration callbacks from WinDNS.
+//
+
+static void
+win32_service_cb(
+    DWORD                 status,      // I - Status
+    PVOID                 context,     // I - Service
+    PDNS_SERVICE_INSTANCE instance)    // I - New instance
+{
+  cups_dnssd_service_t *service = (cups_dnssd_service_t *)context;
+                                       // Service
+
+  (service->cb)(service, service->cb_data, status == ERROR_SUCCESS ? CUPS_DNSSD_FLAGS_NONE : CUPS_DNSSD_FLAGS_ERROR);
+
+  if (instance)
+    DnsServiceFreeInstance(instance);
+}
+
+
+//
+// 'win32_utf8cpy()' - Copy a UTF-16 string to a UTF-8 string.
+//
+
+static void
+win32_utf8cpy(char        *dst,                // I - Destination string
+              const WCHAR *src,                // I - Source string
+             size_t      dstsize)      // I - Size of destination string
+{
+  int  ch;                             // Current character
+
+
+  // Loop until we run out of characters or buffer space...
+  while (*src && dstsize > 4)
+  {
+    // Get the current character...
+    ch = *src++;
+
+    if (ch >= 0xd800 && ch <= 0xdbff && *src >= 0xdc00 && *src <= 0xdfff)
+    {
+      // Convert UTF-16 to unicode...
+      ch = ((ch - 0xd800) << 10) | (*src++ - 0xdc00);
+    }
+
+    if (ch < 0x80)
+    {
+      *dst++ = ch;
+    }
+    else if (ch < 0x800)
+    {
+      *dst++ = 0xc0 | (ch >> 6);
+      *dst++ = 0x80 | (ch & 0x3f);
+    }
+    else if (ch < 0x10000)
+    {
+      *dst++ = 0xe0 | (ch >> 12);
+      *dst++ = 0x80 | ((ch >> 6) & 0x3f);
+      *dst++ = 0x80 | (ch & 0x3f);
+    }
+    else
+    {
+      *dst++ = 0xf0 | (ch >> 18);
+      *dst++ = 0x80 | ((ch >> 12) & 0x3f);
+      *dst++ = 0x80 | ((ch >> 6) & 0x3f);
+      *dst++ = 0x80 | (ch & 0x3f);
+    }
+  }
+
+  // Nul-terminate the destination...
+  *dst = '\0';
+}
+
+
+//
+// 'win32_wstrcpy()' - Copy a UTF-8 string to a UTF-16 string.
+//
+
+static void
+win32_wstrcpy(WCHAR      *dst,         // I - Destination string
+              const char *src,         // I - Source string
+              size_t     dstsize)      // I - Size of destination
+{
+  int  ch;                             // Current character
+
+
+  // Adjust size from bytes to words...
+  dstsize /= sizeof(WCHAR);
+
+  // Loop until we run out of characters or buffer space...
+  while (*src && dstsize > 1)
+  {
+    // Get the current character...
+    if ((*src & 0xe0) == 0xc0)
+    {
+      // Two-byte UTF-8...
+      if ((src[1] & 0xc0) != 0x80)
+        break;
+
+      ch = ((src[0] & 0x1f) << 6) | (src[1] & 0x3f);
+      src += 2;
+    }
+    else if ((*src & 0xf0) == 0xe0)
+    {
+      // Three-byte UTF-8...
+      if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80)
+        break;
+
+      ch = ((src[0] & 0x1f) << 12) | ((src[1] & 0x3f) << 6) | (src[2] & 0x3f);
+      src += 3;
+    }
+    else if ((*src & 0xf8) == 0xf0)
+    {
+      // Four-byte UTF-8...
+      if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80 || (src[3] & 0xc0) != 0x80)
+        break;
+
+      ch = ((src[0] & 0x1f) << 18) | ((src[1] & 0x3f) << 12) | ((src[2] & 0x3f) << 6) | (src[3] & 0x3f);
+      src += 4;
+    }
+    else
+    {
+      // US ASCII...
+      ch = *src++;
+    }
+
+    // Map it to UTF-16...
+    if (ch < 0x10000)
+    {
+      // One-word UTF-16...
+      *dst++ = ch;
+      dstsize --;
+    }
+    else if (dstsize > 2)
+    {
+      // Two-word UTF-16...
+      *dst++ = 0xd800 | ((ch >> 12) & 0x3ff);
+      *dst++ = 0xdc00 | (ch & 0x3ff);
+
+      dstsize -= 2;
+    }
+    else
+    {
+      // Terminate early...
+      break;
+    }
+  }
+
+  // Nul-terminate the destination...
+  *dst = '\0';
+}
 
 
 #else // HAVE_AVAHI
@@ -2145,9 +2745,14 @@ avahi_browse_cb(
   cups_dnssd_flags_t   cups_flags;     // CUPS DNS-SD flags
 
 
+  DEBUG_printf("3avahi_browse_cb(browser=%p, if_index=%u, protocol=%u, event=%d, name=\"%s\", type=\"%s\", domain=\"%s\", flags=%u, browse=%p)", (void *)browser, (unsigned)if_index, (unsigned)protocol, event, name, type, domain, (unsigned)flags, (void *)browse);
+
   (void)protocol;
   (void)flags;
 
+  if (!name)
+    return;
+
   switch (event)
   {
     case AVAHI_BROWSER_NEW :
@@ -2397,7 +3002,7 @@ avahi_resolve_cb(
     cups_dnssd_resolve_t   *resolve)   // I - Resolve request
 {
   AvahiStringList *txtpair;            // Current pair
-  size_t       num_txt = 0;            // Number of TXT key/value pairs
+  int          num_txt = 0;            // Number of TXT key/value pairs
   cups_option_t        *txt = NULL;            // TXT key/value pairs
   char         fullname[1024];         // Full service name
 
@@ -2430,13 +3035,13 @@ avahi_resolve_cb(
 
     avahi_string_list_get_pair(txtpair, &key, &value, NULL);
 
-    DEBUG_printf("4avahi_resolve_cb: txt[%u].name=\"%s\", .value=\"%s\"", (unsigned)num_txt, key, value);
+    DEBUG_printf("4avahi_resolve_cb: txt[%d].name=\"%s\", .value=\"%s\"", num_txt, key, value);
     num_txt = cupsAddOption(key, value, num_txt, &txt);
 
     avahi_free(key);
     avahi_free(value);
   }
-  DEBUG_printf("4avahi_resolve_cb: num_txt=%u", (unsigned)num_txt);
+  DEBUG_printf("4avahi_resolve_cb: num_txt=%d", num_txt);
 
   // Create a full name for the service...
   cupsDNSSDAssembleFullName(fullname, sizeof(fullname), name, type, domain);
index a9045e401ef6c8d82deb5fc716e12a08d0a98547..0556636367fcf69c7c965ea82fe2d0b7d600b04f 100644 (file)
@@ -3,41 +3,47 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 VisualStudioVersion = 15.0.28010.2036\r
 MinimumVisualStudioVersion = 10.0.40219.1\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcups2", "libcups2.vcxproj", "{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}"\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdnssd", "testdnssd.vcxproj", "{CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testfile", "testfile.vcxproj", "{CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testhttp", "testhttp.vcxproj", "{90B0058C-8393-411F-BD3B-E2C831D4E883}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cupstestppd", "cupstestppd.vcxproj", "{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipptool", "ipptool.vcxproj", "{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regex", "regex.vcxproj", "{18950A1B-D37A-40C7-B2DF-C12986C0526E}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
+       EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ippfind", "ippfind.vcxproj", "{B484DA0C-62C8-4C32-83B6-CCEB58968B85}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ippeveprinter", "ippeveprinter.vcxproj", "{82A03BC7-0746-4B85-8908-3C7A3FAA58A9}"\r
        ProjectSection(ProjectDependencies) = postProject\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83} = {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}\r
+               {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dnssdstub", "dnssdstub.vcxproj", "{C0899B3A-43E7-4BC3-A785-659E1FD2EA83}"\r
-EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|x64 = Debug|x64\r
@@ -48,6 +54,10 @@ Global
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Debug|x64.Build.0 = Debug|x64\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.ActiveCfg = Release|x64\r
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}.Release|x64.Build.0 = Release|x64\r
+               {CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}.Debug|x64.ActiveCfg = Debug|x64\r
+               {CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}.Debug|x64.Build.0 = Debug|x64\r
+               {CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}.Release|x64.ActiveCfg = Release|x64\r
+               {CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}.Release|x64.Build.0 = Release|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.ActiveCfg = Debug|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Debug|x64.Build.0 = Debug|x64\r
                {CE75FC5F-E0CF-45DC-AD27-84666D3FBA30}.Release|x64.ActiveCfg = Release|x64\r
@@ -76,10 +86,6 @@ Global
                {82A03BC7-0746-4B85-8908-3C7A3FAA58A9}.Debug|x64.Build.0 = Debug|x64\r
                {82A03BC7-0746-4B85-8908-3C7A3FAA58A9}.Release|x64.ActiveCfg = Release|x64\r
                {82A03BC7-0746-4B85-8908-3C7A3FAA58A9}.Release|x64.Build.0 = Release|x64\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}.Debug|x64.ActiveCfg = Debug|x64\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}.Debug|x64.Build.0 = Debug|x64\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}.Release|x64.ActiveCfg = Release|x64\r
-               {C0899B3A-43E7-4BC3-A785-659E1FD2EA83}.Release|x64.Build.0 = Release|x64\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
diff --git a/vcnet/dns_sd.c b/vcnet/dns_sd.c
deleted file mode 100644 (file)
index 341fc09..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Dynamic wrapper for Bonjour SDK for Windows.
- *
- * Copyright © 2020-2024 by OpenPrinting.
- * Copyright 2018 by Apple Inc.
- *
- * Licensed under Apache License v2.0.  See the file "LICENSE" for more
- * information.
- */
-
-//#include <cups/http-private.h>
-#include <cups/thread.h>
-#include "dns_sd.h"
-
-
-/*
- * Pointers for functions...
- */
-
-static int             dnssd_initialized = 0;
-static cups_mutex_t    dnssd_mutex = CUPS_MUTEX_INITIALIZER;
-static DNSServiceErrorType (*dnssd_add_record)(DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint16_t rrtype, uint16_t rdlen, const void *rdata, uint32_t ttl);
-static DNSServiceErrorType (*dnssd_browse)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, DNSServiceBrowseReply callBack, void *context);
-static DNSServiceErrorType (*dnssd_construct_full_name)(char * const fullName, const char * const service, const char * const regtype, const char * const domain);
-static DNSServiceErrorType (*dnssd_create_connection)(DNSServiceRef *sdRef);
-static DNSServiceErrorType (*dnssd_process_result)(DNSServiceRef sdRef);
-static DNSServiceErrorType (*dnssd_query_record)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callBack, void *context);
-static void (*dnssd_deallocate)(DNSServiceRef sdRef);
-static int (*dnssd_sock_fd)(DNSServiceRef sdRef);
-static DNSServiceErrorType (*dnssd_register)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, const char *host, uint16_t port, uint16_t txtLen, const void *txtRecord, DNSServiceRegisterReply callBack, void *context);
-static DNSServiceErrorType (*dnssd_remove_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags);
-static DNSServiceErrorType (*dnssd_resolve)(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, DNSServiceResolveReply callBack, void *context);
-static DNSServiceErrorType (*dnssd_update_record)(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, uint16_t rdlen, const void *rdata, uint32_t ttl);
-
-static void (*dnssd_txt_create)(TXTRecordRef *txtRecord, uint16_t bufferLen, void *buffer);
-static void (*dnssd_txt_deallocate)(TXTRecordRef *txtRecord);
-static const void *(*dnssd_txt_get_bytes_ptr)(const TXTRecordRef *txtRecord);
-static uint16_t (*dnssd_txt_get_count)(uint16_t txtLen, const void *txtRecord);
-static uint16_t (*dnssd_txt_get_length)(const TXTRecordRef *txtRecord);
-static DNSServiceErrorType (*dnssd_txt_get_item_at_index)(uint16_t txtLen, const void *txtRecord, uint16_t itemIndex, uint16_t keyBufLen, char *key, uint8_t *valueLen, const void **value);
-static const void *(*dnssd_txt_get_value_ptr)(uint16_t txtLen, const void *txtRecord, const char *key, uint8_t *valueLen);
-static DNSServiceErrorType (*dnssd_txt_set_value)(TXTRecordRef *txtRecord, const char *key, uint8_t valueSize, const void *value);
-
-
-/*
- * Function to initialize pointers...
- */
-
-static void
-dnssd_init(void)
-{
-  cupsMutexLock(&dnssd_mutex);
-  if (!dnssd_initialized)
-  {
-    HINSTANCE  dll_handle = LoadLibraryA("dnssd.dll");
-
-    if (dll_handle)
-    {
-      dnssd_add_record          = (DNSServiceErrorType (*)(DNSServiceRef, DNSRecordRef *, DNSServiceFlags, uint16_t, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceAddRecord");
-      dnssd_browse              = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, DNSServiceBrowseReply, void *))GetProcAddress(dll_handle, "DNSServiceBrowse");
-      dnssd_construct_full_name = (DNSServiceErrorType(*)(char * const, const char * const, const char * const, const char * const))GetProcAddress(dll_handle, "DNSServiceConstructFullName");
-      dnssd_create_connection   = (DNSServiceErrorType(*)(DNSServiceRef *))GetProcAddress(dll_handle, "DNSServiceCreateConnection");
-      dnssd_deallocate          = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefDeallocate");
-      dnssd_process_result      = (DNSServiceErrorType(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceProcessResult");
-      dnssd_query_record        = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, uint16_t, uint16_t, DNSServiceQueryRecordReply, void *))GetProcAddress(dll_handle, "DNSServiceQueryRecord");
-      dnssd_register            = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, const char *, uint16_t, uint16_t, const void *, DNSServiceRegisterReply, void *))GetProcAddress(dll_handle, "DNSServiceRegister");
-      dnssd_remove_record       = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags))GetProcAddress(dll_handle, "DNSServiceRemoveRecord");
-      dnssd_resolve             = (DNSServiceErrorType(*)(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *, const char *, const char *, DNSServiceResolveReply, void *))GetProcAddress(dll_handle, "DNSServiceResolve");
-      dnssd_sock_fd             = (int(*)(DNSServiceRef))GetProcAddress(dll_handle, "DNSServiceRefSockFD");
-      dnssd_update_record       = (DNSServiceErrorType(*)(DNSServiceRef, DNSRecordRef, DNSServiceFlags, uint16_t, const void *, uint32_t))GetProcAddress(dll_handle, "DNSServiceUpdateRecord");
-
-      dnssd_txt_create          = (void (*)(TXTRecordRef *, uint16_t, void *))GetProcAddress(dll_handle, "TXTRecordCreate");
-      dnssd_txt_deallocate      = (void (*)(TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordDeallocate");
-      dnssd_txt_get_bytes_ptr   = (const void *(*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetBytesPtr");
-      dnssd_txt_get_count       = (uint16_t (*)(uint16_t, const void *))GetProcAddress(dll_handle, "TXTRecordGetCount");
-      dnssd_txt_get_item_at_index = (DNSServiceErrorType (*)(uint16_t, const void *, uint16_t, uint16_t, char *, uint8_t *, const void **))GetProcAddress(dll_handle, "TXTRecordGetItemAtIndex");
-      dnssd_txt_get_length      = (uint16_t (*)(const TXTRecordRef *))GetProcAddress(dll_handle, "TXTRecordGetLength");
-      dnssd_txt_get_value_ptr   = (const void *(*)(uint16_t, const void *, const char *, uint8_t *))GetProcAddress(dll_handle, "TXTRecordGetValuePtr");
-      dnssd_txt_set_value       = (DNSServiceErrorType (*)(TXTRecordRef *, const char *, uint8_t, const void *))GetProcAddress(dll_handle, "TXTRecordSetValue");
-    }
-
-    dnssd_initialized = 1;
-  }
-  cupsMutexUnlock(&dnssd_mutex);
-}
-
-
-// DNSServiceAddRecord
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags                     flags,
-    uint16_t                            rrtype,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_add_record)
-    return (*dnssd_add_record)(sdRef, RecordRef, flags, rrtype, rdlen, rdata, ttl);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceBrowse
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *regtype,
-    const char                          *domain,    /* may be NULL */
-    DNSServiceBrowseReply               callBack,
-    void                                *context    /* may be NULL */
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_browse)
-    return (*dnssd_browse)(sdRef, flags, interfaceIndex, regtype, domain, callBack, context);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceConstructFullName
-DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
-    (
-    char                            * const fullName,
-    const char                      * const service,      /* may be NULL */
-    const char                      * const regtype,
-    const char                      * const domain
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_construct_full_name)
-    return (*dnssd_construct_full_name)(fullName, service, regtype, domain);
-  else
-    return (-1);
-}
-
-
-// DNSServiceCreateConnection
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_create_connection)
-    return (*dnssd_create_connection)(sdRef);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceProcessResult
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_process_result)
-    return (*dnssd_process_result)(sdRef);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceQueryRecord
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *fullname,
-    uint16_t                            rrtype,
-    uint16_t                            rrclass,
-    DNSServiceQueryRecordReply          callBack,
-    void                                *context  /* may be NULL */
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_query_record)
-    return (*dnssd_query_record)(sdRef, flags, interfaceIndex, fullname, rrtype, rrclass, callBack, context);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceRefDeallocate
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_deallocate)
-    (*dnssd_deallocate)(sdRef);
-}
-
-
-// DNSServiceRefSockFD
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_sock_fd)
-    return (*dnssd_sock_fd)(sdRef);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceRegister
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *name,         /* may be NULL */
-    const char                          *regtype,
-    const char                          *domain,       /* may be NULL */
-    const char                          *host,         /* may be NULL */
-    uint16_t                            port,          /* In network byte order */
-    uint16_t                            txtLen,
-    const void                          *txtRecord,    /* may be NULL */
-    DNSServiceRegisterReply             callBack,      /* may be NULL */
-    void                                *context       /* may be NULL */
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_register)
-    return (*dnssd_register)(sdRef, flags, interfaceIndex, name, regtype, domain, host, port, txtLen, txtRecord, callBack, context);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceRemoveRecord
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-    (
-    DNSServiceRef                 sdRef,
-    DNSRecordRef                  RecordRef,
-    DNSServiceFlags               flags
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_remove_record)
-    return (*dnssd_remove_record)(sdRef, RecordRef, flags);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceResolve
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    DNSServiceResolveReply              callBack,
-    void                                *context  /* may be NULL */
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_resolve)
-    return (*dnssd_resolve)(sdRef, flags, interfaceIndex, name, regtype, domain, callBack, context);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// DNSServiceUpdateRecord
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        RecordRef,     /* may be NULL */
-    DNSServiceFlags                     flags,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_update_record)
-    return (*dnssd_update_record)(sdRef, RecordRef, flags, rdlen, rdata, ttl);
-  else
-    return (kDNSServiceErr_ServiceNotRunning);
-}
-
-
-// TXTRecordCreate
-void DNSSD_API
-TXTRecordCreate(
-    TXTRecordRef     *txtRecord,
-    uint16_t         bufferLen,
-    void             *buffer)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_create)
-    (*dnssd_txt_create)(txtRecord, bufferLen, buffer);
-}
-
-
-// TXTRecordDeallocate
-void DNSSD_API TXTRecordDeallocate
-    (
-    TXTRecordRef     *txtRecord
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_deallocate)
-    (*dnssd_txt_deallocate)(txtRecord);
-}
-
-
-// TXTRecordGetBytesPtr
-const void * DNSSD_API TXTRecordGetBytesPtr
-    (
-    const TXTRecordRef *txtRecord
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_get_bytes_ptr)
-    return (*dnssd_txt_get_bytes_ptr)(txtRecord);
-  else
-    return (NULL);
-}
-
-
-// TXTRecordGetLength
-uint16_t DNSSD_API TXTRecordGetLength
-    (
-    const TXTRecordRef *txtRecord
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_get_length)
-    return (*dnssd_txt_get_length)(txtRecord);
-  else
-    return (0);
-}
-
-
-// TXTRecordSetValue
-DNSServiceErrorType DNSSD_API TXTRecordSetValue
-    (
-    TXTRecordRef     *txtRecord,
-    const char       *key,
-    uint8_t          valueSize,        /* may be zero */
-    const void       *value            /* may be NULL */
-    )
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_set_value)
-    return (*dnssd_txt_set_value)(txtRecord, key, valueSize, value);
-  else
-    return (-1);
-}
-
-
-// TXTRecordGetCount
-uint16_t DNSSD_API
-TXTRecordGetCount(
-    uint16_t         txtLen,
-    const void       *txtRecord)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_get_count)
-    return (*dnssd_txt_get_count)(txtLen, txtRecord);
-  else
-    return (0);
-}
-
-
-// TXTRecordGetItemAtIndex
-DNSServiceErrorType DNSSD_API
-TXTRecordGetItemAtIndex(
-    uint16_t         txtLen,
-    const void       *txtRecord,
-    uint16_t         itemIndex,
-    uint16_t         keyBufLen,
-    char             *key,
-    uint8_t          *valueLen,
-    const void       **value)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_get_item_at_index)
-    return (*dnssd_txt_get_item_at_index)(txtLen, txtRecord, itemIndex, keyBufLen, key, valueLen, value);
-  else
-    return (-1);
-}
-
-
-// TXTRecordGetValuePtr
-const void * DNSSD_API
-TXTRecordGetValuePtr(
-    uint16_t         txtLen,
-    const void       *txtRecord,
-    const char       *key,
-    uint8_t          *valueLen)
-{
-  if (!dnssd_initialized)
-    dnssd_init();
-
-  if (dnssd_txt_get_value_ptr)
-    return (*dnssd_txt_get_value_ptr)(txtLen, txtRecord, key, valueLen);
-  else
-    return (NULL);
-}
diff --git a/vcnet/dns_sd.h b/vcnet/dns_sd.h
deleted file mode 100644 (file)
index afd6ce7..0000000
+++ /dev/null
@@ -1,2435 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright © 2020-2024 by OpenPrinting.
- * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*! @header     DNS Service Discovery
- *
- * @discussion  This section describes the functions, callbacks, and data structures
- *              that make up the DNS Service Discovery API.
- *
- *              The DNS Service Discovery API is part of Bonjour, Apple's implementation
- *              of zero-configuration networking (ZEROCONF).
- *
- *              Bonjour allows you to register a network service, such as a
- *              printer or file server, so that it can be found by name or browsed
- *              for by service type and domain. Using Bonjour, applications can
- *              discover what services are available on the network, along with
- *              all the information -- such as name, IP address, and port --
- *              necessary to access a particular service.
- *
- *              In effect, Bonjour combines the functions of a local DNS server and
- *              AppleTalk. Bonjour allows applications to provide user-friendly printer
- *              and server browsing, among other things, over standard IP networks.
- *              This behavior is a result of combining protocols such as multicast and
- *              DNS to add new functionality to the network (such as multicast DNS).
- *
- *              Bonjour gives applications easy access to services over local IP
- *              networks without requiring the service or the application to support
- *              an AppleTalk or a Netbeui stack, and without requiring a DNS server
- *              for the local network.
- */
-
-
-/* _DNS_SD_H contains the mDNSResponder version number for this header file, formatted as follows:
- *   Major part of the build number * 10000 +
- *   minor part of the build number *   100
- * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
- * version 1080400. This allows C code to do simple greater-than and less-than comparisons:
- * e.g. an application that requires the DNSServiceGetProperty() call (new in mDNSResponder-126) can check:
- *
- *   #if _DNS_SD_H+0 >= 1260000
- *   ... some C code that calls DNSServiceGetProperty() ...
- *   #endif
- *
- * The version defined in this header file symbol allows for compile-time
- * checking, so that C code building with earlier versions of the header file
- * can avoid compile errors trying to use functions that aren't even defined
- * in those earlier versions. Similar checks may also be performed at run-time:
- *  => weak linking -- to avoid link failures if run with an earlier
- *     version of the library that's missing some desired symbol, or
- *  => DNSServiceGetProperty(DaemonVersion) -- to verify whether the running daemon
- *     ("system service" on Windows) meets some required minimum functionality level.
- */
-
-#ifndef _DNS_SD_H
-#define _DNS_SD_H 3331000
-
-#ifdef  __cplusplus
-    extern "C" {
-#endif
-
-/* Set to 1 if libdispatch is supported
- * Note: May also be set by project and/or Makefile
- */
-#ifndef _DNS_SD_LIBDISPATCH
-#define _DNS_SD_LIBDISPATCH 0
-#endif /* ndef _DNS_SD_LIBDISPATCH */
-
-/* standard calling convention under Win32 is __stdcall */
-/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
-/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
-#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
-#define DNSSD_API __stdcall
-#else
-#define DNSSD_API
-#endif
-
-/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
-#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
-#include <sys/types.h>
-
-/* Likewise, on Sun, standard integer types are in sys/types.h */
-#elif defined(__sun__)
-#include <sys/types.h>
-
-/* EFI does not have stdint.h, or anything else equivalent */
-#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
-#include "Tiano.h"
-#if !defined(_STDINT_H_)
-typedef UINT8       uint8_t;
-typedef INT8        int8_t;
-typedef UINT16      uint16_t;
-typedef INT16       int16_t;
-typedef UINT32      uint32_t;
-typedef INT32       int32_t;
-#endif
-/* Windows has its own differences */
-#elif defined(_WIN32)
-#include <windows.h>
-#define _UNUSED
-#ifndef _MSL_STDINT_H
-typedef UINT8       uint8_t;
-typedef INT8        int8_t;
-typedef UINT16      uint16_t;
-typedef INT16       int16_t;
-typedef UINT32      uint32_t;
-typedef INT32       int32_t;
-#endif
-
-/* All other Posix platforms use stdint.h */
-#else
-#include <stdint.h>
-#endif
-
-#if _DNS_SD_LIBDISPATCH
-#include <dispatch/dispatch.h>
-#endif
-
-/* DNSServiceRef, DNSRecordRef
- *
- * Opaque internal data types.
- * Note: client is responsible for serializing access to these structures if
- * they are shared between concurrent threads.
- */
-
-typedef struct _DNSServiceRef_t *DNSServiceRef;
-typedef struct _DNSRecordRef_t *DNSRecordRef;
-
-struct sockaddr;
-
-/*! @enum General flags
- * Most DNS-SD API functions and callbacks include a DNSServiceFlags parameter.
- * As a general rule, any given bit in the 32-bit flags field has a specific fixed meaning,
- * regardless of the function or callback being used. For any given function or callback,
- * typically only a subset of the possible flags are meaningful, and all others should be zero.
- * The discussion section for each API call describes which flags are valid for that call
- * and callback. In some cases, for a particular call, it may be that no flags are currently
- * defined, in which case the DNSServiceFlags parameter exists purely to allow future expansion.
- * In all cases, developers should expect that in future releases, it is possible that new flag
- * values will be defined, and write code with this in mind. For example, code that tests
- *     if (flags == kDNSServiceFlagsAdd) ...
- * will fail if, in a future release, another bit in the 32-bit flags field is also set.
- * The reliable way to test whether a particular bit is set is not with an equality test,
- * but with a bitwise mask:
- *     if (flags & kDNSServiceFlagsAdd) ...
- */
-enum
-    {
-    kDNSServiceFlagsMoreComing          = 0x1,
-    /* MoreComing indicates to a callback that at least one more result is
-     * queued and will be delivered following immediately after this one.
-     * When the MoreComing flag is set, applications should not immediately
-     * update their UI, because this can result in a great deal of ugly flickering
-     * on the screen, and can waste a great deal of CPU time repeatedly updating
-     * the screen with content that is then immediately erased, over and over.
-     * Applications should wait until until MoreComing is not set, and then
-     * update their UI when no more changes are imminent.
-     * When MoreComing is not set, that doesn't mean there will be no more
-     * answers EVER, just that there are no more answers immediately
-     * available right now at this instant. If more answers become available
-     * in the future they will be delivered as usual.
-     */
-
-    kDNSServiceFlagsAdd                 = 0x2,
-    kDNSServiceFlagsDefault             = 0x4,
-    /* Flags for domain enumeration and browse/query reply callbacks.
-     * "Default" applies only to enumeration and is only valid in
-     * conjunction with "Add". An enumeration callback with the "Add"
-     * flag NOT set indicates a "Remove", i.e. the domain is no longer
-     * valid.
-     */
-
-    kDNSServiceFlagsNoAutoRename        = 0x8,
-    /* Flag for specifying renaming behavior on name conflict when registering
-     * non-shared records. By default, name conflicts are automatically handled
-     * by renaming the service. NoAutoRename overrides this behavior - with this
-     * flag set, name conflicts will result in a callback. The NoAutorename flag
-     * is only valid if a name is explicitly specified when registering a service
-     * (i.e. the default name is not used.)
-     */
-
-    kDNSServiceFlagsShared              = 0x10,
-    kDNSServiceFlagsUnique              = 0x20,
-    /* Flag for registering individual records on a connected
-     * DNSServiceRef. Shared indicates that there may be multiple records
-     * with this name on the network (e.g. PTR records). Unique indicates that the
-     * record's name is to be unique on the network (e.g. SRV records).
-     */
-
-    kDNSServiceFlagsBrowseDomains       = 0x40,
-    kDNSServiceFlagsRegistrationDomains = 0x80,
-    /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
-     * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
-     * enumerates domains recommended for registration.
-     */
-
-    kDNSServiceFlagsLongLivedQuery      = 0x100,
-    /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
-
-    kDNSServiceFlagsAllowRemoteQuery    = 0x200,
-    /* Flag for creating a record for which we will answer remote queries
-     * (queries from hosts more than one hop away; hosts not directly connected to the local link).
-     */
-
-    kDNSServiceFlagsForceMulticast      = 0x400,
-    /* Flag for signifying that a query or registration should be performed exclusively via multicast
-     * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
-     */
-
-    kDNSServiceFlagsForce               = 0x800,
-    /* Flag for signifying a "stronger" variant of an operation.
-     * Currently defined only for DNSServiceReconfirmRecord(), where it forces a record to
-     * be removed from the cache immediately, instead of querying for a few seconds before
-     * concluding that the record is no longer valid and then removing it. This flag should
-     * be used with caution because if a service browsing PTR record is indeed still valid
-     * on the network, forcing its removal will result in a user-interface flap -- the
-     * discovered service instance will disappear, and then re-appear moments later.
-     */
-
-    kDNSServiceFlagsReturnIntermediates = 0x1000,
-    /* Flag for returning intermediate results.
-     * For example, if a query results in an authoritative NXDomain (name does not exist)
-     * then that result is returned to the client. However the query is not implicitly
-     * cancelled -- it remains active and if the answer subsequently changes
-     * (e.g. because a VPN tunnel is subsequently established) then that positive
-     * result will still be returned to the client.
-     * Similarly, if a query results in a CNAME record, then in addition to following
-     * the CNAME referral, the intermediate CNAME result is also returned to the client.
-     * When this flag is not set, NXDomain errors are not returned, and CNAME records
-     * are followed silently without informing the client of the intermediate steps.
-     * (In earlier builds this flag was briefly calledkDNSServiceFlagsReturnCNAME)
-     */
-
-    kDNSServiceFlagsNonBrowsable        = 0x2000,
-    /* A service registered with the NonBrowsable flag set can be resolved using
-     * DNSServiceResolve(), but will not be discoverable using DNSServiceBrowse().
-     * This is for cases where the name is actually a GUID; it is found by other means;
-     * there is no end-user benefit to browsing to find a long list of opaque GUIDs.
-     * Using the NonBrowsable flag creates SRV+TXT without the cost of also advertising
-     * an associated PTR record.
-     */
-
-    kDNSServiceFlagsShareConnection     = 0x4000,
-    /* For efficiency, clients that perform many concurrent operations may want to use a
-     * single Unix Domain Socket connection with the background daemon, instead of having a
-     * separate connection for each independent operation. To use this mode, clients first
-     * call DNSServiceCreateConnection(&MainRef) to initialize the main DNSServiceRef.
-     * For each subsequent operation that is to share that same connection, the client copies
-     * the MainRef, and then passes the address of that copy, setting the ShareConnection flag
-     * to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef;
-     * it's a copy of an existing DNSServiceRef whose connection information should be reused.
-     *
-     * For example:
-     *
-     * DNSServiceErrorType error;
-     * DNSServiceRef MainRef;
-     * error = DNSServiceCreateConnection(&MainRef);
-     * if (error) ...
-     * DNSServiceRef BrowseRef = MainRef;  // Important: COPY the primary DNSServiceRef first...
-     * error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, ...); // then use the copy
-     * if (error) ...
-     * ...
-     * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
-     * DNSServiceRefDeallocate(MainRef);   // Terminate the shared connection
-     *
-     * Notes:
-     *
-     * 1. Collective kDNSServiceFlagsMoreComing flag
-     * When callbacks are invoked using a shared DNSServiceRef, the
-     * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
-     * operations sharing the same parent DNSServiceRef. If the MoreComing flag is
-     * set it means that there are more results queued on this parent DNSServiceRef,
-     * but not necessarily more results for this particular callback function.
-     * The implication of this for client programmers is that when a callback
-     * is invoked with the MoreComing flag set, the code should update its
-     * internal data structures with the new result, and set a variable indicating
-     * that its UI needs to be updated. Then, later when a callback is eventually
-     * invoked with the MoreComing flag not set, the code should update *all*
-     * stale UI elements related to that shared parent DNSServiceRef that need
-     * updating, not just the UI elements related to the particular callback
-     * that happened to be the last one to be invoked.
-     *
-     * 2. Canceling operations and kDNSServiceFlagsMoreComing
-     * Whenever you cancel any operation for which you had deferred UI updates
-     * waiting because of a kDNSServiceFlagsMoreComing flag, you should perform
-     * those deferred UI updates. This is because, after cancelling the operation,
-     * you can no longer wait for a callback *without* MoreComing set, to tell
-     * you do perform your deferred UI updates (the operation has been canceled,
-     * so there will be no more callbacks). An implication of the collective
-     * kDNSServiceFlagsMoreComing flag for shared connections is that this
-     * guideline applies more broadly -- any time you cancel an operation on
-     * a shared connection, you should perform all deferred UI updates for all
-     * operations sharing that connection. This is because the MoreComing flag
-     * might have been referring to events coming for the operation you canceled,
-     * which will now not be coming because the operation has been canceled.
-     *
-     * 3. Only share DNSServiceRef's created with DNSServiceCreateConnection
-     * Calling DNSServiceCreateConnection(&ref) creates a special shareable DNSServiceRef.
-     * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
-     * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
-     *
-     * 4. Don't Double-Deallocate
-     * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
-     * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
-     * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
-     * automatically terminates the shared connection and all operations that were still using it.
-     * After doing this, DO NOT then attempt to deallocate any remaining subordinate DNSServiceRef's.
-     * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
-     * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
-     * to freed memory, leading to crashes or other equally undesirable results.
-     *
-     * 5. Thread Safety
-     * The dns_sd.h API does not presuppose any particular threading model, and consequently
-     * does no locking of its own (which would require linking some specific threading library).
-     * If client code calls API routines on the same DNSServiceRef concurrently
-     * from multiple threads, it is the client's responsibility to use a mutext
-     * lock or take similar appropriate precautions to serialize those calls.
-     */
-
-    kDNSServiceFlagsSuppressUnusable    = 0x8000,
-    /*
-     * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
-     * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
-     * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses
-     * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly,
-     * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
-     * "hostname".
-     */
-
-    kDNSServiceFlagsTimeout            = 0x10000,
-    /*
-     * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is
-     * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped
-     * is determined by the system and cannot be configured by the user. The query will be stopped irrespective
-     * of whether a response was given earlier or not. When the query is stopped, the callback will be called
-     * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo
-     * and zero length rdata will be returned for DNSServiceQueryRecord.
-     */
-
-    kDNSServiceFlagsIncludeP2P          = 0x20000,
-    /*
-     * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified.
-     * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces.
-     */
-    kDNSServiceFlagsWakeOnResolve      = 0x40000
-    /*
-     * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
-     * to wake up the client.
-     */
-    };
-
-/* Possible protocols for DNSServiceNATPortMappingCreate(). */
-enum
-    {
-    kDNSServiceProtocol_IPv4 = 0x01,
-    kDNSServiceProtocol_IPv6 = 0x02,
-    /* 0x04 and 0x08 reserved for future internetwork protocols */
-
-    kDNSServiceProtocol_UDP  = 0x10,
-    kDNSServiceProtocol_TCP  = 0x20
-    /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960]
-     * or DCCP [RFC 4340]. If future NAT gateways are created that support port
-     * mappings for these protocols, new constants will be defined here.
-     */
-    };
-
-/*
- * The values for DNS Classes and Types are listed in RFC 1035, and are available
- * on every OS in its DNS header file. Unfortunately every OS does not have the
- * same header file containing DNS Class and Type constants, and the names of
- * the constants are not consistent. For example, BIND 8 uses "T_A",
- * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
- * For this reason, these constants are also listed here, so that code using
- * the DNS-SD programming APIs can use these constants, so that the same code
- * can compile on all our supported platforms.
- */
-
-enum
-    {
-    kDNSServiceClass_IN       = 1       /* Internet */
-    };
-
-enum
-    {
-    kDNSServiceType_A          = 1,      /* Host address. */
-    kDNSServiceType_NS         = 2,      /* Authoritative server. */
-    kDNSServiceType_MD         = 3,      /* Mail destination. */
-    kDNSServiceType_MF         = 4,      /* Mail forwarder. */
-    kDNSServiceType_CNAME      = 5,      /* Canonical name. */
-    kDNSServiceType_SOA        = 6,      /* Start of authority zone. */
-    kDNSServiceType_MB         = 7,      /* Mailbox domain name. */
-    kDNSServiceType_MG         = 8,      /* Mail group member. */
-    kDNSServiceType_MR         = 9,      /* Mail rename name. */
-    kDNSServiceType_NULL       = 10,     /* Null resource record. */
-    kDNSServiceType_WKS        = 11,     /* Well known service. */
-    kDNSServiceType_PTR        = 12,     /* Domain name pointer. */
-    kDNSServiceType_HINFO      = 13,     /* Host information. */
-    kDNSServiceType_MINFO      = 14,     /* Mailbox information. */
-    kDNSServiceType_MX         = 15,     /* Mail routing information. */
-    kDNSServiceType_TXT        = 16,     /* One or more text strings (NOT "zero or more..."). */
-    kDNSServiceType_RP         = 17,     /* Responsible person. */
-    kDNSServiceType_AFSDB      = 18,     /* AFS cell database. */
-    kDNSServiceType_X25        = 19,     /* X_25 calling address. */
-    kDNSServiceType_ISDN       = 20,     /* ISDN calling address. */
-    kDNSServiceType_RT         = 21,     /* Router. */
-    kDNSServiceType_NSAP       = 22,     /* NSAP address. */
-    kDNSServiceType_NSAP_PTR   = 23,     /* Reverse NSAP lookup (deprecated). */
-    kDNSServiceType_SIG        = 24,     /* Security signature. */
-    kDNSServiceType_KEY        = 25,     /* Security key. */
-    kDNSServiceType_PX         = 26,     /* X.400 mail mapping. */
-    kDNSServiceType_GPOS       = 27,     /* Geographical position (withdrawn). */
-    kDNSServiceType_AAAA       = 28,     /* IPv6 Address. */
-    kDNSServiceType_LOC        = 29,     /* Location Information. */
-    kDNSServiceType_NXT        = 30,     /* Next domain (security). */
-    kDNSServiceType_EID        = 31,     /* Endpoint identifier. */
-    kDNSServiceType_NIMLOC     = 32,     /* Nimrod Locator. */
-    kDNSServiceType_SRV        = 33,     /* Server Selection. */
-    kDNSServiceType_ATMA       = 34,     /* ATM Address */
-    kDNSServiceType_NAPTR      = 35,     /* Naming Authority PoinTeR */
-    kDNSServiceType_KX         = 36,     /* Key Exchange */
-    kDNSServiceType_CERT       = 37,     /* Certification record */
-    kDNSServiceType_A6         = 38,     /* IPv6 Address (deprecated) */
-    kDNSServiceType_DNAME      = 39,     /* Non-terminal DNAME (for IPv6) */
-    kDNSServiceType_SINK       = 40,     /* Kitchen sink (experimental) */
-    kDNSServiceType_OPT        = 41,     /* EDNS0 option (meta-RR) */
-    kDNSServiceType_APL        = 42,     /* Address Prefix List */
-    kDNSServiceType_DS         = 43,     /* Delegation Signer */
-    kDNSServiceType_SSHFP      = 44,     /* SSH Key Fingerprint */
-    kDNSServiceType_IPSECKEY   = 45,     /* IPSECKEY */
-    kDNSServiceType_RRSIG      = 46,     /* RRSIG */
-    kDNSServiceType_NSEC       = 47,     /* Denial of Existence */
-    kDNSServiceType_DNSKEY     = 48,     /* DNSKEY */
-    kDNSServiceType_DHCID      = 49,     /* DHCP Client Identifier */
-    kDNSServiceType_NSEC3      = 50,     /* Hashed Authenticated Denial of Existence */
-    kDNSServiceType_NSEC3PARAM = 51,     /* Hashed Authenticated Denial of Existence */
-
-    kDNSServiceType_HIP        = 55,     /* Host Identity Protocol */
-
-    kDNSServiceType_SPF        = 99,     /* Sender Policy Framework for E-Mail */
-    kDNSServiceType_UINFO      = 100,    /* IANA-Reserved */
-    kDNSServiceType_UID        = 101,    /* IANA-Reserved */
-    kDNSServiceType_GID        = 102,    /* IANA-Reserved */
-    kDNSServiceType_UNSPEC     = 103,    /* IANA-Reserved */
-
-    kDNSServiceType_TKEY       = 249,    /* Transaction key */
-    kDNSServiceType_TSIG       = 250,    /* Transaction signature. */
-    kDNSServiceType_IXFR       = 251,    /* Incremental zone transfer. */
-    kDNSServiceType_AXFR       = 252,    /* Transfer zone of authority. */
-    kDNSServiceType_MAILB      = 253,    /* Transfer mailbox records. */
-    kDNSServiceType_MAILA      = 254,    /* Transfer mail agent records. */
-    kDNSServiceType_ANY        = 255     /* Wildcard match. */
-    };
-
-/* possible error code values */
-enum
-    {
-    kDNSServiceErr_NoError                   = 0,
-    kDNSServiceErr_Unknown                   = -65537,  /* 0xFFFE FFFF */
-    kDNSServiceErr_NoSuchName                = -65538,
-    kDNSServiceErr_NoMemory                  = -65539,
-    kDNSServiceErr_BadParam                  = -65540,
-    kDNSServiceErr_BadReference              = -65541,
-    kDNSServiceErr_BadState                  = -65542,
-    kDNSServiceErr_BadFlags                  = -65543,
-    kDNSServiceErr_Unsupported               = -65544,
-    kDNSServiceErr_NotInitialized            = -65545,
-    kDNSServiceErr_AlreadyRegistered         = -65547,
-    kDNSServiceErr_NameConflict              = -65548,
-    kDNSServiceErr_Invalid                   = -65549,
-    kDNSServiceErr_Firewall                  = -65550,
-    kDNSServiceErr_Incompatible              = -65551,  /* client library incompatible with daemon */
-    kDNSServiceErr_BadInterfaceIndex         = -65552,
-    kDNSServiceErr_Refused                   = -65553,
-    kDNSServiceErr_NoSuchRecord              = -65554,
-    kDNSServiceErr_NoAuth                    = -65555,
-    kDNSServiceErr_NoSuchKey                 = -65556,
-    kDNSServiceErr_NATTraversal              = -65557,
-    kDNSServiceErr_DoubleNAT                 = -65558,
-    kDNSServiceErr_BadTime                   = -65559,  /* Codes up to here existed in Tiger */
-    kDNSServiceErr_BadSig                    = -65560,
-    kDNSServiceErr_BadKey                    = -65561,
-    kDNSServiceErr_Transient                 = -65562,
-    kDNSServiceErr_ServiceNotRunning         = -65563,  /* Background daemon not running */
-    kDNSServiceErr_NATPortMappingUnsupported = -65564,  /* NAT doesn't support NAT-PMP or UPnP */
-    kDNSServiceErr_NATPortMappingDisabled    = -65565,  /* NAT supports NAT-PMP or UPnP but it's disabled by the administrator */
-    kDNSServiceErr_NoRouter                  = -65566,  /* No router currently configured (probably no network connectivity) */
-    kDNSServiceErr_PollingMode               = -65567,
-    kDNSServiceErr_Timeout                   = -65568
-
-    /* mDNS Error codes are in the range
-     * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
-    };
-
-/* Maximum length, in bytes, of a service name represented as a */
-/* literal C-String, including the terminating NULL at the end. */
-
-#define kDNSServiceMaxServiceName 64
-
-/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
-/* including the final trailing dot, and the C-String terminating NULL at the end. */
-
-#define kDNSServiceMaxDomainName 1009
-
-/*
- * Notes on DNS Name Escaping
- *   -- or --
- * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
- *
- * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below,
- * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules:
- *
- *   '\\' represents a single literal '\' in the name
- *   '\.' represents a single literal '.' in the name
- *   '\ddd', where ddd is a three-digit decimal value from 000 to 255,
- *        represents a single literal byte with that value.
- *   A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
- *
- * The exceptions, that do not use escaping, are the routines where the full
- * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
- * In these routines, the "servicename" is NOT escaped. It does not need to be, since
- * it is, by definition, just a single literal string. Any characters in that string
- * represent exactly what they are. The "regtype" portion is, technically speaking,
- * escaped, but since legal regtypes are only allowed to contain letters, digits,
- * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
- * portion is also escaped, though most domains in use on the public Internet
- * today, like regtypes, don't contain any characters that need to be escaped.
- * As DNS-SD becomes more popular, rich-text domains for service discovery will
- * become common, so software should be written to cope with domains with escaping.
- *
- * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
- * terminating NULL at the end). The regtype is of the form _service._tcp or
- * _service._udp, where the "service" part is 1-15 characters, which may be
- * letters, digits, or hyphens. The domain part of the three-part name may be
- * any legal domain, providing that the resulting servicename+regtype+domain
- * name does not exceed 256 bytes.
- *
- * For most software, these issues are transparent. When browsing, the discovered
- * servicenames should simply be displayed as-is. When resolving, the discovered
- * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
- * When a DNSServiceResolve() succeeds, the returned fullname is already in
- * the correct format to pass to standard system DNS APIs such as res_query().
- * For converting from servicename/regtype/domain to a single properly-escaped
- * full DNS name, the helper function DNSServiceConstructFullName() is provided.
- *
- * The following (highly contrived) example illustrates the escaping process.
- * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
- * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
- * The full (escaped) DNS name of this service's SRV record would be:
- * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
- */
-
-
-/*
- * Constants for specifying an interface index
- *
- * Specific interface indexes are identified via a 32-bit unsigned integer returned
- * by the if_nametoindex() family of calls.
- *
- * If the client passes 0 for interface index, that means "do the right thing",
- * which (at present) means, "if the name is in an mDNS local multicast domain
- * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
- * on all applicable interfaces, otherwise send via unicast to the appropriate
- * DNS server." Normally, most clients will use 0 for interface index to
- * automatically get the default sensible behaviour.
- *
- * If the client passes a positive interface index, then for multicast names that
- * indicates to do the operation only on that one interface. For unicast names the
- * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
- * a service, then that service will be found *only* by other local clients
- * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
- * or kDNSServiceInterfaceIndexAny.
- * If a client has a 'private' service, accessible only to other processes
- * running on the same machine, this allows the client to advertise that service
- * in a way such that it does not inadvertently appear in service lists on
- * all the other machines on the network.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
- * then it will find *all* records registered on that same local machine.
- * Clients explicitly wishing to discover *only* LocalOnly services can
- * accomplish this by inspecting the interfaceIndex of each service reported
- * to their DNSServiceBrowseReply() callback function, and discarding those
- * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
- *
- * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord,
- * and Resolve operations. It should not be used in other DNSService APIs.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
- *   DNSServiceQueryRecord, it restricts the operation to P2P.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
- *   mapped internally to kDNSServiceInterfaceIndexAny, because resolving
- *   a P2P service may create and/or enable an interface whose index is not
- *   known a priori. The resolve callback will indicate the index of the
- *   interface via which the service can be accessed.
- *
- * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
- * or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
- * to include P2P. In this case, if a service instance or the record being queried
- * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
- * as the interface index.
- */
-
-#define kDNSServiceInterfaceIndexAny 0
-#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
-#define kDNSServiceInterfaceIndexUnicast   ((uint32_t)-2)
-#define kDNSServiceInterfaceIndexP2P       ((uint32_t)-3)
-
-typedef uint32_t DNSServiceFlags;
-typedef uint32_t DNSServiceProtocol;
-typedef int32_t  DNSServiceErrorType;
-
-
-/*********************************************************************************************
- *
- * Version checking
- *
- *********************************************************************************************/
-
-/* DNSServiceGetProperty() Parameters:
- *
- * property:        The requested property.
- *                  Currently the only property defined is kDNSServiceProperty_DaemonVersion.
- *
- * result:          Place to store result.
- *                  For retrieving DaemonVersion, this should be the address of a uint32_t.
- *
- * size:            Pointer to uint32_t containing size of the result location.
- *                  For retrieving DaemonVersion, this should be sizeof(uint32_t).
- *                  On return the uint32_t is updated to the size of the data returned.
- *                  For DaemonVersion, the returned size is always sizeof(uint32_t), but
- *                  future properties could be defined which return variable-sized results.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
- *                  if the daemon (or "system service" on Windows) is not running.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceGetProperty
-    (
-    const char *property,  /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
-    void       *result,    /* Pointer to place to store result */
-    uint32_t   *size       /* size of result location */
-    );
-
-/*
- * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point
- * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t).
- *
- * On return, the 32-bit unsigned integer contains the version number, formatted as follows:
- *   Major part of the build number * 10000 +
- *   minor part of the build number *   100
- *
- * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
- * version 1080400. This allows applications to do simple greater-than and less-than comparisons:
- * e.g. an application that requires at least mDNSResponder-108.4 can check:
- *
- *   if (version >= 1080400) ...
- *
- * Example usage:
- *
- * uint32_t version;
- * uint32_t size = sizeof(version);
- * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
- * if (!err) printf("Bonjour version is %d.%d\n", version / 10000, version / 100 % 100);
- */
-
-#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
-
-
-/*********************************************************************************************
- *
- * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
- *
- *********************************************************************************************/
-
-/* DNSServiceRefSockFD()
- *
- * Access underlying Unix domain socket for an initialized DNSServiceRef.
- * The DNS Service Discovery implementation uses this socket to communicate between the client and
- * the mDNSResponder daemon. The application MUST NOT directly read from or write to this socket.
- * Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop
- * event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/
- * select/CFRunLoop etc.) indicates to the client that data is available for reading on the
- * socket, the client should call DNSServiceProcessResult(), which will extract the daemon's
- * reply from the socket, and pass it to the appropriate application callback. By using a run
- * loop or select(), results from the daemon can be processed asynchronously. Alternatively,
- * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
- * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
- * will block until data does become available, and then process the data and return to the caller.
- * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
- * in a timely fashion -- if the client allows a large backlog of data to build up the daemon
- * may terminate the connection.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
- *
- * return value:    The DNSServiceRef's underlying socket descriptor, or -1 on
- *                  error.
- */
-
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
-
-
-/* DNSServiceProcessResult()
- *
- * Read a reply from the daemon, calling the appropriate application callback. This call will
- * block until the daemon's response is received. Use DNSServiceRefSockFD() in
- * conjunction with a run loop or select() to determine the presence of a response from the
- * server before calling this function to process the reply without blocking. Call this function
- * at any point if it is acceptable to block until the daemon's response arrives. Note that the
- * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
- * a reply from the daemon - the daemon may terminate its connection with a client that does not
- * process the daemon's responses.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls
- *                  that take a callback parameter.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns
- *                  an error code indicating the specific failure that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
-
-
-/* DNSServiceRefDeallocate()
- *
- * Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
- * Any services or records registered with this DNSServiceRef will be deregistered. Any
- * Browse, Resolve, or Query operations called with this reference will be terminated.
- *
- * Note: If the reference's underlying socket is used in a run loop or select() call, it should
- * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
- * socket.
- *
- * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
- * created via this reference will be invalidated by this call - the resource records are
- * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
- * if the reference was initialized with DNSServiceRegister, and an extra resource record was
- * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
- * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
- * functions.
- *
- * Note: This call is to be used only with the DNSServiceRef defined by this API. It is
- * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based
- * DNSServiceDiscovery.h API.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
- *
- */
-
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
-
-
-/*********************************************************************************************
- *
- * Domain Enumeration
- *
- *********************************************************************************************/
-
-/* DNSServiceEnumerateDomains()
- *
- * Asynchronously enumerate domains available for browsing and registration.
- *
- * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
- * are to be found.
- *
- * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
- * and are escaped using standard DNS escaping rules.
- * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
- * A graphical browser displaying a hierarchical tree-structured view should cut
- * the names at the bare dots to yield individual labels, then de-escape each
- * label according to the escaping rules, and then display the resulting UTF-8 text.
- *
- * DNSServiceDomainEnumReply Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceEnumerateDomains().
- *
- * flags:           Possible values are:
- *                  kDNSServiceFlagsMoreComing
- *                  kDNSServiceFlagsAdd
- *                  kDNSServiceFlagsDefault
- *
- * interfaceIndex:  Specifies the interface on which the domain exists. (The index for a given
- *                  interface is determined via the if_nametoindex() family of calls.)
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
- *                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
- *
- * replyDomain:     The name of the domain.
- *
- * context:         The context pointer passed to DNSServiceEnumerateDomains.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceDomainEnumReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *replyDomain,
-    void                                *context
-    );
-
-
-/* DNSServiceEnumerateDomains() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the enumeration operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Possible values are:
- *                  kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
- *                  kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
- *                  for registration.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to look for domains.
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to enumerate domains on
- *                  all interfaces. See "Constants for specifying an interface index" for more details.
- *
- * callBack:        The function to be called when a domain is found or the call asynchronously
- *                  fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    DNSServiceDomainEnumReply           callBack,
-    void                                *context  /* may be NULL */
-    );
-
-
-/*********************************************************************************************
- *
- *  Service Registration
- *
- *********************************************************************************************/
-
-/* Register a service that is discovered via Browse() and Resolve() calls.
- *
- * DNSServiceRegisterReply() Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceRegister().
- *
- * flags:           When a name is successfully registered, the callback will be
- *                  invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
- *                  DNS-SD is in use, it is possible for a single service to get
- *                  more than one success callback (e.g. one in the "local" multicast
- *                  DNS domain, and another in a wide-area unicast DNS domain).
- *                  If a successfully-registered name later suffers a name conflict
- *                  or similar problem and has to be deregistered, the callback will
- *                  be invoked with the kDNSServiceFlagsAdd flag not set. The callback
- *                  is *not* invoked in the case where the caller explicitly terminates
- *                  the service registration by calling DNSServiceRefDeallocate(ref);
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts,
- *                  if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- * name:            The service name registered (if the application did not specify a name in
- *                  DNSServiceRegister(), this indicates what name was automatically chosen).
- *
- * regtype:         The type of service registered, as it was passed to the callout.
- *
- * domain:          The domain on which the service was registered (if the application did not
- *                  specify a domain in DNSServiceRegister(), this indicates the default domain
- *                  on which the service was registered).
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceRegisterReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    DNSServiceErrorType                 errorCode,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    void                                *context
-    );
-
-
-/* DNSServiceRegister() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the registration will remain active indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to register the service
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to register on all
- *                  available interfaces. See "Constants for specifying an interface index" for more details.
- *
- * flags:           Indicates the renaming behavior on name conflict (most applications
- *                  will pass 0). See flag definitions above for details.
- *
- * name:            If non-NULL, specifies the service name to be registered.
- *                  Most applications will not specify a name, in which case the computer
- *                  name is used (this name is communicated to the client via the callback).
- *                  If a name is specified, it must be 1-63 bytes of UTF-8 text.
- *                  If the name is longer than 63 bytes it will be automatically truncated
- *                  to a legal length, unless the NoAutoRename flag is set,
- *                  in which case kDNSServiceErr_BadParam will be returned.
- *
- * regtype:         The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp"). The service type must be an underscore, followed
- *                  by 1-15 characters, which may be letters, digits, or hyphens.
- *                  The transport protocol must be "_tcp" or "_udp". New service types
- *                  should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
- *
- *                  Additional subtypes of the primary service type (where a service
- *                  type has defined subtypes) follow the primary service type in a
- *                  comma-separated list, with no additional spaces, e.g.
- *                      "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
- *                  Subtypes provide a mechanism for filtered browsing: A client browsing
- *                  for "_primarytype._tcp" will discover all instances of this type;
- *                  a client browsing for "_primarytype._tcp,_subtype2" will discover only
- *                  those instances that were registered with "_subtype2" in their list of
- *                  registered subtypes.
- *
- *                  The subtype mechanism can be illustrated with some examples using the
- *                  dns-sd command-line tool:
- *
- *                  % dns-sd -R Simple _test._tcp "" 1001 &
- *                  % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
- *                  % dns-sd -R Best   _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
- *
- *                  Now:
- *                  % dns-sd -B _test._tcp             # will find all three services
- *                  % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
- *                  % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
- *
- *                  Subtype labels may be up to 63 bytes long, and may contain any eight-
- *                  bit byte values, including zero bytes. However, due to the nature of
- *                  using a C-string-based API, conventional DNS escaping must be used for
- *                  dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
- *
- *                  % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
- *
- * domain:          If non-NULL, specifies the domain on which to advertise the service.
- *                  Most applications will not specify a domain, instead automatically
- *                  registering in the default domain(s).
- *
- * host:            If non-NULL, specifies the SRV target host name. Most applications
- *                  will not specify a host, instead automatically using the machine's
- *                  default host name(s). Note that specifying a non-NULL host does NOT
- *                  create an address record for that host - the application is responsible
- *                  for ensuring that the appropriate address record exists, or creating it
- *                  via DNSServiceRegisterRecord().
- *
- * port:            The port, in network byte order, on which the service accepts connections.
- *                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
- *                  by browsing, but will cause a name conflict if another client tries to
- *                  register that same name). Most clients will not use placeholder services.
- *
- * txtLen:          The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
- *
- * txtRecord:       The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
- *                  TXT record, i.e. <length byte> <data> <length byte> <data> ...
- *                  Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
- *                  i.e. it creates a TXT record of length one containing a single empty string.
- *                  RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
- *                  string is the smallest legal DNS TXT record.
- *                  As with the other parameters, the DNSServiceRegister call copies the txtRecord
- *                  data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
- *                  then you can safely free that memory right after the DNSServiceRegister call returns.
- *
- * callBack:        The function to be called when the registration completes or asynchronously
- *                  fails. The client MAY pass NULL for the callback -  The client will NOT be notified
- *                  of the default values picked on its behalf, and the client will NOT be notified of any
- *                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
- *                  of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
- *                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *name,         /* may be NULL */
-    const char                          *regtype,
-    const char                          *domain,       /* may be NULL */
-    const char                          *host,         /* may be NULL */
-    uint16_t                            port,          /* In network byte order */
-    uint16_t                            txtLen,
-    const void                          *txtRecord,    /* may be NULL */
-    DNSServiceRegisterReply             callBack,      /* may be NULL */
-    void                                *context       /* may be NULL */
-    );
-
-
-/* DNSServiceAddRecord()
- *
- * Add a record to a registered service. The name of the record will be the same as the
- * registered service's name.
- * The record can later be updated or deregistered by passing the RecordRef initialized
- * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *
- * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
- * with respect to a single DNSServiceRef. If you plan to have multiple threads
- * in your program simultaneously add, update, or remove records from the same
- * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
- * or take similar appropriate precautions to serialize those calls.
- *
- * Parameters;
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceRegister().
- *
- * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesful completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
- *                  invalidated and may not be used further.
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * rrtype:          The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
- *
- * rdlen:           The length, in bytes, of the rdata.
- *
- * rdata:           The raw rdata to be contained in the added resource record.
- *
- * ttl:             The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred (the RecordRef is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags                     flags,
-    uint16_t                            rrtype,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl
-    );
-
-
-/* DNSServiceUpdateRecord
- *
- * Update a registered resource record. The record must either be:
- *   - The primary txt record of a service registered via DNSServiceRegister()
- *   - A record added to a registered service via DNSServiceAddRecord()
- *   - An individual record registered by DNSServiceRegisterRecord()
- *
- * Parameters:
- *
- * sdRef:           A DNSServiceRef that was initialized by DNSServiceRegister()
- *                  or DNSServiceCreateConnection().
- *
- * RecordRef:       A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
- *                  service's primary txt record.
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * rdlen:           The length, in bytes, of the new rdata.
- *
- * rdata:           The new rdata to be contained in the updated resource record.
- *
- * ttl:             The time to live of the updated resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        RecordRef,     /* may be NULL */
-    DNSServiceFlags                     flags,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl
-    );
-
-
-/* DNSServiceRemoveRecord
- *
- * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
- * an record registered individually via DNSServiceRegisterRecord().
- *
- * Parameters:
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceRegister() (if the
- *                  record being removed was registered via DNSServiceAddRecord()) or by
- *                  DNSServiceCreateConnection() (if the record being removed was registered via
- *                  DNSServiceRegisterRecord()).
- *
- * recordRef:       A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
- *                  or DNSServiceRegisterRecord().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-    (
-    DNSServiceRef                 sdRef,
-    DNSRecordRef                  RecordRef,
-    DNSServiceFlags               flags
-    );
-
-
-/*********************************************************************************************
- *
- *  Service Discovery
- *
- *********************************************************************************************/
-
-/* Browse for instances of a service.
- *
- * DNSServiceBrowseReply() Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceBrowse().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
- *                  See flag definitions for details.
- *
- * interfaceIndex:  The interface on which the service is advertised. This index should
- *                  be passed to DNSServiceResolve() when resolving the service.
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- * serviceName:     The discovered service name. This name should be displayed to the user,
- *                  and stored for subsequent use in the DNSServiceResolve() call.
- *
- * regtype:         The service type, which is usually (but not always) the same as was passed
- *                  to DNSServiceBrowse(). One case where the discovered service type may
- *                  not be the same as the requested service type is when using subtypes:
- *                  The client may want to browse for only those ftp servers that allow
- *                  anonymous connections. The client will pass the string "_ftp._tcp,_anon"
- *                  to DNSServiceBrowse(), but the type of the service that's discovered
- *                  is simply "_ftp._tcp". The regtype for each discovered service instance
- *                  should be stored along with the name, so that it can be passed to
- *                  DNSServiceResolve() when the service is later resolved.
- *
- * domain:          The domain of the discovered service instance. This may or may not be the
- *                  same as the domain that was passed to DNSServiceBrowse(). The domain for each
- *                  discovered service instance should be stored along with the name, so that
- *                  it can be passed to DNSServiceResolve() when the service is later resolved.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceBrowseReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *serviceName,
-    const char                          *regtype,
-    const char                          *replyDomain,
-    void                                *context
-    );
-
-
-/* DNSServiceBrowse() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the browse operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to browse for services
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to browse on all available
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- * regtype:         The service type being browsed for followed by the protocol, separated by a
- *                  dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
- *                  A client may optionally specify a single subtype to perform filtered browsing:
- *                  e.g. browsing for "_primarytype._tcp,_subtype" will discover only those
- *                  instances of "_primarytype._tcp" that were registered specifying "_subtype"
- *                  in their list of registered subtypes.
- *
- * domain:          If non-NULL, specifies the domain on which to browse for services.
- *                  Most applications will not specify a domain, instead browsing on the
- *                  default domain(s).
- *
- * callBack:        The function to be called when an instance of the service being browsed for
- *                  is found, or if the call asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *regtype,
-    const char                          *domain,    /* may be NULL */
-    DNSServiceBrowseReply               callBack,
-    void                                *context    /* may be NULL */
-    );
-
-
-/* DNSServiceResolve()
- *
- * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
- * txt record.
- *
- * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
- * DNSServiceQueryRecord() instead, as it is more efficient for this task.
- *
- * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
- * DNSServiceRefDeallocate().
- *
- * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
- * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
- * DNSServiceQueryRecord() should be used.
- *
- * DNSServiceResolveReply Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceResolve().
- *
- * flags:           Possible values: kDNSServiceFlagsMoreComing
- *
- * interfaceIndex:  The interface on which the service was resolved.
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- * fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
- *                  (This name is escaped following standard DNS rules, making it suitable for
- *                  passing to standard system DNS APIs such as res_query(), or to the
- *                  special-purpose functions included in this API that take fullname parameters.
- *                  See "Notes on DNS Name Escaping" earlier in this file for more details.)
- *
- * hosttarget:      The target hostname of the machine providing the service. This name can
- *                  be passed to functions like gethostbyname() to identify the host's IP address.
- *
- * port:            The port, in network byte order, on which connections are accepted for this service.
- *
- * txtLen:          The length of the txt record, in bytes.
- *
- * txtRecord:       The service's primary txt record, in standard txt record format.
- *
- * context:         The context pointer that was passed to the callout.
- *
- * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
- * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
- * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
- * These should be fixed by updating your own callback function definition to match the corrected
- * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
- * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
- * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
- * If you need to maintain portable code that will compile cleanly with both the old and new versions of
- * this header file, you should update your callback function definition to use the correct unsigned value,
- * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
- * the compiler warning, e.g.:
- *   DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
- * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
- * with both the old header and with the new corrected version.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceResolveReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *fullname,
-    const char                          *hosttarget,
-    uint16_t                            port,        /* In network byte order */
-    uint16_t                            txtLen,
-    const unsigned char                 *txtRecord,
-    void                                *context
-    );
-
-
-/* DNSServiceResolve() Parameters
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the resolve operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Specifying kDNSServiceFlagsForceMulticast will cause query to be
- *                  performed with a link-local mDNS query, even if the name is an
- *                  apparently non-local name (i.e. a name not ending in ".local.")
- *
- * interfaceIndex:  The interface on which to resolve the service. If this resolve call is
- *                  as a result of a currently active DNSServiceBrowse() operation, then the
- *                  interfaceIndex should be the index reported in the DNSServiceBrowseReply
- *                  callback. If this resolve call is using information previously saved
- *                  (e.g. in a preference file) for later use, then use interfaceIndex 0, because
- *                  the desired service may now be reachable via a different physical interface.
- *                  See "Constants for specifying an interface index" for more details.
- *
- * name:            The name of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * regtype:         The type of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * domain:          The domain of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    DNSServiceResolveReply              callBack,
-    void                                *context  /* may be NULL */
-    );
-
-
-/*********************************************************************************************
- *
- *  Querying Individual Specific Records
- *
- *********************************************************************************************/
-
-/* DNSServiceQueryRecord
- *
- * Query for an arbitrary DNS record.
- *
- * DNSServiceQueryRecordReply() Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceQueryRecord().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
- *                  with a ttl of 0, i.e. "Remove" events.
- *
- * interfaceIndex:  The interface on which the query was resolved (the index for a given
- *                  interface is determined via the if_nametoindex() family of calls).
- *                  See "Constants for specifying an interface index" for more details.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  errorCode is nonzero.
- *
- * fullname:        The resource record's full domain name.
- *
- * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * rdlen:           The length, in bytes, of the resource record rdata.
- *
- * rdata:           The raw rdata of the resource record.
- *
- * ttl:             If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceQueryRecordReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    DNSServiceErrorType                 errorCode,
-    const char                          *fullname,
-    uint16_t                            rrtype,
-    uint16_t                            rrclass,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl,
-    void                                *context
-    );
-
-
-/* DNSServiceQueryRecord() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the query operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query in a non-local domain. Without setting this flag, unicast queries
- *                  will be one-shot - that is, only answers available at the time of the call
- *                  will be returned. By setting this flag, answers (including Add and Remove
- *                  events) that become available after the initial call is made will generate
- *                  callbacks. This flag has no effect on link-local multicast queries.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to issue the query
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the name to be queried for on all
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- * fullname:        The full domain name of the resource record to be queried for.
- *
- * rrtype:          The numerical type of the resource record to be queried for
- *                  (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *fullname,
-    uint16_t                            rrtype,
-    uint16_t                            rrclass,
-    DNSServiceQueryRecordReply          callBack,
-    void                                *context  /* may be NULL */
-    );
-
-
-/*********************************************************************************************
- *
- *  Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname
- *
- *********************************************************************************************/
-
-/* DNSServiceGetAddrInfo
- *
- * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
- *
- * DNSServiceGetAddrInfoReply() parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceGetAddrInfo().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd.
- *
- * interfaceIndex:  The interface to which the answers pertain.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred.  Other parameters are
- *                  undefined if errorCode is nonzero.
- *
- * hostname:        The fully qualified domain name of the host to be queried for.
- *
- * address:         IPv4 or IPv6 address.
- *
- * ttl:             If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceGetAddrInfoReply)
-    (
-    DNSServiceRef                    sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         interfaceIndex,
-    DNSServiceErrorType              errorCode,
-    const char                       *hostname,
-    const struct sockaddr            *address,
-    uint32_t                         ttl,
-    void                             *context
-    );
-
-
-/* DNSServiceGetAddrInfo() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
- *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the query
- *                  begins and will last indefinitely until the client terminates the query
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query in a non-local domain. Without setting this flag, unicast queries
- *                  will be one-shot - that is, only answers available at the time of the call
- *                  will be returned. By setting this flag, answers (including Add and Remove
- *                  events) that become available after the initial call is made will generate
- *                  callbacks. This flag has no effect on link-local multicast queries.
- *
- * interfaceIndex:  The interface on which to issue the query.  Passing 0 causes the query to be
- *                  sent on all active interfaces via Multicast or the primary interface via Unicast.
- *
- * protocol:        Pass in kDNSServiceProtocol_IPv4 to look up IPv4 addresses, or kDNSServiceProtocol_IPv6
- *                  to look up IPv6 addresses, or both to look up both kinds. If neither flag is
- *                  set, the system will apply an intelligent heuristic, which is (currently)
- *                  that it will attempt to look up both, except:
- *
- *                   * If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
- *                     but this host has no routable IPv6 address, then the call will not try to
- *                     look up IPv6 addresses for "hostname", since any addresses it found would be
- *                     unlikely to be of any use anyway. Similarly, if this host has no routable
- *                     IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
- *
- * hostname:        The fully qualified domain name of the host to be queried for.
- *
- * callBack:        The function to be called when the query succeeds or fails asynchronously.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
-    (
-    DNSServiceRef                    *sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         interfaceIndex,
-    DNSServiceProtocol               protocol,
-    const char                       *hostname,
-    DNSServiceGetAddrInfoReply       callBack,
-    void                             *context          /* may be NULL */
-    );
-
-
-/*********************************************************************************************
- *
- *  Special Purpose Calls:
- *  DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord()
- *  (most applications will not use these)
- *
- *********************************************************************************************/
-
-/* DNSServiceCreateConnection()
- *
- * Create a connection to the daemon allowing efficient registration of
- * multiple individual records.
- *
- * Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. Deallocating
- *                  the reference (via DNSServiceRefDeallocate()) severs the
- *                  connection and deregisters all records registered on this connection.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns
- *                  an error code indicating the specific failure that occurred (in which
- *                  case the DNSServiceRef is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
-
-
-/* DNSServiceRegisterRecord
- *
- * Register an individual resource record on a connected DNSServiceRef.
- *
- * Note that name conflicts occurring for records registered via this call must be handled
- * by the client in the callback.
- *
- * DNSServiceRegisterRecordReply() parameters:
- *
- * sdRef:           The connected DNSServiceRef initialized by
- *                  DNSServiceCreateConnection().
- *
- * RecordRef:       The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
- *                  DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
- *                  invalidated, and may not be used further.
- *
- * flags:           Currently unused, reserved for future use.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
- typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        RecordRef,
-    DNSServiceFlags                     flags,
-    DNSServiceErrorType                 errorCode,
-    void                                *context
-    );
-
-
-/* DNSServiceRegisterRecord() Parameters:
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceCreateConnection().
- *
- * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesful completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  (To deregister ALL records registered on a single connected DNSServiceRef
- *                  and deallocate each of their corresponding DNSServiceRecordRefs, call
- *                  DNSServiceRefDeallocate()).
- *
- * flags:           Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
- *                  (see flag type definitions for details).
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to register the record
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the record to be registered on all interfaces.
- *                  See "Constants for specifying an interface index" for more details.
- *
- * fullname:        The full domain name of the resource record.
- *
- * rrtype:          The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN)
- *
- * rdlen:           Length, in bytes, of the rdata.
- *
- * rdata:           A pointer to the raw rdata, as it is to appear in the DNS record.
- *
- * ttl:             The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails (e.g. because of a name conflict.)
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSRecordRef is
- *                  not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
-    (
-    DNSServiceRef                       sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *fullname,
-    uint16_t                            rrtype,
-    uint16_t                            rrclass,
-    uint16_t                            rdlen,
-    const void                          *rdata,
-    uint32_t                            ttl,
-    DNSServiceRegisterRecordReply       callBack,
-    void                                *context    /* may be NULL */
-    );
-
-
-/* DNSServiceReconfirmRecord
- *
- * Instruct the daemon to verify the validity of a resource record that appears
- * to be out of date (e.g. because TCP connection to a service's target failed.)
- * Causes the record to be flushed from the daemon's cache (as well as all other
- * daemons' caches on the network) if the record is determined to be invalid.
- * Use this routine conservatively. Reconfirming a record necessarily consumes
- * network bandwidth, so this should not be done indiscriminately.
- *
- * Parameters:
- *
- * flags:           Pass kDNSServiceFlagsForce to force immediate deletion of record,
- *                  instead of after some number of reconfirmation queries have gone unanswered.
- *
- * interfaceIndex:  Specifies the interface of the record in question.
- *                  The caller must specify the interface.
- *                  This API (by design) causes increased network traffic, so it requires
- *                  the caller to be precise about which record should be reconfirmed.
- *                  It is not possible to pass zero for the interface index to perform
- *                  a "wildcard" reconfirmation, where *all* matching records are reconfirmed.
- *
- * fullname:        The resource record's full domain name.
- *
- * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * rdlen:           The length, in bytes, of the resource record rdata.
- *
- * rdata:           The raw rdata of the resource record.
- *
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-    (
-    DNSServiceFlags                    flags,
-    uint32_t                           interfaceIndex,
-    const char                         *fullname,
-    uint16_t                           rrtype,
-    uint16_t                           rrclass,
-    uint16_t                           rdlen,
-    const void                         *rdata
-    );
-
-
-/*********************************************************************************************
- *
- *  NAT Port Mapping
- *
- *********************************************************************************************/
-
-/* DNSServiceNATPortMappingCreate
- *
- * Request a port mapping in the NAT gateway, which maps a port on the local machine
- * to an external port on the NAT. The NAT should support either the NAT-PMP or the UPnP IGD
- * protocol for this API to create a successful mapping.
- *
- * The port mapping will be renewed indefinitely until the client process exits, or
- * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
- * The client callback will be invoked, informing the client of the NAT gateway's
- * external IP address and the external port that has been allocated for this client.
- * The client should then record this external IP address and port using whatever
- * directory service mechanism it is using to enable peers to connect to it.
- * (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
- * -- when a client calls DNSServiceRegister() NAT mappings are automatically created
- * and the external IP address and port for the service are recorded in the global DNS.
- * Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
- * this API to explicitly map their own ports.)
- *
- * It's possible that the client callback could be called multiple times, for example
- * if the NAT gateway's IP address changes, or if a configuration change results in a
- * different external port being mapped for this client. Over the lifetime of any long-lived
- * port mapping, the client should be prepared to handle these notifications of changes
- * in the environment, and should update its recorded address and/or port as appropriate.
- *
- * NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
- * which were intentionally designed to help simplify client code:
- *
- *  1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
- *     In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
- *     gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
- *     NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
- *     whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
- *     a machine with multiple active network interfaces. Rather than make every client recreate
- *     this logic for deciding whether a NAT mapping is required, the PortMapping API does that
- *     work for you. If the client calls the PortMapping API when the machine already has a
- *     routable public IP address, then instead of complaining about it and giving an error,
- *     the PortMapping API just invokes your callback, giving the machine's public address
- *     and your own port number. This means you don't need to write code to work out whether
- *     your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
- *     necessary, no harm is done:
- *
- *     - If the machine already has a routable public IP address, then your callback
- *       will just be invoked giving your own address and port.
- *     - If a NAT mapping is required and obtained, then your callback will be invoked
- *       giving you the external address and port.
- *     - If a NAT mapping is required but not obtained from the local NAT gateway,
- *       or the machine has no network connectivity, then your callback will be
- *       invoked giving zero address and port.
- *
- *  2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
- *     network, it's the client's job to notice this, and work out whether a NAT mapping
- *     is required on the new network, and make a new NAT mapping request if necessary.
- *     The DNSServiceNATPortMappingCreate API does this for you, automatically.
- *     The client just needs to make one call to the PortMapping API, and its callback will
- *     be invoked any time the mapping state changes. This property complements point (1) above.
- *     If the client didn't make a NAT mapping request just because it determined that one was
- *     not required at that particular moment in time, the client would then have to monitor
- *     for network state changes to determine if a NAT port mapping later became necessary.
- *     By unconditionally making a NAT mapping request, even when a NAT mapping not to be
- *     necessary, the PortMapping API will then begin monitoring network state changes on behalf of
- *     the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
- *     mapping and inform the client with a new callback giving the new address and port information.
- *
- * DNSServiceNATPortMappingReply() parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
- *
- * flags:           Currently unused, reserved for future use.
- *
- * interfaceIndex:  The interface through which the NAT gateway is reached.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success.
- *                  Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
- *                  more layers of NAT, in which case the other parameters have the defined values.
- *                  For other failures, will indicate the failure that occurred, and the other
- *                  parameters are undefined.
- *
- * externalAddress: Four byte IPv4 address in network byte order.
- *
- * protocol:        Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
- *
- * internalPort:    The port on the local machine that was mapped.
- *
- * externalPort:    The actual external port in the NAT gateway that was mapped.
- *                  This is likely to be different than the requested external port.
- *
- * ttl:             The lifetime of the NAT port mapping created on the gateway.
- *                  This controls how quickly stale mappings will be garbage-collected
- *                  if the client machine crashes, suffers a power failure, is disconnected
- *                  from the network, or suffers some other unfortunate demise which
- *                  causes it to vanish without explicitly removing its NAT port mapping.
- *                  It's possible that the ttl value will differ from the requested ttl value.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
-    (
-    DNSServiceRef                    sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         interfaceIndex,
-    DNSServiceErrorType              errorCode,
-    uint32_t                         externalAddress,   /* four byte IPv4 address in network byte order */
-    DNSServiceProtocol               protocol,
-    uint16_t                         internalPort,      /* In network byte order */
-    uint16_t                         externalPort,      /* In network byte order and may be different than the requested port */
-    uint32_t                         ttl,               /* may be different than the requested ttl */
-    void                             *context
-    );
-
-
-/* DNSServiceNATPortMappingCreate() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
- *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the nat
- *                  port mapping will last indefinitely until the client terminates the port
- *                  mapping request by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * interfaceIndex:  The interface on which to create port mappings in a NAT gateway. Passing 0 causes
- *                  the port mapping request to be sent on the primary interface.
- *
- * protocol:        To request a port mapping, pass in kDNSServiceProtocol_UDP, or kDNSServiceProtocol_TCP,
- *                  or (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP) to map both.
- *                  The local listening port number must also be specified in the internalPort parameter.
- *                  To just discover the NAT gateway's external IP address, pass zero for protocol,
- *                  internalPort, externalPort and ttl.
- *
- * internalPort:    The port number in network byte order on the local machine which is listening for packets.
- *
- * externalPort:    The requested external port in network byte order in the NAT gateway that you would
- *                  like to map to the internal port. Pass 0 if you don't care which external port is chosen for you.
- *
- * ttl:             The requested renewal period of the NAT port mapping, in seconds.
- *                  If the client machine crashes, suffers a power failure, is disconnected from
- *                  the network, or suffers some other unfortunate demise which causes it to vanish
- *                  unexpectedly without explicitly removing its NAT port mappings, then the NAT gateway
- *                  will garbage-collect old stale NAT port mappings when their lifetime expires.
- *                  Requesting a short TTL causes such orphaned mappings to be garbage-collected
- *                  more promptly, but consumes system resources and network bandwidth with
- *                  frequent renewal packets to keep the mapping from expiring.
- *                  Requesting a long TTL is more efficient on the network, but in the event of the
- *                  client vanishing, stale NAT port mappings will not be garbage-collected as quickly.
- *                  Most clients should pass 0 to use a system-wide default value.
- *
- * callBack:        The function to be called when the port mapping request succeeds or fails asynchronously.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- *
- *                  If you don't actually want a port mapped, and are just calling the API
- *                  because you want to find out the NAT's external IP address (e.g. for UI
- *                  display) then pass zero for protocol, internalPort, externalPort and ttl.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
-    (
-    DNSServiceRef                    *sdRef,
-    DNSServiceFlags                  flags,
-    uint32_t                         interfaceIndex,
-    DNSServiceProtocol               protocol,          /* TCP and/or UDP          */
-    uint16_t                         internalPort,      /* network byte order      */
-    uint16_t                         externalPort,      /* network byte order      */
-    uint32_t                         ttl,               /* time to live in seconds */
-    DNSServiceNATPortMappingReply    callBack,
-    void                             *context           /* may be NULL             */
-    );
-
-
-/*********************************************************************************************
- *
- *  General Utility Functions
- *
- *********************************************************************************************/
-
-/* DNSServiceConstructFullName()
- *
- * Concatenate a three-part domain name (as returned by the above callbacks) into a
- * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
- * strings where necessary.
- *
- * Parameters:
- *
- * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
- *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
- *                  accommodate the longest legal domain name without buffer overrun.
- *
- * service:         The service name - any dots or backslashes must NOT be escaped.
- *                  May be NULL (to construct a PTR record name, e.g.
- *                  "_ftp._tcp.apple.com.").
- *
- * regtype:         The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp").
- *
- * domain:          The domain name, e.g. "apple.com.". Literal dots or backslashes,
- *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
- *
- * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
- *
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
-    (
-    char                            * const fullName,
-    const char                      * const service,      /* may be NULL */
-    const char                      * const regtype,
-    const char                      * const domain
-    );
-
-
-/*********************************************************************************************
- *
- *   TXT Record Construction Functions
- *
- *********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record construction is something like:
- *
- * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
- * TXTRecordCreate();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * ...
- * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
- * TXTRecordDeallocate();
- * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
- */
-
-
-/* TXTRecordRef
- *
- * Opaque internal data type.
- * Note: Represents a DNS-SD TXT record.
- */
-
-typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
-
-
-/* TXTRecordCreate()
- *
- * Creates a new empty TXTRecordRef referencing the specified storage.
- *
- * If the buffer parameter is NULL, or the specified storage size is not
- * large enough to hold a key subsequently added using TXTRecordSetValue(),
- * then additional memory will be added as needed using malloc().
- *
- * On some platforms, when memory is low, malloc() may fail. In this
- * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
- * error condition will need to be handled as appropriate by the caller.
- *
- * You can avoid the need to handle this error condition if you ensure
- * that the storage you initially provide is large enough to hold all
- * the key/value pairs that are to be added to the record.
- * The caller can precompute the exact length required for all of the
- * key/value pairs to be added, or simply provide a fixed-sized buffer
- * known in advance to be large enough.
- * A no-value (key-only) key requires  (1 + key length) bytes.
- * A key with empty value requires     (1 + key length + 1) bytes.
- * A key with non-empty value requires (1 + key length + 1 + value length).
- * For most applications, DNS-SD TXT records are generally
- * less than 100 bytes, so in most cases a simple fixed-sized
- * 256-byte buffer will be more than sufficient.
- * Recommended size limits for DNS-SD TXT Records are discussed in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * Note: When passing parameters to and from these TXT record APIs,
- * the key name does not include the '=' character. The '=' character
- * is the separator between the key and value in the on-the-wire
- * packet format; it is not part of either the key or the value.
- *
- * txtRecord:       A pointer to an uninitialized TXTRecordRef.
- *
- * bufferLen:       The size of the storage provided in the "buffer" parameter.
- *
- * buffer:          Optional caller-supplied storage used to hold the TXTRecord data.
- *                  This storage must remain valid for as long as
- *                  the TXTRecordRef.
- */
-
-void DNSSD_API TXTRecordCreate
-    (
-    TXTRecordRef     *txtRecord,
-    uint16_t         bufferLen,
-    void             *buffer
-    );
-
-
-/* TXTRecordDeallocate()
- *
- * Releases any resources allocated in the course of preparing a TXT Record
- * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
- * Ownership of the buffer provided in TXTRecordCreate() returns to the client.
- *
- * txtRecord:           A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- */
-
-void DNSSD_API TXTRecordDeallocate
-    (
-    TXTRecordRef     *txtRecord
-    );
-
-
-/* TXTRecordSetValue()
- *
- * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already
- * exists in the TXTRecordRef, then the current value will be replaced with
- * the new value.
- * Keys may exist in four states with respect to a given TXT record:
- *  - Absent (key does not appear at all)
- *  - Present with no value ("key" appears alone)
- *  - Present with empty value ("key=" appears in TXT record)
- *  - Present with non-empty value ("key=value" appears in TXT record)
- * For more details refer to "Data Syntax for DNS-SD TXT Records" in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * key:             A null-terminated string which only contains printable ASCII
- *                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
- *                  9 characters or fewer (not counting the terminating null).
- *
- * valueSize:       The size of the value.
- *
- * value:           Any binary value. For values that represent
- *                  textual data, UTF-8 is STRONGLY recommended.
- *                  For values that represent textual data, valueSize
- *                  should NOT include the terminating null (if any)
- *                  at the end of the string.
- *                  If NULL, then "key" will be added with no value.
- *                  If non-NULL but valueSize is zero, then "key=" will be
- *                  added with empty value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_Invalid if the "key" string contains
- *                  illegal characters.
- *                  Returns kDNSServiceErr_NoMemory if adding this key would
- *                  exceed the available storage.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordSetValue
-    (
-    TXTRecordRef     *txtRecord,
-    const char       *key,
-    uint8_t          valueSize,        /* may be zero */
-    const void       *value            /* may be NULL */
-    );
-
-
-/* TXTRecordRemoveValue()
- *
- * Removes a key from a TXTRecordRef. The "key" must be an
- * ASCII string which exists in the TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * key:             A key name which exists in the TXTRecordRef.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoSuchKey if the "key" does not
- *                  exist in the TXTRecordRef.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
-    (
-    TXTRecordRef     *txtRecord,
-    const char       *key
-    );
-
-
-/* TXTRecordGetLength()
- *
- * Allows you to determine the length of the raw bytes within a TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * return value:    Returns the size of the raw bytes inside a TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- *                  Returns 0 if the TXTRecordRef is empty.
- */
-
-uint16_t DNSSD_API TXTRecordGetLength
-    (
-    const TXTRecordRef *txtRecord
-    );
-
-
-/* TXTRecordGetBytesPtr()
- *
- * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * return value:    Returns a pointer to the raw bytes inside the TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- */
-
-const void * DNSSD_API TXTRecordGetBytesPtr
-    (
-    const TXTRecordRef *txtRecord
-    );
-
-
-/*********************************************************************************************
- *
- *   TXT Record Parsing Functions
- *
- *********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record parsing is something like:
- *
- * Receive TXT record data in DNSServiceResolve() callback
- * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
- * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
- * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
- * ...
- * memcpy(myval1, val1ptr, len1);
- * memcpy(myval2, val2ptr, len2);
- * ...
- * return;
- *
- * If you wish to retain the values after return from the DNSServiceResolve()
- * callback, then you need to copy the data to your own storage using memcpy()
- * or similar, as shown in the example above.
- *
- * If for some reason you need to parse a TXT record you built yourself
- * using the TXT record construction functions above, then you can do
- * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
- * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
- *
- * Most applications only fetch keys they know about from a TXT record and
- * ignore the rest.
- * However, some debugging tools wish to fetch and display all keys.
- * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
- */
-
-/* TXTRecordContainsKey()
- *
- * Allows you to determine if a given TXT Record contains a specified key.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * key:             A null-terminated ASCII string containing the key name.
- *
- * return value:    Returns 1 if the TXT Record contains the specified key.
- *                  Otherwise, it returns 0.
- */
-
-int DNSSD_API TXTRecordContainsKey
-    (
-    uint16_t         txtLen,
-    const void       *txtRecord,
-    const char       *key
-    );
-
-
-/* TXTRecordGetValuePtr()
- *
- * Allows you to retrieve the value for a given key from a TXT Record.
- *
- * txtLen:          The size of the received TXT Record
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * key:             A null-terminated ASCII string containing the key name.
- *
- * valueLen:        On output, will be set to the size of the "value" data.
- *
- * return value:    Returns NULL if the key does not exist in this TXT record,
- *                  or exists with no value (to differentiate between
- *                  these two cases use TXTRecordContainsKey()).
- *                  Returns pointer to location within TXT Record bytes
- *                  if the key exists with empty or non-empty value.
- *                  For empty value, valueLen will be zero.
- *                  For non-empty value, valueLen will be length of value data.
- */
-
-const void * DNSSD_API TXTRecordGetValuePtr
-    (
-    uint16_t         txtLen,
-    const void       *txtRecord,
-    const char       *key,
-    uint8_t          *valueLen
-    );
-
-
-/* TXTRecordGetCount()
- *
- * Returns the number of keys stored in the TXT Record. The count
- * can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * return value:    Returns the total number of keys in the TXT Record.
- *
- */
-
-uint16_t DNSSD_API TXTRecordGetCount
-    (
-    uint16_t         txtLen,
-    const void       *txtRecord
-    );
-
-
-/* TXTRecordGetItemAtIndex()
- *
- * Allows you to retrieve a key name and value pointer, given an index into
- * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
- * It's also possible to iterate through keys in a TXT record by simply
- * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
- * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
- *
- * On return:
- * For keys with no value, *value is set to NULL and *valueLen is zero.
- * For keys with empty value, *value is non-NULL and *valueLen is zero.
- * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * itemIndex:       An index into the TXT Record.
- *
- * keyBufLen:       The size of the string buffer being supplied.
- *
- * key:             A string buffer used to store the key name.
- *                  On return, the buffer contains a null-terminated C string
- *                  giving the key name. DNS-SD TXT keys are usually
- *                  9 characters or fewer. To hold the maximum possible
- *                  key name, the buffer should be 256 bytes long.
- *
- * valueLen:        On output, will be set to the size of the "value" data.
- *
- * value:           On output, *value is set to point to location within TXT
- *                  Record bytes that holds the value data.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
- *                  Returns kDNSServiceErr_Invalid if index is greater than
- *                  TXTRecordGetCount()-1.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
-    (
-    uint16_t         txtLen,
-    const void       *txtRecord,
-    uint16_t         itemIndex,
-    uint16_t         keyBufLen,
-    char             *key,
-    uint8_t          *valueLen,
-    const void       **value
-    );
-
-#if _DNS_SD_LIBDISPATCH
-/*
-* DNSServiceSetDispatchQueue
-*
-* Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous
-* callbacks.  It's the clients responsibility to ensure that the provided dispatch queue is running.
-*
-* A typical application that uses CFRunLoopRun or dispatch_main on its main thread will
-* usually schedule DNSServiceRefs on its main queue (which is always a serial queue)
-* using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());"
-*
-* If there is any error during the processing of events, the application callback will
-* be called with an error code. For shared connections, each subordinate DNSServiceRef
-* will get its own error callback. Currently these error callbacks only happen
-* if the mDNSResponder daemon is manually terminated or crashes, and the error
-* code in this case is kDNSServiceErr_ServiceNotRunning. The application must call
-* DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code.
-* These error callbacks are rare and should not normally happen on customer machines,
-* but application code should be written defensively to handle such error callbacks
-* gracefully if they occur.
-*
-* After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult
-* on the same DNSServiceRef will result in undefined behavior and should be avoided.
-*
-* Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using
-* DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use
-* DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch
-* queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until
-* the application no longer requires that operation and terminates it using DNSServiceRefDeallocate.
-*
-* service:         DNSServiceRef that was allocated and returned to the application, when the
-*                  application calls one of the DNSService API.
-*
-* queue:           dispatch queue where the application callback will be scheduled
-*
-* return value:    Returns kDNSServiceErr_NoError on success.
-*                  Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source
-*                  Returns kDNSServiceErr_BadParam if the service param is invalid or the
-*                  queue param is invalid
-*/
-
-DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
-  (
-  DNSServiceRef service,
-  dispatch_queue_t queue
-  );
-#endif //_DNS_SD_LIBDISPATCH
-
-#ifdef __APPLE_API_PRIVATE
-
-#define kDNSServiceCompPrivateDNS   "PrivateDNS"
-#define kDNSServiceCompMulticastDNS "MulticastDNS"
-
-#endif //__APPLE_API_PRIVATE
-
-/* Some C compiler cleverness. We can make the compiler check certain things for us,
- * and report errors at compile-time if anything is wrong. The usual way to do this would
- * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
- * then you don't find out what's wrong until you run the software. This way, if the assertion
- * condition is false, the array size is negative, and the compiler complains immediately.
- */
-
-struct CompileTimeAssertionChecks_DNS_SD
-    {
-    char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
-    };
-
-#ifdef  __cplusplus
-    }
-#endif
-
-#endif  /* _DNS_SD_H */
diff --git a/vcnet/dnssdstub.vcxproj b/vcnet/dnssdstub.vcxproj
deleted file mode 100644 (file)
index e31e94a..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="dns_sd.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="dns_sd.h" />
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <VCProjectVersion>15.0</VCProjectVersion>
-    <ProjectGuid>{C0899B3A-43E7-4BC3-A785-659E1FD2EA83}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dnssdstub</RootNamespace>
-    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v143</PlatformToolset>
-    <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
-    <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v143</PlatformToolset>
-    <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
-    <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="Shared">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <OutDir>$(Platform)/$(Configuration)/</OutDir>
-    <IntDir>$(Platform)/$(Configuration)/$(ProjectName)/</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <OutDir>$(Platform)/$(Configuration)/</OutDir>
-    <IntDir>$(Platform)/$(Configuration)/$(ProjectName)/</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ConformanceMode>true</ConformanceMode>
-      <PrecompiledHeaderFile />
-      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <ConformanceMode>true</ConformanceMode>
-      <PrecompiledHeaderFile />
-      <AdditionalIncludeDirectories>..\vcnet;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/vcnet/testdnssd.vcxproj b/vcnet/testdnssd.vcxproj
new file mode 100644 (file)
index 0000000..e190a15
--- /dev/null
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{CBEFF8C1-C109-4B37-92B9-843DF7EB4FA0}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+    <Import Project="packages\libressl_native.4.0.0\build\native\libressl_native.props" Condition="Exists('packages\libressl_native.4.0.0\build\native\libressl_native.props')" />
+    <Import Project="packages\zlib_native.redist.1.2.11\build\native\zlib_native.redist.targets" Condition="Exists('packages\zlib_native.redist.1.2.11\build\native\zlib_native.redist.targets')" />
+    <Import Project="packages\zlib_native.1.2.11\build\native\zlib_native.targets" Condition="Exists('packages\zlib_native.1.2.11\build\native\zlib_native.targets')" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\vcnet;..;..\vcnet\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)testdnssd.exe</OutputFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>$(OutDir)testdnssd.pdb</ProgramDatabaseFile>
+      <SubSystem>Console</SubSystem>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention>
+      </DataExecutionPrevention>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\vcnet;..;..\vcnet\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>
+      </DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <OutputFile>$(OutDir)testdnssd.exe</OutputFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <DataExecutionPrevention>
+      </DataExecutionPrevention>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\cups\testdnssd.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="libcups3.vcxproj">
+      <Project>{cb4aa6f2-3e84-45be-b505-95cd375e8be3}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets" />
+</Project>
\ No newline at end of file
similarity index 67%
rename from vcnet/dnssdstub.vcxproj.filters
rename to vcnet/testdnssd.vcxproj.filters
index 1bbb2f00f68fc05471f9aebd303c5f0c15f58de5..926710ab326be8c52df8e4a8f98e749decf63899 100644 (file)
@@ -3,25 +3,20 @@
   <ItemGroup>
     <Filter Include="Source Files">
       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+      <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
     </Filter>
     <Filter Include="Header Files">
       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
     <Filter Include="Resource Files">
       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="dns_sd.c">
+    <ClCompile Include="..\cups\testdnssd.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="dns_sd.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
 </Project>
\ No newline at end of file