From: Michael R Sweet Date: Thu, 18 Apr 2024 18:14:28 +0000 (-0400) Subject: Adopt new DNS-SD API for cupsd sharing (Issue #931) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87ee0717d85c4ee47028902a97b1c39022c72395;p=thirdparty%2Fcups.git Adopt new DNS-SD API for cupsd sharing (Issue #931) Note: Still needs more testing. --- diff --git a/cups/dnssd.c b/cups/dnssd.c index c097f83786..a68b8a68d4 100644 --- a/cups/dnssd.c +++ b/cups/dnssd.c @@ -11,6 +11,11 @@ #include "debug-internal.h" #include "dnssd.h" +#ifdef __APPLE__ +# include +# include +# include +#endif // __APPLE__ #ifdef HAVE_MDNSRESPONDER # include # if _WIN32 @@ -197,6 +202,67 @@ cupsDNSSDAssembleFullName( } +// +// 'cupsDNSSDCopyComputerName()' - Copy the current human-readable name for the system. +// +// This function copies the current human-readable name ("My Computer") to the +// provided buffer. The "dnssd" parameter is a DNS-SD context created with +// @link cupsDNSSDNew@. The "buffer" parameter points to a character array of +// at least 128 bytes and the "bufsize" parameter specifies the actual size of +// the array. +// + +char * // O - Computer name or `NULL` on error +cupsDNSSDCopyComputerName( + cups_dnssd_t *dnssd, // I - DNS-SD context + char *buffer, // I - Computer name buffer + size_t bufsize) // I - Size of computer name buffer (at least 128 bytes) +{ + // Range check input... + if (buffer) + *buffer = '\0'; + + if (!dnssd || !buffer || bufsize < 128) + return (NULL); + + // Copy the current computer name... +#ifdef __APPLE__ + SCDynamicStoreRef sc; // Context for dynamic store + CFStringEncoding nameEncoding; // Encoding of computer name + CFStringRef nameRef; // Computer name CFString + + if ((sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("libcups"), NULL, NULL)) != NULL) + { + // Get the computer name from the dynamic store... + if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) + { + if (!CFStringGetCString(nameRef, buffer, (CFIndex)bufsize, kCFStringEncodingUTF8)) + *buffer = '\0'; + + CFRelease(nameRef); + } + + CFRelease(sc); + } + +#elif defined(HAVE_MDNSRESPONDER) + char *bufptr; // Pointer into name + + cupsMutexLock(&dnssd->mutex); + cupsCopyString(buffer, dnssd->hostname, bufsize); + cupsMutexUnlock(&dnssd->mutex); + + if ((bufptr = strchr(buffer, '.')) != NULL) + *bufptr = '\0'; + +#else // HAVE_AVAHI + cupsCopyString(buffer, avahi_client_get_host_name(dnssd->client), bufsize); +#endif // __APPLE__ + + return (buffer); +} + + // // 'cupsDNSSDCopyHostName()' - Copy the current mDNS hostname for the system. // diff --git a/cups/dnssd.h b/cups/dnssd.h index 9f0d41e20e..f3388bc8bf 100644 --- a/cups/dnssd.h +++ b/cups/dnssd.h @@ -88,6 +88,7 @@ typedef void (*cups_dnssd_service_cb_t)(cups_dnssd_service_t *service, void *cb_ // Functions... // +extern char *cupsDNSSDCopyComputerName(cups_dnssd_t *dnssd, char *buffer, size_t bufsize) _CUPS_PUBLIC; extern char *cupsDNSSDCopyHostName(cups_dnssd_t *dnssd, char *buffer, size_t bufsize) _CUPS_PUBLIC; extern void cupsDNSSDDelete(cups_dnssd_t *dnssd) _CUPS_PUBLIC; extern size_t cupsDNSSDGetConfigChanges(cups_dnssd_t *dnssd) _CUPS_PUBLIC; diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index 689b88b49b..2f161d809d 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index e36a5e54aa..850a99abfe 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -9,10 +9,6 @@ * information. */ -/* - * Include necessary headers... - */ - #include "cupsd.h" #include @@ -23,55 +19,16 @@ #endif /* HAVE_MDNSRESPONDER && __APPLE__ */ -/* - * Local globals... - */ - -#ifdef HAVE_AVAHI -static int avahi_running = 0; -#endif /* HAVE_AVAHI */ - - /* * Local functions... */ -static char *get_auth_info_required(cupsd_printer_t *p, - char *buffer, size_t bufsize); -# ifdef __APPLE__ -static void dnssdAddAlias(const void *key, const void *value, - void *context); -# endif /* __APPLE__ */ -static cupsd_txt_t dnssdBuildTxtRecord(cupsd_printer_t *p); -# ifdef HAVE_AVAHI -static void dnssdClientCallback(AvahiClient *c, AvahiClientState state, void *userdata); -# endif /* HAVE_AVAHI */ -static void dnssdDeregisterAllPrinters(int from_callback); -static void dnssdDeregisterInstance(cupsd_srv_t *srv, int from_callback); -static void dnssdDeregisterPrinter(cupsd_printer_t *p, int clear_name, int from_callback); -static const char *dnssdErrorString(int error); -static void dnssdFreeTxtRecord(cupsd_txt_t *txt); -static void dnssdRegisterAllPrinters(int from_callback); -# ifdef HAVE_MDNSRESPONDER -static void dnssdRegisterCallback(DNSServiceRef sdRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, - const char *name, - const char *regtype, - const char *domain, - void *context); -# else -static void dnssdRegisterCallback(AvahiEntryGroup *p, - AvahiEntryGroupState state, - void *context); -# endif /* HAVE_MDNSRESPONDER */ -static int dnssdRegisterInstance(cupsd_srv_t *srv, cupsd_printer_t *p, char *name, const char *type, const char *subtypes, int port, cupsd_txt_t *txt, int commit, int from_callback); -static void dnssdRegisterPrinter(cupsd_printer_t *p, int from_callback); +static char *get_auth_info_required(cupsd_printer_t *p, char *buffer, size_t bufsize); +static int dnssdBuildTxtRecord(cupsd_printer_t *p, cups_option_t **txt); +static void dnssdErrorCB(void *cb_data, const char *message); +static void dnssdRegisterCallback(cups_dnssd_service_t *service, void *cb_data, cups_dnssd_flags_t flags); +static void dnssdRegisterPrinter(cupsd_printer_t *p); static void dnssdStop(void); -# ifdef HAVE_MDNSRESPONDER -static void dnssdUpdate(void); -# endif /* HAVE_MDNSRESPONDER */ -static void dnssdUpdateDNSSDName(int from_callback); /* @@ -89,20 +46,20 @@ cupsdDeregisterPrinter( * Only deregister if browsing is enabled and it's a local printer... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", (void *)p, p->name, - removeit); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", (void *)p, p->name, removeit); - if (!Browsing || !p->shared || - (p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) + if (!Browsing || !p->shared || (p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) return; /* * Announce the deletion... */ - if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdDeregisterPrinter(p, 1, 0); + if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDContext) + { + cupsDNSSDServiceDelete(p->dnssd); + p->dnssd = NULL; + } } @@ -114,15 +71,13 @@ cupsdDeregisterPrinter( void cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ { - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", (void *)p, - p->name); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", (void *)p, p->name); - if (!Browsing || !BrowseLocalProtocols || - (p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) + if (!Browsing || !BrowseLocalProtocols || (p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) return; - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdRegisterPrinter(p, 0); + if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDContext) + dnssdRegisterPrinter(p); } @@ -133,38 +88,20 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ void cupsdStartBrowsing(void) { + cupsd_printer_t *p; /* Current printer */ + + if (!Browsing || !BrowseLocalProtocols) return; if (BrowseLocalProtocols & BROWSE_DNSSD) { -# ifdef HAVE_MDNSRESPONDER - DNSServiceErrorType error; /* Error from service creation */ - - /* - * First create a "master" connection for all registrations... - */ - - if ((error = DNSServiceCreateConnection(&DNSSDMaster)) - != kDNSServiceErr_NoError) + if ((DNSSDContext = cupsDNSSDNew(dnssdErrorCB, /*cb_data*/NULL)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create master DNS-SD reference: %d", error); - if (FatalErrors & CUPSD_FATAL_BROWSE) cupsdEndProcess(getpid(), 0); - } - else - { - /* - * Add the master connection to the select list... - */ - - int fd = DNSServiceRefSockFD(DNSSDMaster); - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - - cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); + return; } /* @@ -174,43 +111,16 @@ cupsdStartBrowsing(void) DNSSDPort = 0; cupsdUpdateDNSSDName(); -# else /* HAVE_AVAHI */ - if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create DNS-SD thread."); + /* + * Register the individual printers + */ - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - else + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) { - int error; /* Error code, if any */ - - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); - - if (DNSSDClient == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to communicate with avahi-daemon: %s", - dnssdErrorString(error)); - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - - avahi_threaded_poll_free(DNSSDMaster); - DNSSDMaster = NULL; - } - else - avahi_threaded_poll_start(DNSSDMaster); + if (!(p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) + dnssdRegisterPrinter(p); } -# endif /* HAVE_MDNSRESPONDER */ } - - /* - * Register the individual printers - */ - - dnssdRegisterAllPrinters(0); } @@ -224,17 +134,11 @@ cupsdStopBrowsing(void) if (!Browsing || !BrowseLocalProtocols) return; - /* - * De-register the individual printers - */ - - dnssdDeregisterAllPrinters(0); - /* * Shut down browsing sockets... */ - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) + if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDContext) dnssdStop(); } @@ -246,92 +150,127 @@ cupsdStopBrowsing(void) void cupsdUpdateDNSSDName(void) { - dnssdUpdateDNSSDName(0); -} + char name[1024]; /* Computer/host name */ -# ifdef __APPLE__ -/* - * 'dnssdAddAlias()' - Add a DNS-SD alias name. - */ + /* + * Only share the web interface and printers when non-local listening is + * enabled... + */ -static void -dnssdAddAlias(const void *key, /* I - Key */ - const void *value, /* I - Value (domain) */ - void *context) /* I - Unused */ -{ - char valueStr[1024], /* Domain string */ - hostname[1024], /* Complete hostname */ - *hostptr; /* Pointer into hostname */ + if (!DNSSDPort) + { + /* + * Get the port we use for registrations. If we are not listening on any + * non-local ports, there is no sense sharing local printers via Bonjour... + */ + + cupsd_listener_t *lis; /* Current listening socket */ + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + { + if (httpAddrLocalhost(&(lis->address))) + continue; + + DNSSDPort = httpAddrPort(&(lis->address)); + break; + } + } + + if (!DNSSDPort) + return; + /* + * Get the computer name... + */ - (void)key; - (void)context; + if (cupsDNSSDCopyComputerName(DNSSDContext, name, sizeof(name)) && name[0]) + cupsdSetString(&DNSSDComputerName, name); - if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && - CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), - kCFStringEncodingUTF8)) + if (!DNSSDComputerName) { - snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); - hostptr = hostname + strlen(hostname) - 1; - if (*hostptr == '.') - *hostptr = '\0'; /* Strip trailing dot */ + /* + * Use the ServerName instead... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "Using ServerName \"%s\" as computer name.", ServerName); + cupsdSetString(&DNSSDComputerName, ServerName); + } - if (!DNSSDAlias) - DNSSDAlias = cupsArrayNew(NULL, NULL); + /* + * Get the hostname... + */ + + if (cupsDNSSDCopyHostName(DNSSDContext, name, sizeof(name))) + cupsdSetString(&DNSSDHostName, name); + + if (!DNSSDHostName) + { + if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - cupsdAddAlias(DNSSDAlias, hostname); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", - hostname); + cupsdLogMessage(CUPSD_LOG_INFO, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName); + } + + /* + * Then (re)register the web interface if enabled... + */ + + cupsDNSSDServiceDelete(DNSSDWebIF); + DNSSDWebIF = NULL; + + if (BrowseWebIF) + { + char webif[1024]; /* Web interface share name */ + + if (DNSSDComputerName) + snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); + else + cupsCopyString(webif, "CUPS", sizeof(webif)); + + DNSSDWebIF = cupsDNSSDServiceNew(DNSSDContext, CUPS_DNSSD_IF_INDEX_ANY, webif, /*cb*/NULL, /*cb_data*/NULL); + cupsDNSSDServiceAdd(DNSSDWebIF, "_http._tcp", /*domain*/NULL, DNSSDHostName, (uint16_t)DNSSDPort, /*num_txt*/0, /*txt*/NULL); + cupsDNSSDServicePublish(DNSSDWebIF); } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad Back to My Mac domain in dynamic store!"); } -# endif /* __APPLE__ */ /* * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. */ -static cupsd_txt_t /* O - TXT record */ +static int /* O - Number of TXT key/value pairs */ dnssdBuildTxtRecord( - cupsd_printer_t *p) /* I - Printer information */ + cupsd_printer_t *p, /* I - Printer information */ + cups_option_t **txt) /* O - TXT key/value pairs */ { int i, /* Looping var */ - count; /* Count of key/value pairs */ + num_txt; /* Number of TXT key/value pairs */ char admin_hostname[256], /* Hostname for admin page */ - adminurl_str[256], /* URL for the admin page */ - type_str[32], /* Type to string buffer */ - rp_str[256], /* Queue name string buffer */ - air_str[256], /* auth-info-required string buffer */ - urf_str[256], /* URF string buffer */ - *keyvalue[32][2], /* Table of key/value pairs */ + rp[256], /* RP value */ + value[256], /* TXT value */ *ptr; /* Pointer in string */ - cupsd_txt_t txt; /* TXT record */ cupsd_listener_t *lis; /* Current listener */ const char *admin_scheme = "http"; /* Admin page URL scheme */ ipp_attribute_t *urf_supported; /* urf-supported attribute */ + /* * Load up the key value pairs... */ - count = 0; + num_txt = 0; + *txt = NULL; - keyvalue[count ][0] = "txtvers"; - keyvalue[count++][1] = "1"; + num_txt = cupsAddOption("txtvers", "1", num_txt, txt); + num_txt = cupsAddOption("qtotal", "1", num_txt, txt); - keyvalue[count ][0] = "qtotal"; - keyvalue[count++][1] = "1"; + snprintf(rp, sizeof(rp), "%s/%s", (p->type & CUPS_PTYPE_CLASS) ? "classes" : "printers", p->name); + num_txt = cupsAddOption("rp", rp, num_txt, txt); - keyvalue[count ][0] = "rp"; - keyvalue[count++][1] = rp_str; - snprintf(rp_str, sizeof(rp_str), "%s/%s", (p->type & CUPS_PTYPE_CLASS) ? "classes" : "printers", p->name); - - keyvalue[count ][0] = "ty"; - keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown"; + num_txt = cupsAddOption("ty", p->make_model ? p->make_model : "Unknown", num_txt, txt); /* * Get the hostname for the admin page... @@ -370,769 +309,140 @@ dnssdBuildTxtRecord( } } - httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), admin_scheme, NULL, admin_hostname, DNSSDPort, "/%s/%s", (p->type & CUPS_PTYPE_CLASS) ? "classes" : "printers", p->name); - keyvalue[count ][0] = "adminurl"; - keyvalue[count++][1] = adminurl_str; + httpAssembleURIf(HTTP_URI_CODING_ALL, value, sizeof(value), admin_scheme, NULL, admin_hostname, DNSSDPort, "/%s/%s", (p->type & CUPS_PTYPE_CLASS) ? "classes" : "printers", p->name); + + num_txt = cupsAddOption("adminurl", value, num_txt, txt); if (p->location) - { - keyvalue[count ][0] = "note"; - keyvalue[count++][1] = p->location; - } + num_txt = cupsAddOption("note", p->location, num_txt, txt); - keyvalue[count ][0] = "priority"; - keyvalue[count++][1] = "0"; + num_txt = cupsAddOption("priority", "0", num_txt, txt); - keyvalue[count ][0] = "product"; - keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown"; + num_txt = cupsAddOption("product", p->pc && p->pc->product ? p->pc->product : "Unknown", num_txt, txt); - keyvalue[count ][0] = "pdl"; - keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript"; + num_txt = cupsAddOption("pdl", p->pdl ? p->pdl : "application/postscript", num_txt, txt); - if (get_auth_info_required(p, air_str, sizeof(air_str))) - { - keyvalue[count ][0] = "air"; - keyvalue[count++][1] = air_str; - } + if (get_auth_info_required(p, value, sizeof(value))) + num_txt = cupsAddOption("air", value, num_txt, txt); - keyvalue[count ][0] = "UUID"; - keyvalue[count++][1] = p->uuid + 9; + num_txt = cupsAddOption("UUID", p->uuid + 9, num_txt, txt); - keyvalue[count ][0] = "TLS"; - keyvalue[count++][1] = "1.3"; + num_txt = cupsAddOption("TLS", "1.3", num_txt, txt); if ((urf_supported = ippFindAttribute(p->ppd_attrs, "urf-supported", IPP_TAG_KEYWORD)) != NULL) { int urf_count = ippGetCount(urf_supported); // Number of URF values - urf_str[0] = '\0'; - for (i = 0, ptr = urf_str; i < urf_count; i ++) + value[0] = '\0'; + for (i = 0, ptr = value; i < urf_count; i ++) { - const char *value = ippGetString(urf_supported, i, NULL); + const char *keyword = ippGetString(urf_supported, i, NULL); - if (ptr > urf_str && ptr < (urf_str + sizeof(urf_str) - 1)) + if (ptr > value && ptr < (value + sizeof(value) - 1)) *ptr++ = ','; - cupsCopyString(ptr, value, sizeof(urf_str) - (size_t)(ptr - urf_str)); + cupsCopyString(ptr, keyword, sizeof(value) - (size_t)(ptr - value)); ptr += strlen(ptr); - if (ptr >= (urf_str + sizeof(urf_str) - 1)) + if (ptr >= (value + sizeof(value) - 1)) break; } - keyvalue[count ][0] = "URF"; - keyvalue[count++][1] = urf_str; + num_txt = cupsAddOption("URF", value, num_txt, txt); } - keyvalue[count ][0] = "mopria-certified"; - keyvalue[count++][1] = "1.3"; + num_txt = cupsAddOption("mopria-certified", "1.3", num_txt, txt); if (p->type & CUPS_PTYPE_FAX) { - keyvalue[count ][0] = "Fax"; - keyvalue[count++][1] = "T"; - keyvalue[count ][0] = "rfo"; - keyvalue[count++][1] = rp_str; + num_txt = cupsAddOption("Fax", "T", num_txt, txt); + num_txt = cupsAddOption("rfo", rp, num_txt, txt); } if (p->type & CUPS_PTYPE_COLOR) - { - keyvalue[count ][0] = "Color"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_COLOR) ? "T" : "F"; - } + num_txt = cupsAddOption("Color", (p->type & CUPS_PTYPE_COLOR) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_DUPLEX) - { - keyvalue[count ][0] = "Duplex"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_DUPLEX) ? "T" : "F"; - } + num_txt = cupsAddOption("Duplex", (p->type & CUPS_PTYPE_DUPLEX) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_STAPLE) - { - keyvalue[count ][0] = "Staple"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_STAPLE) ? "T" : "F"; - } + num_txt = cupsAddOption("Staple", (p->type & CUPS_PTYPE_STAPLE) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_COPIES) - { - keyvalue[count ][0] = "Copies"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_COPIES) ? "T" : "F"; - } + num_txt = cupsAddOption("Copies", (p->type & CUPS_PTYPE_COPIES) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_COLLATE) - { - keyvalue[count ][0] = "Collate"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_COLLATE) ? "T" : "F"; - } + num_txt = cupsAddOption("Collate", (p->type & CUPS_PTYPE_COLLATE) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_PUNCH) - { - keyvalue[count ][0] = "Punch"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_PUNCH) ? "T" : "F"; - } + num_txt = cupsAddOption("Punch", (p->type & CUPS_PTYPE_PUNCH) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_BIND) - { - keyvalue[count ][0] = "Bind"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_BIND) ? "T" : "F"; - } + num_txt = cupsAddOption("Bind", (p->type & CUPS_PTYPE_BIND) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_SORT) - { - keyvalue[count ][0] = "Sort"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_SORT) ? "T" : "F"; - } + num_txt = cupsAddOption("Sort", (p->type & CUPS_PTYPE_SORT) ? "T" : "F", num_txt, txt); if (p->type & CUPS_PTYPE_MFP) - { - keyvalue[count ][0] = "Scan"; - keyvalue[count++][1] = (p->type & CUPS_PTYPE_MFP) ? "T" : "F"; - } + num_txt = cupsAddOption("Scan", (p->type & CUPS_PTYPE_MFP) ? "T" : "F", num_txt, txt); - snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PTYPE_REMOTE); + snprintf(value, sizeof(value), "0x%X", p->type | CUPS_PTYPE_REMOTE); + num_txt = cupsAddOption("printer-type", value, num_txt, txt); - keyvalue[count ][0] = "printer-type"; - keyvalue[count++][1] = type_str; - - /* - * Then pack them into a proper txt record... - */ - -# ifdef HAVE_MDNSRESPONDER - TXTRecordCreate(&txt, 0, NULL); - - for (i = 0; i < count; i ++) - { - size_t len = strlen(keyvalue[i][1]); - - if (len < 256) - TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]); - } - -# else - for (i = 0, txt = NULL; i < count; i ++) - txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0], - keyvalue[i][1]); -# endif /* HAVE_MDNSRESPONDER */ - - return (txt); + return (num_txt); } -# ifdef HAVE_AVAHI -/* - * 'dnssdClientCallback()' - Client callback for Avahi. - * - * Called whenever the client or server state changes... - */ +// +// 'dnssdErrorCB()' - DNS-SD error callback. +// static void -dnssdClientCallback( - AvahiClient *c, /* I - Client */ - AvahiClientState state, /* I - Current state */ - void *userdata) /* I - User data (unused) */ +dnssdErrorCB(void *cb_data, // I - Callback data (unused) + const char *message) // I - Error message { - int error; /* Error code, if any */ - - - (void)userdata; - - if (!c) - return; - - /* - * Make sure DNSSDClient is already set also if this callback function is - * already running before avahi_client_new() in dnssdStartBrowsing() - * finishes. - */ - - if (!DNSSDClient) - DNSSDClient = c; - - switch (state) - { - case AVAHI_CLIENT_S_REGISTERING: - case AVAHI_CLIENT_S_RUNNING: - case AVAHI_CLIENT_S_COLLISION: - cupsdLogMessage(CUPSD_LOG_DEBUG, "Avahi server connection now available, registering printers for Bonjour broadcasting."); - - /* - * Mark that Avahi server is running... - */ - - avahi_running = 1; - - /* - * Set the computer name and register the web interface... - */ - - DNSSDPort = 0; - dnssdUpdateDNSSDName(1); - - /* - * Register the individual printers - */ - - dnssdRegisterAllPrinters(1); - break; - - case AVAHI_CLIENT_FAILURE: - if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Avahi server disappeared, unregistering printers for Bonjour broadcasting."); - - /* - * Unregister everything and close the client... - */ - - dnssdDeregisterAllPrinters(1); - dnssdDeregisterInstance(&WebIFSrv, 1); - avahi_client_free(DNSSDClient); - DNSSDClient = NULL; - - /* - * Mark that Avahi server is not running... - */ - - avahi_running = 0; - - /* - * Renew Avahi client... - */ - - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); - - if (!DNSSDClient) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to communicate with avahi-daemon: %s", dnssdErrorString(error)); - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - } - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Communication with avahi-daemon has failed: %s", avahi_strerror(avahi_client_errno(c))); - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - break; + (void)cb_data; - default: - break; - } + cupsdLogMessage(CUPSD_LOG_ERROR, "[DNS-SD] %s", message); } -# endif /* HAVE_AVAHI */ /* - * 'dnssdDeregisterAllPrinters()' - Deregister all printers. + * 'dnssdRegisterCallback()' - Service registration callback. */ static void -dnssdDeregisterAllPrinters( - int from_callback) /* I - Deregistering because of callback? */ +dnssdRegisterCallback( + cups_dnssd_service_t *service, // I - Service + void *cb_data, // I - Callback data (printer) + cups_dnssd_flags_t flags) // I - Registration flags { - cupsd_printer_t *p; /* Current printer */ + cupsd_printer_t *p = (cupsd_printer_t *)cb_data; + // Current printer + const char *reg_name; // Updated service name - if (!DNSSDMaster) + if (flags & CUPS_DNSSD_FLAGS_ERROR) return; - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) - dnssdDeregisterPrinter(p, 1, from_callback); -} - - -/* - * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance. - */ - -static void -dnssdDeregisterInstance( - cupsd_srv_t *srv, /* I - Service */ - int from_callback) /* I - Called from callback? */ -{ - if (!srv || !*srv) + if (!p) return; -# ifdef HAVE_MDNSRESPONDER - (void)from_callback; - - DNSServiceRefDeallocate(*srv); - - *srv = NULL; - -# else /* HAVE_AVAHI */ - if (!from_callback) - avahi_threaded_poll_lock(DNSSDMaster); - - if (*srv) - { - avahi_entry_group_free(*srv); - *srv = NULL; - } - - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); -# endif /* HAVE_MDNSRESPONDER */ -} - - -/* - * 'dnssdDeregisterPrinter()' - Deregister all services for a printer. - */ - -static void -dnssdDeregisterPrinter( - cupsd_printer_t *p, /* I - Printer */ - int clear_name, /* I - Clear the name? */ - int from_callback) /* I - Called from callback? */ - -{ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "dnssdDeregisterPrinter(p=%p(%s), clear_name=%d)", (void *)p, p->name, - clear_name); - - if (p->ipp_srv) - { - dnssdDeregisterInstance(&p->ipp_srv, from_callback); - -# ifdef HAVE_MDNSRESPONDER - dnssdDeregisterInstance(&p->ipps_srv, from_callback); - dnssdDeregisterInstance(&p->printer_srv, from_callback); -# endif /* HAVE_MDNSRESPONDER */ - } - - /* - * Remove the printer from the array of DNS-SD printers but keep the - * registered name... - */ - - cupsArrayRemove(DNSSDPrinters, p); - - /* - * Optionally clear the service name... - */ - - if (clear_name) - cupsdClearString(&p->reg_name); -} - - -/* - * 'dnssdErrorString()' - Return an error string for an error code. - */ + reg_name = cupsDNSSDServiceGetName(service); -static const char * /* O - Error message */ -dnssdErrorString(int error) /* I - Error number */ -{ -# ifdef HAVE_MDNSRESPONDER - switch (error) + if ((!p->reg_name || _cups_strcasecmp(reg_name, p->reg_name))) { - case kDNSServiceErr_NoError : - return ("OK."); - - default : - case kDNSServiceErr_Unknown : - return ("Unknown error."); - - case kDNSServiceErr_NoSuchName : - return ("Service not found."); - - case kDNSServiceErr_NoMemory : - return ("Out of memory."); - - case kDNSServiceErr_BadParam : - return ("Bad parameter."); - - case kDNSServiceErr_BadReference : - return ("Bad service reference."); - - case kDNSServiceErr_BadState : - return ("Bad state."); - - case kDNSServiceErr_BadFlags : - return ("Bad flags."); - - case kDNSServiceErr_Unsupported : - return ("Unsupported."); - - case kDNSServiceErr_NotInitialized : - return ("Not initialized."); - - case kDNSServiceErr_AlreadyRegistered : - return ("Already registered."); - - case kDNSServiceErr_NameConflict : - return ("Name conflict."); - - case kDNSServiceErr_Invalid : - return ("Invalid name."); - - case kDNSServiceErr_Firewall : - return ("Firewall prevents registration."); - - case kDNSServiceErr_Incompatible : - return ("Client library incompatible."); - - case kDNSServiceErr_BadInterfaceIndex : - return ("Bad interface index."); - - case kDNSServiceErr_Refused : - return ("Server prevents registration."); - - case kDNSServiceErr_NoSuchRecord : - return ("Record not found."); - - case kDNSServiceErr_NoAuth : - return ("Authentication required."); - - case kDNSServiceErr_NoSuchKey : - return ("Encryption key not found."); - - case kDNSServiceErr_NATTraversal : - return ("Unable to traverse NAT boundary."); - - case kDNSServiceErr_DoubleNAT : - return ("Unable to traverse double-NAT boundary."); - - case kDNSServiceErr_BadTime : - return ("Bad system time."); - - case kDNSServiceErr_BadSig : - return ("Bad signature."); - - case kDNSServiceErr_BadKey : - return ("Bad encryption key."); - - case kDNSServiceErr_Transient : - return ("Transient error occurred - please try again."); - - case kDNSServiceErr_ServiceNotRunning : - return ("Server not running."); - - case kDNSServiceErr_NATPortMappingUnsupported : - return ("NAT doesn't support NAT-PMP or UPnP."); - - case kDNSServiceErr_NATPortMappingDisabled : - return ("NAT supports NAT-PNP or UPnP but it is disabled."); - - case kDNSServiceErr_NoRouter : - return ("No Internet/default router configured."); - - case kDNSServiceErr_PollingMode : - return ("Service polling mode error."); - - case kDNSServiceErr_Timeout : - return ("Service timeout."); - } - -# else /* HAVE_AVAHI */ - return (avahi_strerror(error)); -# endif /* HAVE_MDNSRESPONDER */ -} - - -/* - * 'dnssdRegisterCallback()' - Free a TXT record. - */ - -static void -dnssdFreeTxtRecord(cupsd_txt_t *txt) /* I - TXT record */ -{ -# ifdef HAVE_MDNSRESPONDER - TXTRecordDeallocate(txt); - -# else /* HAVE_AVAHI */ - avahi_string_list_free(*txt); - *txt = NULL; -# endif /* HAVE_MDNSRESPONDER */ -} - - -/* - * 'dnssdRegisterAllPrinters()' - Register all printers. - */ - -static void -dnssdRegisterAllPrinters(int from_callback) /* I - Called from callback? */ -{ - cupsd_printer_t *p; /* Current printer */ - - - if (!DNSSDMaster) - return; - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PTYPE_REMOTE | CUPS_PTYPE_SCANNER))) - dnssdRegisterPrinter(p, from_callback); -} - - -/* - * 'dnssdRegisterCallback()' - DNSServiceRegister callback. - */ - -# ifdef HAVE_MDNSRESPONDER -static void -dnssdRegisterCallback( - DNSServiceRef sdRef, /* I - DNS Service reference */ - DNSServiceFlags flags, /* I - Reserved for future use */ - DNSServiceErrorType errorCode, /* I - Error code */ - const char *name, /* I - Service name */ - const char *regtype, /* I - Service type */ - const char *domain, /* I - Domain. ".local" for now */ - void *context) /* I - Printer */ -{ - cupsd_printer_t *p = (cupsd_printer_t *)context; - /* Current printer */ - - - (void)sdRef; - (void)flags; - (void)domain; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", - name, regtype, p ? p->name : "Web Interface", - p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); - - if (errorCode) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "DNSServiceRegister failed with error %d", (int)errorCode); - return; - } - else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name))) - { - cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"", - name, p->name); + cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\".", reg_name, p->name); cupsArrayRemove(DNSSDPrinters, p); - cupsdSetString(&p->reg_name, name); + cupsdSetString(&p->reg_name, reg_name); cupsArrayAdd(DNSSDPrinters, p); LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; } } -# else /* HAVE_AVAHI */ -static void -dnssdRegisterCallback( - AvahiEntryGroup *srv, /* I - Service */ - AvahiEntryGroupState state, /* I - Registration state */ - void *context) /* I - Printer */ -{ - cupsd_printer_t *p = (cupsd_printer_t *)context; - /* Current printer */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "dnssdRegisterCallback(srv=%p, state=%d, context=%p) " - "for %s (%s)", srv, state, context, - p ? p->name : "Web Interface", - p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); - - /* TODO: Handle collisions with avahi_alternate_service_name(p->reg_name)? */ -} -# endif /* HAVE_MDNSRESPONDER */ - - -/* - * 'dnssdRegisterInstance()' - Register an instance of a printer service. - */ - -static int /* O - 1 on success, 0 on failure */ -dnssdRegisterInstance( - cupsd_srv_t *srv, /* O - Service */ - cupsd_printer_t *p, /* I - Printer */ - char *name, /* I - DNS-SD service name */ - const char *type, /* I - DNS-SD service type */ - const char *subtypes, /* I - Subtypes to register or NULL */ - int port, /* I - Port number or 0 */ - cupsd_txt_t *txt, /* I - TXT record */ - int commit, /* I - Commit registration? */ - int from_callback) /* I - Called from callback? */ -{ - char temp[256], /* Temporary string */ - *ptr; /* Pointer into string */ - int error; /* Any error */ - - -# ifdef HAVE_MDNSRESPONDER - (void)from_callback; -# endif /* HAVE_MDNSRESPONDER */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Registering \"%s\" with DNS-SD type \"%s\".", name, type); - - if (p && !srv) - { - /* - * Assign the correct pointer for "srv"... - */ - -# ifdef HAVE_MDNSRESPONDER - if (!strcmp(type, "_printer._tcp")) - srv = &p->printer_srv; /* Target LPD service */ - else if (!strcmp(type, "_ipps._tcp")) - srv = &p->ipps_srv; /* Target IPPS service */ - else - srv = &p->ipp_srv; /* Target IPP service */ - -# else /* HAVE_AVAHI */ - srv = &p->ipp_srv; /* Target service group */ -# endif /* HAVE_MDNSRESPONDER */ - } - -# ifdef HAVE_MDNSRESPONDER - (void)commit; - -# else /* HAVE_AVAHI */ - if (!from_callback) - avahi_threaded_poll_lock(DNSSDMaster); - - if (!*srv) - *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL); - if (!*srv) - { - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); - - cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", - name, dnssdErrorString(avahi_client_errno(DNSSDClient))); - return (0); - } -# endif /* HAVE_MDNSRESPONDER */ - - /* - * Make sure the name is <= 63 octets, and when we truncate be sure to - * properly truncate any UTF-8 characters... - */ - - ptr = name + strlen(name); - while ((ptr - name) > 63) - { - do - { - ptr --; - } - while (ptr > name && (*ptr & 0xc0) == 0x80); - - if (ptr > name) - *ptr = '\0'; - } - - /* - * Register the service... - */ - -# ifdef HAVE_MDNSRESPONDER - if (subtypes) - snprintf(temp, sizeof(temp), "%s,%s", type, subtypes); - else - cupsCopyString(temp, type, sizeof(temp)); - - *srv = DNSSDMaster; - error = DNSServiceRegister(srv, kDNSServiceFlagsShareConnection, - 0, name, temp, NULL, DNSSDHostName, htons(port), - txt ? TXTRecordGetLength(txt) : 0, - txt ? TXTRecordGetBytesPtr(txt) : NULL, - dnssdRegisterCallback, p); - -# else /* HAVE_AVAHI */ - if (txt) - { - AvahiStringList *temptxt; - for (temptxt = *txt; temptxt; temptxt = temptxt->next) - cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS_SD \"%s\" %s", name, temptxt->text); - } - - error = avahi_entry_group_add_service_strlst(*srv, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, 0, name, - type, NULL, DNSSDHostName, port, - txt ? *txt : NULL); - if (error) - cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD service add for \"%s\" failed.", - name); - - if (!error && subtypes) - { - /* - * Register all of the subtypes... - */ - - char *start, /* Start of subtype */ - subtype[256]; /* Subtype string */ - - cupsCopyString(temp, subtypes, sizeof(temp)); - - for (start = temp; *start; start = ptr) - { - /* - * Skip leading whitespace... - */ - - while (*start && isspace(*start & 255)) - start ++; - - /* - * Grab everything up to the next comma or the end of the string... - */ - - for (ptr = start; *ptr && *ptr != ','; ptr ++); - - if (*ptr) - *ptr++ = '\0'; - - if (!*start) - break; - - /* - * Register the subtype... - */ - - snprintf(subtype, sizeof(subtype), "%s._sub.%s", start, type); - - error = avahi_entry_group_add_service_subtype(*srv, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, 0, - name, type, NULL, subtype); - if (error) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "DNS-SD subtype %s registration for \"%s\" failed." , - subtype, name); - break; - } - } - } - - if (!error && commit) - { - if ((error = avahi_entry_group_commit(*srv)) != 0) - cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.", - name); - } - - if (!from_callback) - avahi_threaded_poll_unlock(DNSSDMaster); -# endif /* HAVE_MDNSRESPONDER */ - - if (error) - { - cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", - name, dnssdErrorString(error)); - cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD type: %s", type); - if (subtypes) - cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD sub-types: %s", subtypes); - } - - return (!error); -} - /* * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer @@ -1141,28 +451,24 @@ dnssdRegisterInstance( static void dnssdRegisterPrinter( - cupsd_printer_t *p, /* I - Printer */ - int from_callback) /* I - Called from callback? */ + cupsd_printer_t *p) /* I - Printer */ { - char name[256]; /* Service name */ - int status; /* Registration status */ - cupsd_txt_t ipp_txt; /* IPP(S) TXT record */ + char name[256], /* Service name */ + regtype[256]; /* Registration type(s) */ + int num_txt; /* Number of IPP(S) TXT key/value pairs */ + cups_option_t *txt; /* IPP(S) TXT key/value pairs */ + bool status; /* Registration status */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, - !p->ipp_srv ? "new" : "update"); - -# ifdef HAVE_AVAHI - if (!avahi_running) - return; -# endif /* HAVE_AVAHI */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s)", p->name); /* * Remove the current registrations if we have them and then return if * per-printer sharing was just disabled... */ - dnssdDeregisterPrinter(p, 0, from_callback); + cupsDNSSDServiceDelete(p->dnssd); + p->dnssd = NULL; if (!p->shared) return; @@ -1182,12 +488,18 @@ dnssdRegisterPrinter( cupsCopyString(name, p->info, sizeof(name)); } else if (DNSSDComputerName) + { snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName); + } else + { cupsCopyString(name, p->name, sizeof(name)); + } } else + { cupsCopyString(name, p->reg_name, sizeof(name)); + } /* * Register IPP and LPD... @@ -1196,49 +508,54 @@ dnssdRegisterPrinter( * our name, but use port number 0 so that we don't have clients using LPD... */ - ipp_txt = dnssdBuildTxtRecord(p); + p->dnssd = cupsDNSSDServiceNew(DNSSDContext, CUPS_DNSSD_IF_INDEX_ANY, name, dnssdRegisterCallback, p); + status = p->dnssd != NULL; - status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, 0, NULL, 0, from_callback); + // LPD placeholder + status &= cupsDNSSDServiceAdd(p->dnssd, "_printer._tcp", /*domain*/NULL, DNSSDHostName, /*port*/0, /*num_txt*/0, /*txt*/NULL); - if (status) - dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 0, from_callback); + // IPP service + num_txt = dnssdBuildTxtRecord(p, &txt); - if (status) + if (p->type & CUPS_PTYPE_FAX) { - /* - * Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"... - */ - - if (p->type & CUPS_PTYPE_FAX) - status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); + if (DNSSDSubTypes) + snprintf(regtype, sizeof(regtype), "_fax-ipp._tcp,%s", DNSSDSubTypes); + else + cupsCopyString(regtype, "_fax-ipp._tcp", sizeof(regtype)); + } + else + { + if (DNSSDSubTypes) + snprintf(regtype, sizeof(regtype), "_ipp._tcp,%s", DNSSDSubTypes); else - status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); + cupsCopyString(regtype, "_ipp._tcp", sizeof(regtype)); } - dnssdFreeTxtRecord(&ipp_txt); + status &= cupsDNSSDServiceAdd(p->dnssd, regtype, /*domain*/NULL, DNSSDHostName, (uint16_t)DNSSDPort, num_txt, txt); + + // IPPS service + if (DNSSDSubTypes) + snprintf(regtype, sizeof(regtype), "_ipps._tcp,%s", DNSSDSubTypes); + else + cupsCopyString(regtype, "_ipps._tcp", sizeof(regtype)); + + status &= cupsDNSSDServiceAdd(p->dnssd, regtype, /*domain*/NULL, DNSSDHostName, (uint16_t)DNSSDPort, num_txt, txt); + + cupsFreeOptions(num_txt, txt); if (status) { - /* - * Save the registered name and add the printer to the array of DNS-SD - * printers... - */ - + // Save the registered name and add the printer to the array of DNS-SD + // printers... cupsdSetString(&p->reg_name, name); cupsArrayAdd(DNSSDPrinters, p); } else { - /* - * Registration failed for this printer... - */ - - dnssdDeregisterInstance(&p->ipp_srv, from_callback); - -# ifdef HAVE_MDNSRESPONDER - dnssdDeregisterInstance(&p->ipps_srv, from_callback); - dnssdDeregisterInstance(&p->printer_srv, from_callback); -# endif /* HAVE_MDNSRESPONDER */ + // Registration failed for this printer... + cupsDNSSDServiceDelete(p->dnssd); + p->dnssd = NULL; } } @@ -1257,39 +574,21 @@ dnssdStop(void) * De-register the individual printers */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - dnssdDeregisterPrinter(p, 1, 0); + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) + { + cupsDNSSDServiceDelete(p->dnssd); + p->dnssd = NULL; + } /* * Shutdown the rest of the service refs... */ - dnssdDeregisterInstance(&WebIFSrv, 0); - -# ifdef HAVE_MDNSRESPONDER - cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster)); - - DNSServiceRefDeallocate(DNSSDMaster); - DNSSDMaster = NULL; - -# else /* HAVE_AVAHI */ - if (DNSSDMaster) - avahi_threaded_poll_stop(DNSSDMaster); - - if (DNSSDClient) - { - avahi_client_free(DNSSDClient); - DNSSDClient = NULL; - } + cupsDNSSDServiceDelete(DNSSDWebIF); + DNSSDWebIF = NULL; - if (DNSSDMaster) - { - avahi_threaded_poll_free(DNSSDMaster); - DNSSDMaster = NULL; - } -# endif /* HAVE_MDNSRESPONDER */ + cupsDNSSDDelete(DNSSDContext); + DNSSDContext = NULL; cupsArrayDelete(DNSSDPrinters); DNSSDPrinters = NULL; @@ -1298,231 +597,6 @@ dnssdStop(void) } -# ifdef HAVE_MDNSRESPONDER -/* - * 'dnssdUpdate()' - Handle DNS-SD queries. - */ - -static void -dnssdUpdate(void) -{ - DNSServiceErrorType sdErr; /* Service discovery error */ - - - if ((sdErr = DNSServiceProcessResult(DNSSDMaster)) != kDNSServiceErr_NoError) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "DNS Service Discovery registration error %d!", - sdErr); - dnssdStop(); - } -} -# endif /* HAVE_MDNSRESPONDER */ - - -/* - * 'dnssdUpdateDNSSDName()' - Update the listen port, computer name, and web interface registration. - */ - -static void -dnssdUpdateDNSSDName(int from_callback) /* I - Called from callback? */ -{ - char webif[1024]; /* Web interface share name */ -# ifdef __APPLE__ - SCDynamicStoreRef sc; /* Context for dynamic store */ - CFDictionaryRef btmm; /* Back-to-My-Mac domains */ - CFStringEncoding nameEncoding; /* Encoding of computer name */ - CFStringRef nameRef; /* Host name CFString */ - char nameBuffer[1024]; /* C-string buffer */ -# endif /* __APPLE__ */ - - - /* - * Only share the web interface and printers when non-local listening is - * enabled... - */ - - if (!DNSSDPort) - { - /* - * Get the port we use for registrations. If we are not listening on any - * non-local ports, there is no sense sharing local printers via Bonjour... - */ - - cupsd_listener_t *lis; /* Current listening socket */ - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - { - if (httpAddrLocalhost(&(lis->address))) - continue; - - DNSSDPort = httpAddrPort(&(lis->address)); - break; - } - } - - if (!DNSSDPort) - return; - - /* - * Get the computer name as a c-string... - */ - -# ifdef __APPLE__ - sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL); - - if (sc) - { - /* - * Get the computer name from the dynamic store... - */ - - cupsdClearString(&DNSSDComputerName); - - if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store computer name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDComputerName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDComputerName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as computer name.", ServerName); - cupsdSetString(&DNSSDComputerName, ServerName); - } - - if (!DNSSDHostName) - { - /* - * Get the local hostname from the dynamic store... - */ - - if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Dynamic store host name is \"%s\".", nameBuffer); - - if (strchr(nameBuffer, '.')) - cupsdSetString(&DNSSDHostName, nameBuffer); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", nameBuffer); - - cupsdLogMessage(CUPSD_LOG_INFO, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName); - } - - CFRelease(nameRef); - } - } - - if (!DNSSDHostName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Using ServerName \"%s\" as host name.", ServerName); - cupsdSetString(&DNSSDHostName, ServerName); - - cupsdLogMessage(CUPSD_LOG_INFO, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName); - } - - /* - * Get any Back-to-My-Mac domains and add them as aliases... - */ - - cupsdFreeAliases(DNSSDAlias); - DNSSDAlias = NULL; - - btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac")); - if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID()) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.", - (int)CFDictionaryGetCount(btmm)); - CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL); - } - else if (btmm) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad Back to My Mac data in dynamic store!"); - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add."); - - if (btmm) - CFRelease(btmm); - - CFRelease(sc); - } - else -# endif /* __APPLE__ */ -# ifdef HAVE_AVAHI - if (DNSSDClient) - { - const char *host_name = avahi_client_get_host_name(DNSSDClient); - - cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); - - if (!DNSSDHostName) - { - const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); - - if (host_fqdn) - cupsdSetString(&DNSSDHostName, host_fqdn); - else if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - - cupsdLogMessage(CUPSD_LOG_INFO, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName); - } - } - else -# endif /* HAVE_AVAHI */ - { - cupsdSetString(&DNSSDComputerName, ServerName); - - if (!DNSSDHostName) - { - if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - - cupsdLogMessage(CUPSD_LOG_INFO, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName); - } - } - - /* - * Then (re)register the web interface if enabled... - */ - - if (BrowseWebIF) - { - if (DNSSDComputerName) - snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); - else - cupsCopyString(webif, "CUPS", sizeof(webif)); - - dnssdDeregisterInstance(&WebIFSrv, from_callback); - dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer", DNSSDPort, NULL, 1, from_callback); - } -} - - /* * 'get_auth_info_required()' - Get the auth-info-required value to advertise. */ diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h index 91bbf49793..cb978cd4e5 100644 --- a/scheduler/dirsvc.h +++ b/scheduler/dirsvc.h @@ -38,19 +38,12 @@ VAR cups_array_t *DNSSDAlias VALUE(NULL); /* List of dynamic ServerAlias's */ VAR int DNSSDPort VALUE(0); /* Port number to register */ +VAR cups_dnssd_t *DNSSDContext VALUE(NULL); + /* DNS-SD context */ VAR cups_array_t *DNSSDPrinters VALUE(NULL); /* Printers we have registered */ -# ifdef HAVE_MDNSRESPONDER -VAR DNSServiceRef DNSSDMaster VALUE(NULL); - /* Master DNS-SD service reference */ -# else /* HAVE_AVAHI */ -VAR AvahiThreadedPoll *DNSSDMaster VALUE(NULL); - /* Master polling interface for Avahi */ -VAR AvahiClient *DNSSDClient VALUE(NULL); - /* Client information */ -# endif /* HAVE_MDNSRESPONDER */ -VAR cupsd_srv_t WebIFSrv VALUE(NULL); - /* Service reference for the web interface */ +VAR cups_dnssd_service_t *DNSSDWebIF VALUE(NULL); + /* Web interface service */ /* diff --git a/scheduler/printers.h b/scheduler/printers.h index 3c1b12de41..360d8ac7f1 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -8,14 +8,6 @@ * Licensed under Apache License v2.0. See the file "LICENSE" for more information. */ -#ifdef HAVE_MDNSRESPONDER -# include -#elif defined(HAVE_AVAHI) -# include -# include -# include -# include -#endif /* HAVE_MDNSRESPONDER */ #include @@ -32,20 +24,6 @@ typedef struct } cupsd_quota_t; -/* - * DNS-SD types to make the code cleaner/clearer... - */ - -#ifdef HAVE_MDNSRESPONDER -typedef DNSServiceRef cupsd_srv_t; /* Service reference */ -typedef TXTRecordRef cupsd_txt_t; /* TXT record */ - -#elif defined(HAVE_AVAHI) -typedef AvahiEntryGroup *cupsd_srv_t; /* Service reference */ -typedef AvahiStringList *cupsd_txt_t; /* TXT record */ -#endif /* HAVE_MDNSRESPONDER */ - - /* * Printer/class information structure... */ @@ -113,11 +91,7 @@ struct cupsd_printer_s char *reg_name, /* Name used for service registration */ *pdl; /* pdl value for TXT record */ - cupsd_srv_t ipp_srv; /* IPP service(s) */ -# ifdef HAVE_MDNSRESPONDER - cupsd_srv_t ipps_srv; /* IPPS service(s) */ - cupsd_srv_t printer_srv; /* LPD service */ -# endif /* HAVE_MDNSRESPONDER */ + cups_dnssd_service_t *dnssd; /* DNS-SD service(s) */ }; @@ -153,36 +127,21 @@ extern int cupsdDeletePrinter(cupsd_printer_t *p, int update); extern void cupsdDeleteTemporaryPrinters(int force); extern cupsd_printer_t *cupsdFindDest(const char *name); extern cupsd_printer_t *cupsdFindPrinter(const char *name); -extern cupsd_quota_t *cupsdFindQuota(cupsd_printer_t *p, - const char *username); +extern cupsd_quota_t *cupsdFindQuota(cupsd_printer_t *p, const char *username); extern void cupsdFreeQuotas(cupsd_printer_t *p); extern void cupsdLoadAllPrinters(void); -extern void cupsdRenamePrinter(cupsd_printer_t *p, - const char *name); +extern void cupsdRenamePrinter(cupsd_printer_t *p, const char *name); extern void cupsdSaveAllPrinters(void); -extern int cupsdSetAuthInfoRequired(cupsd_printer_t *p, - const char *values, - ipp_attribute_t *attr); +extern int cupsdSetAuthInfoRequired(cupsd_printer_t *p, const char *values, ipp_attribute_t *attr); extern void cupsdSetDeviceURI(cupsd_printer_t *p, const char *uri); -extern void cupsdSetPrinterAttr(cupsd_printer_t *p, - const char *name, - const char *value); +extern void cupsdSetPrinterAttr(cupsd_printer_t *p, const char *name, const char *value); extern void cupsdSetPrinterAttrs(cupsd_printer_t *p); -extern int cupsdSetPrinterReasons(cupsd_printer_t *p, - const char *s); -extern void cupsdSetPrinterState(cupsd_printer_t *p, ipp_pstate_t s, - int update); -#define cupsdStartPrinter(p,u) cupsdSetPrinterState((p), \ - IPP_PSTATE_IDLE, (u)) +extern int cupsdSetPrinterReasons(cupsd_printer_t *p, const char *s); +extern void cupsdSetPrinterState(cupsd_printer_t *p, ipp_pstate_t s, int update); +#define cupsdStartPrinter(p,u) cupsdSetPrinterState((p), IPP_PSTATE_IDLE, (u)) extern void cupsdStopPrinter(cupsd_printer_t *p, int update); -extern int cupsdUpdatePrinterPPD(cupsd_printer_t *p, - int num_keywords, - cups_option_t *keywords); +extern int cupsdUpdatePrinterPPD(cupsd_printer_t *p, int num_keywords, cups_option_t *keywords); extern void cupsdUpdatePrinters(void); -extern cupsd_quota_t *cupsdUpdateQuota(cupsd_printer_t *p, - const char *username, int pages, - int k); -extern const char *cupsdValidateDest(const char *uri, - cups_ptype_t *dtype, - cupsd_printer_t **printer); +extern cupsd_quota_t *cupsdUpdateQuota(cupsd_printer_t *p, const char *username, int pages, int k); +extern const char *cupsdValidateDest(const char *uri, cups_ptype_t *dtype, cupsd_printer_t **printer); extern void cupsdWritePrintcap(void);