From: msweet Date: Wed, 5 Mar 2014 21:10:04 +0000 (+0000) Subject: More Avahi changes to make cupsd resiliant to Avahi failures (STR #4373) X-Git-Tag: v2.2b1~713 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ebd5991b0fff66a5fa4807b26f75bd40e4d56dce;p=thirdparty%2Fcups.git More Avahi changes to make cupsd resiliant to Avahi failures (STR #4373) git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11687 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES-1.7.txt b/CHANGES-1.7.txt index df9d3c8862..7ef0ef95f2 100644 --- a/CHANGES-1.7.txt +++ b/CHANGES-1.7.txt @@ -20,7 +20,7 @@ CHANGES IN CUPS V1.7.2 - Fixed a D-BUS threading issue that caused the scheduler to crash (STR #4347) - The scheduler now automatically reconnects to Avahi as needed - (STR #4370) + (STR #4370, STR #4373) - The scheduler did not handle GET requests for the log files properly (STR #3265) - The dnssd backend did not always report all discovered printers using diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 3f053f67f2..495bf1b7f5 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -27,6 +27,15 @@ #endif /* HAVE_DNSSD && __APPLE__ */ +/* + * Local globals... + */ + +#ifdef HAVE_AVAHI +static int avahi_running = 0; +#endif /* HAVE_AVAHI */ + + /* * Local functions... */ @@ -48,11 +57,15 @@ static void dnssdAddAlias(const void *key, const void *value, void *context); # endif /* __APPLE__ */ static cupsd_txt_t dnssdBuildTxtRecord(cupsd_printer_t *p, int for_lpd); -static void dnssdDeregisterInstance(cupsd_srv_t *srv); -static void dnssdDeregisterPrinter(cupsd_printer_t *p, - int clear_name); +# 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_DNSSD static void dnssdRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, @@ -66,16 +79,13 @@ static void dnssdRegisterCallback(AvahiEntryGroup *p, AvahiEntryGroupState state, void *context); # endif /* HAVE_DNSSD */ -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); -static void dnssdRegisterPrinter(cupsd_printer_t *p); +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 void dnssdStop(void); # ifdef HAVE_DNSSD static void dnssdUpdate(void); # endif /* HAVE_DNSSD */ +static void dnssdUpdateDNSSDName(int from_callback); #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -108,7 +118,7 @@ cupsdDeregisterPrinter( #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdDeregisterPrinter(p, 1); + dnssdDeregisterPrinter(p, 1, 0); #endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -130,7 +140,7 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdRegisterPrinter(p); + dnssdRegisterPrinter(p, 0); #endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -142,16 +152,12 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ void cupsdStartBrowsing(void) { - cupsd_printer_t *p; /* Current printer */ - - if (!Browsing || !BrowseLocalProtocols) return; #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (BrowseLocalProtocols & BROWSE_DNSSD) { - cupsd_listener_t *lis; /* Current listening socket */ # ifdef HAVE_DNSSD DNSServiceErrorType error; /* Error from service creation */ @@ -181,6 +187,13 @@ cupsdStartBrowsing(void) cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); } + /* + * Set the computer name and register the web interface... + */ + + DNSSDPort = 0; + cupsdUpdateDNSSDName(); + # else /* HAVE_AVAHI */ if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL) { @@ -193,7 +206,7 @@ cupsdStartBrowsing(void) { int error; /* Error code, if any */ - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, NULL, NULL, &error); + DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); if (DNSSDClient == NULL) { @@ -211,31 +224,6 @@ cupsdStartBrowsing(void) avahi_threaded_poll_start(DNSSDMaster); } # endif /* HAVE_DNSSD */ - - /* - * Then 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... - */ - - DNSSDPort = 0; - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - { - if (httpAddrLocalhost(&(lis->address))) - continue; - - DNSSDPort = httpAddrPort(&(lis->address)); - break; - } - - /* - * Set the computer name and register the web interface... - */ - - cupsdUpdateDNSSDName(); } #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -253,11 +241,7 @@ cupsdStartBrowsing(void) * Register the individual printers */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) - cupsdRegisterPrinter(p); + dnssdRegisterAllPrinters(0); } @@ -268,9 +252,6 @@ cupsdStartBrowsing(void) void cupsdStopBrowsing(void) { - cupsd_printer_t *p; /* Current printer */ - - if (!Browsing || !BrowseLocalProtocols) return; @@ -278,11 +259,7 @@ cupsdStopBrowsing(void) * De-register the individual printers */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) - cupsdDeregisterPrinter(p, 1); + dnssdDeregisterAllPrinters(0); /* * Shut down browsing sockets... @@ -313,161 +290,7 @@ cupsdStopBrowsing(void) void cupsdUpdateDNSSDName(void) { - 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) - 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); - } - - /* - * Get the local hostname from the dynamic store... - */ - - cupsdClearString(&DNSSDHostName); - - if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store host name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDHostName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDHostName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as host name.", ServerName); - cupsdSetString(&DNSSDHostName, ServerName); - } - - /* - * 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); - const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); - - cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); - - if (host_fqdn) - cupsdSetString(&DNSSDHostName, host_fqdn); - else if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - } - else -# endif /* HAVE_AVAHI */ - { - cupsdSetString(&DNSSDComputerName, ServerName); - - if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - } - - /* - * Then (re)register the web interface if enabled... - */ - - if (BrowseWebIF) - { - if (DNSSDComputerName) - snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); - else - strlcpy(webif, "CUPS", sizeof(webif)); - - dnssdDeregisterInstance(&WebIFSrv); - dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer", - DNSSDPort, NULL, 1); - } + dnssdUpdateDNSSDName(0); } @@ -702,24 +525,158 @@ dnssdBuildTxtRecord( } +# ifdef HAVE_AVAHI +/* + * 'dnssdClientCallback()' - Client callback for Avahi. + * + * Called whenever the client or server state changes... + */ + +static void +dnssdClientCallback( + AvahiClient *c, /* I - Client */ + AvahiClientState state, /* I - Current state */ + void *userdata) /* I - User data (unused) */ +{ + 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; + + default: + break; + } +} +# endif /* HAVE_AVAHI */ + + +/* + * 'dnssdDeregisterAllPrinters()' - Deregister all printers. + */ + +static void +dnssdDeregisterAllPrinters( + int from_callback) /* I - Deregistering because of 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_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + dnssdDeregisterPrinter(p, 1, from_callback); +} + + /* * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance. */ static void dnssdDeregisterInstance( - cupsd_srv_t *srv) /* I - Service */ + cupsd_srv_t *srv, /* I - Service */ + int from_callback) /* I - Called from callback? */ { if (!srv || !*srv) return; # ifdef HAVE_DNSSD + (void)from_callback; + DNSServiceRefDeallocate(*srv); # else /* HAVE_AVAHI */ - avahi_threaded_poll_lock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_lock(DNSSDMaster); + avahi_entry_group_free(*srv); - avahi_threaded_poll_unlock(DNSSDMaster); + + if (!from_callback) + avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ *srv = NULL; @@ -733,7 +690,8 @@ dnssdDeregisterInstance( static void dnssdDeregisterPrinter( cupsd_printer_t *p, /* I - Printer */ - int clear_name) /* I - Clear the name? */ + int clear_name, /* I - Clear the name? */ + int from_callback) /* I - Called from callback? */ { cupsdLogMessage(CUPSD_LOG_DEBUG2, @@ -742,13 +700,13 @@ dnssdDeregisterPrinter( if (p->ipp_srv) { - dnssdDeregisterInstance(&p->ipp_srv); + dnssdDeregisterInstance(&p->ipp_srv, from_callback); # ifdef HAVE_DNSSD # ifdef HAVE_SSL - dnssdDeregisterInstance(&p->ipps_srv); + dnssdDeregisterInstance(&p->ipps_srv, from_callback); # endif /* HAVE_SSL */ - dnssdDeregisterInstance(&p->printer_srv); + dnssdDeregisterInstance(&p->printer_srv, from_callback); # endif /* HAVE_DNSSD */ } @@ -899,6 +857,27 @@ dnssdFreeTxtRecord(cupsd_txt_t *txt) /* I - TXT record */ } +/* + * '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_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + dnssdRegisterPrinter(p, from_callback); +} + + /* * 'dnssdRegisterCallback()' - DNSServiceRegister callback. */ @@ -979,15 +958,19 @@ dnssdRegisterInstance( 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 commit, /* I - Commit registration? */ + int from_callback) /* I - Called from callback? */ { char temp[256], /* Temporary string */ *ptr; /* Pointer into string */ int error; /* Any error */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Registering \"%s\" with DNS-SD type \"%s\".", name, type); +# ifdef HAVE_DNSSD + (void)from_callback; +# endif /* HAVE_DNSSD */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "Registering \"%s\" with DNS-SD type \"%s\".", name, type); if (p && !srv) { @@ -1014,13 +997,15 @@ dnssdRegisterInstance( (void)commit; # else /* HAVE_AVAHI */ - avahi_threaded_poll_lock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_lock(DNSSDMaster); if (!*srv) *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL); if (!*srv) { - avahi_threaded_poll_unlock(DNSSDMaster); + 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))); @@ -1137,7 +1122,8 @@ dnssdRegisterInstance( name); } - avahi_threaded_poll_unlock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ if (error) @@ -1159,7 +1145,9 @@ dnssdRegisterInstance( */ static void -dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +dnssdRegisterPrinter( + cupsd_printer_t *p, /* I - Printer */ + int from_callback) /* I - Called from callback? */ { char name[256]; /* Service name */ int printer_port; /* LPD port number */ @@ -1167,15 +1155,21 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ cupsd_txt_t ipp_txt, /* IPP(S) TXT record */ printer_txt; /* LPD TXT record */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, !p->ipp_srv ? "new" : "update"); +# ifdef HAVE_AVAHI + if (!avahi_running) + return; +# endif /* HAVE_AVAHI */ + /* * Remove the current registrations if we have them and then return if * per-printer sharing was just disabled... */ - dnssdDeregisterPrinter(p, 0); + dnssdDeregisterPrinter(p, 0, from_callback); if (!p->shared) return; @@ -1218,13 +1212,11 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ else printer_port = 0; - status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, - printer_port, &printer_txt, 0); + status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, printer_port, &printer_txt, 0, from_callback); # ifdef HAVE_SSL if (status) - dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, - DNSSDPort, &ipp_txt, 0); + dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 0, from_callback); # endif /* HAVE_SSL */ if (status) @@ -1234,11 +1226,9 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ */ if (p->type & CUPS_PRINTER_FAX) - status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", - DNSSDSubTypes, DNSSDPort, &ipp_txt, 1); + status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); else - status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, - DNSSDPort, &ipp_txt, 1); + status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); } dnssdFreeTxtRecord(&ipp_txt); @@ -1260,13 +1250,13 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ * Registration failed for this printer... */ - dnssdDeregisterInstance(&p->ipp_srv); + dnssdDeregisterInstance(&p->ipp_srv, from_callback); # ifdef HAVE_DNSSD # ifdef HAVE_SSL - dnssdDeregisterInstance(&p->ipps_srv); + dnssdDeregisterInstance(&p->ipps_srv, from_callback); # endif /* HAVE_SSL */ - dnssdDeregisterInstance(&p->printer_srv); + dnssdDeregisterInstance(&p->printer_srv, from_callback); # endif /* HAVE_DNSSD */ } } @@ -1289,13 +1279,13 @@ dnssdStop(void) for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) - dnssdDeregisterPrinter(p, 1); + dnssdDeregisterPrinter(p, 1, 0); /* * Shutdown the rest of the service refs... */ - dnssdDeregisterInstance(&WebIFSrv); + dnssdDeregisterInstance(&WebIFSrv, 0); # ifdef HAVE_DNSSD cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster)); @@ -1342,6 +1332,191 @@ dnssdUpdate(void) # endif /* HAVE_DNSSD */ +/* + * '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); + } + + /* + * Get the local hostname from the dynamic store... + */ + + cupsdClearString(&DNSSDHostName); + + if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) + { + if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), + kCFStringEncodingUTF8)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Dynamic store host name is \"%s\".", nameBuffer); + cupsdSetString(&DNSSDHostName, nameBuffer); + } + + CFRelease(nameRef); + } + + if (!DNSSDHostName) + { + /* + * Use the ServerName instead... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Using ServerName \"%s\" as host name.", ServerName); + cupsdSetString(&DNSSDHostName, ServerName); + } + + /* + * 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); + const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); + + cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); + + if (host_fqdn) + cupsdSetString(&DNSSDHostName, host_fqdn); + else if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); + } + else +# endif /* HAVE_AVAHI */ + { + cupsdSetString(&DNSSDComputerName, ServerName); + + if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); + } + + /* + * Then (re)register the web interface if enabled... + */ + + if (BrowseWebIF) + { + if (DNSSDComputerName) + snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); + else + strlcpy(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. */