1 diff --git a/scheduler/client.c b/scheduler/client.c
2 index e4c9b01..984dcc5 100644
3 --- a/scheduler/client.c
4 +++ b/scheduler/client.c
5 @@ -4987,7 +4987,7 @@ valid_host(cupsd_client_t *con) /* I - Client connection */
6 !strncmp(host, "[::1]:", 6));
10 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
12 * Check if the hostname is something.local (Bonjour); if so, allow it.
14 @@ -4996,7 +4996,7 @@ valid_host(cupsd_client_t *con) /* I - Client connection */
15 (!_cups_strcasecmp(end, ".local") || !_cups_strncasecmp(end, ".local:", 7) ||
16 !_cups_strcasecmp(end, ".local.") || !_cups_strncasecmp(end, ".local.:", 8)))
18 -#endif /* HAVE_DNSSD */
19 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
22 * Check if the hostname is an IP address...
23 diff --git a/scheduler/conf.c b/scheduler/conf.c
24 index badc630..c1edd39 100644
25 --- a/scheduler/conf.c
26 +++ b/scheduler/conf.c
27 @@ -648,7 +648,7 @@ cupsdReadConfiguration(void)
28 Browsing = CUPS_DEFAULT_BROWSING;
29 DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED;
32 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
33 cupsdSetString(&DNSSDRegType, "_ipp._tcp,_cups");
34 #endif /* HAVE_DNSSD */
36 diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
37 index eb3c862..48dcef9 100644
38 --- a/scheduler/dirsvc.c
39 +++ b/scheduler/dirsvc.c
42 * cupsdRegisterPrinter() - Start sending broadcast information for a
43 * printer or update the broadcast contents.
44 + * cupsdStartAvahiClient() - Start an Avahi client if needed
45 * cupsdStartBrowsing() - Start sending and receiving broadcast
47 * cupsdStopBrowsing() - Stop sending and receiving broadcast
50 * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
52 + * avahiPackTxtRecord() - Pack an array of key/value pairs into an
54 * dnssdRegisterCallback() - DNSServiceRegister callback.
55 * dnssdRegisterPrinter() - Start sending broadcast information for a
56 * printer or update the broadcast contents.
66 # endif /* HAVE_SYSTEMCONFIGURATION */
67 # endif /* __APPLE__ */
68 #endif /* HAVE_DNSSD */
70 +# include <avahi-common/domain.h>
71 +#endif /* HAVE_AVAHI */
75 +typedef char *cupsd_txt_record_t;
76 +#endif /* HAVE_DNSSD */
78 +typedef AvahiStringList *cupsd_txt_record_t;
79 +#endif /* HAVE_AVAHI */
83 @@ -159,26 +174,39 @@ static void update_polling(void);
84 static void update_smb(int onoff);
87 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
88 +static cupsd_txt_record_t dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
90 +static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
91 +static void dnssdDeregisterPrinter(cupsd_printer_t *p);
92 +static void dnssdRegisterPrinter(cupsd_printer_t *p);
93 +static void dnssdStop(void);
94 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
97 # ifdef HAVE_COREFOUNDATION
98 static void dnssdAddAlias(const void *key, const void *value,
100 # endif /* HAVE_COREFOUNDATION */
101 -static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
103 -static void dnssdDeregisterPrinter(cupsd_printer_t *p);
104 -static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
106 static void dnssdRegisterCallback(DNSServiceRef sdRef,
107 DNSServiceFlags flags,
108 DNSServiceErrorType errorCode,
109 const char *name, const char *regtype,
110 const char *domain, void *context);
111 -static void dnssdRegisterPrinter(cupsd_printer_t *p);
112 -static void dnssdStop(void);
113 static void dnssdUpdate(void);
114 #endif /* HAVE_DNSSD */
117 +static AvahiStringList *avahiPackTxtRecord(char *keyvalue[][2],
119 +static void avahi_entry_group_cb (AvahiEntryGroup *group,
120 + AvahiEntryGroupState state,
122 +static void avahi_client_cb (AvahiClient *client,
123 + AvahiClientState state,
125 +#endif /* HAVE_AVAHI */
129 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
130 @@ -283,10 +310,10 @@ cupsdDeregisterPrinter(
131 ldap_dereg_printer(p);
132 #endif /* HAVE_LDAP */
135 - if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
136 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
137 + if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD))
138 dnssdDeregisterPrinter(p);
139 -#endif /* HAVE_DNSSD */
140 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
144 @@ -702,10 +729,10 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
145 slpRegisterPrinter(p); */
146 #endif /* HAVE_LIBSLP */
149 - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
150 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
151 + if ((BrowseLocalProtocols & BROWSE_DNSSD))
152 dnssdRegisterPrinter(p);
153 -#endif /* HAVE_DNSSD */
154 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
158 @@ -1419,6 +1446,27 @@ ldap_disconnect(LDAP *ld) /* I - LDAP handle */
159 #endif /* HAVE_LDAP */
164 + * 'cupsdStartAvahiClient()' - Start an Avahi client if needed
168 +cupsdStartAvahiClient(void)
170 + if (!AvahiCupsClient && !AvahiCupsClientConnecting)
172 + if (!AvahiCupsPollHandle)
173 + AvahiCupsPollHandle = avahi_cups_poll_new ();
175 + if (AvahiCupsPollHandle)
176 + avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle),
177 + AVAHI_CLIENT_NO_FAIL, avahi_client_cb, NULL, NULL);
180 +#endif /* HAVE_AVAHI */
184 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
186 @@ -1542,13 +1590,16 @@ cupsdStartBrowsing(void)
191 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
192 if (BrowseLocalProtocols & BROWSE_DNSSD)
195 DNSServiceErrorType error; /* Error from service creation */
196 +#endif /* HAVE_DNSSD */
197 cupsd_listener_t *lis; /* Current listening socket */
202 * First create a "master" connection for all registrations...
204 @@ -1573,6 +1624,7 @@ cupsdStartBrowsing(void)
205 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
207 cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
208 +#endif /* HAVE_DNSSD */
211 * Then get the port we use for registrations. If we are not listening
212 @@ -1606,9 +1658,16 @@ cupsdStartBrowsing(void)
215 cupsdUpdateDNSSDName();
218 + cupsdStartAvahiClient ();
219 +#endif /* HAVE_AVAHI */
224 #endif /* HAVE_DNSSD */
226 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
229 * Enable LPD and SMB printer sharing as needed through external programs...
230 @@ -1834,10 +1893,10 @@ cupsdStopBrowsing(void)
235 - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
236 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
237 + if ((BrowseLocalProtocols & BROWSE_DNSSD))
239 -#endif /* HAVE_DNSSD */
240 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
243 if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) &&
244 @@ -1902,7 +1961,7 @@ cupsdStopPolling(void)
249 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
251 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
253 @@ -1910,8 +1969,14 @@ cupsdStopPolling(void)
255 cupsdUpdateDNSSDName(void)
258 DNSServiceErrorType error; /* Error from service creation */
259 char webif[1024]; /* Web interface share name */
260 +#endif /* HAVE_DNSSD */
262 + int ret; /* Error from service creation */
263 + char webif[AVAHI_LABEL_MAX]; /* Web interface share name */
264 +#endif /* HAVE_AVAHI */
265 # ifdef HAVE_SYSTEMCONFIGURATION
266 SCDynamicStoreRef sc; /* Context for dynamic store */
267 CFDictionaryRef btmm; /* Back-to-My-Mac domains */
268 @@ -2042,6 +2107,7 @@ cupsdUpdateDNSSDName(void)
270 strlcpy(webif, "CUPS Web Interface", sizeof(webif));
274 DNSServiceRefDeallocate(WebIFRef);
276 @@ -2054,9 +2120,45 @@ cupsdUpdateDNSSDName(void)
277 NULL)) != kDNSServiceErr_NoError)
278 cupsdLogMessage(CUPSD_LOG_ERROR,
279 "DNS-SD web interface registration failed: %d", error);
280 +#endif /* HAVE_DNSSD */
283 + if (!AvahiCupsClient)
285 + * Client not yet running.
289 + if (AvahiWebIFGroup)
290 + avahi_entry_group_reset (AvahiWebIFGroup);
292 + AvahiWebIFGroup = avahi_entry_group_new (AvahiCupsClient,
293 + avahi_entry_group_cb,
296 + if (AvahiWebIFGroup)
298 + ret = avahi_entry_group_add_service (AvahiWebIFGroup,
300 + AVAHI_PROTO_UNSPEC,
303 + "_http._tcp", /* type */
306 + DNSSDPort, /* port */
309 + ret = avahi_entry_group_commit (AvahiWebIFGroup);
312 + cupsdLogMessage (CUPSD_LOG_ERROR,
313 + "Avahi web interface registration failed: %d", ret);
315 +#endif /* HAVE_AVAHI */
318 -#endif /* HAVE_DNSSD */
319 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
323 @@ -2334,13 +2436,15 @@ dnssdAddAlias(const void *key, /* I - Key */
324 "Bad Back to My Mac domain in dynamic store!");
326 # endif /* HAVE_COREFOUNDATION */
327 +#endif /* HAVE_DNSSD */
330 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
332 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
335 -static char * /* O - TXT record */
336 +static cupsd_txt_record_t /* O - TXT record */
338 int *txt_len, /* O - TXT record length */
339 cupsd_printer_t *p, /* I - Printer information */
340 @@ -2379,7 +2483,12 @@ dnssdBuildTxtRecord(
341 keyvalue[i ][0] = "ty";
342 keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
344 - snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
345 + snprintf(admin_hostname, sizeof(admin_hostname),
348 + "." /* terminating dot no good for Avahi */
349 +#endif /* HAVE_DNSSD */
351 httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
352 "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
353 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
354 @@ -2462,7 +2571,12 @@ dnssdBuildTxtRecord(
355 * Then pack them into a proper txt record...
359 return (dnssdPackTxtRecord(txt_len, keyvalue, i));
360 +#endif /* HAVE_DNSSD */
362 + return (avahiPackTxtRecord(keyvalue, i));
363 +#endif /* HAVE_AVAHI */
367 @@ -2489,6 +2612,10 @@ dnssdDeregisterPrinter(
369 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
376 * Closing the socket deregisters the service
378 @@ -2524,6 +2651,24 @@ dnssdDeregisterPrinter(
379 free(p->printer_txt);
380 p->printer_txt = NULL;
382 +#endif /* HAVE_DNSSD */
385 + if (p->avahi_group)
387 + avahi_entry_group_reset (p->avahi_group);
388 + avahi_entry_group_free (p->avahi_group);
389 + p->avahi_group = NULL;
392 + avahi_string_list_free (p->ipp_txt);
394 + if (p->printer_txt)
395 + avahi_string_list_free (p->printer_txt);
397 + p->ipp_txt = p->printer_txt = NULL;
399 +#endif /* HAVE_AVAHI */
402 * Remove the printer from the array of DNS-SD printers, then clear the
403 @@ -2533,8 +2678,10 @@ dnssdDeregisterPrinter(
404 cupsArrayRemove(DNSSDPrinters, p);
405 cupsdClearString(&p->reg_name);
407 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
412 * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
414 @@ -2644,8 +2791,10 @@ dnssdRegisterCallback(
415 LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
418 +#endif /* HAVE_DNSSD */
421 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
423 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
424 * or update the broadcast contents.
425 @@ -2654,20 +2803,40 @@ dnssdRegisterCallback(
427 dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
430 DNSServiceErrorType se; /* dnssd errors */
431 char *ipp_txt, /* IPP TXT record buffer */
432 *printer_txt, /* LPD TXT record buffer */
433 - name[1024], /* Service name */
434 - *nameptr; /* Pointer into name */
435 + name[1024]; /* Service name */
436 int ipp_len, /* IPP TXT record length */
437 printer_len, /* LPD TXT record length */
438 printer_port; /* LPD port number */
439 +#endif /* HAVE_DNSSD */
441 + int ret; /* Error code */
442 + AvahiStringList *ipp_txt, /* IPP TXT record */
443 + *printer_txt; /* LPD TXT record */
444 + char name[AVAHI_LABEL_MAX], /* Service name */
445 + fullsubtype[AVAHI_LABEL_MAX]; /* Full subtype */
446 + char *regtype_copy, /* Writeable copy of reg type */
447 + *subtype, /* Current service sub type */
448 + *nextsubtype; /* Next service sub type */
449 +#endif /* HAVE_AVAHI */
450 + char *nameptr; /* Pointer into name */
451 const char *regtype; /* Registration type */
458 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
459 !p->ipp_ref ? "new" : "update");
461 +#endif /* HAVE_DNSSD */
463 + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
464 + !p->avahi_group ? "new" : "update");
465 +#endif /* HAVE_AVAHI */
467 * If per-printer sharing was just disabled make sure we're not
468 * registered before returning.
469 @@ -2686,12 +2855,36 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
470 if (p->info && strlen(p->info) > 0)
472 if (DNSSDComputerName)
473 - snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
476 + * Make sure there is room for at least 15 characters of
477 + * DNSSDComputerName.
480 + assert(sizeof(name) >= 15 + 4);
481 + nameptr = name + strlcpy(name, p->info,
483 + strnlen(DNSSDComputerName, 15));
484 + nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
485 + strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
488 strlcpy(name, p->info, sizeof(name));
490 else if (DNSSDComputerName)
491 - snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
494 + * Make sure there is room for at least 15 characters of
495 + * DNSSDComputerName.
498 + assert(sizeof(name) >= 15 + 4);
499 + nameptr = name + strlcpy(name, p->info,
501 + strnlen(DNSSDComputerName, 15));
502 + nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
503 + strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
506 strlcpy(name, p->name, sizeof(name));
508 @@ -2712,6 +2905,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
509 * Register IPP and (optionally) LPD...
513 ipp_len = 0; /* anti-compiler-warning-code */
514 ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
516 @@ -2884,6 +3078,209 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
520 +#endif /* HAVE_DNSSD */
522 + if (!AvahiCupsClient)
524 + * Client not running yet. The client callback will call us again later.
528 + ipp_txt = dnssdBuildTxtRecord(NULL, p, 0);
529 + printer_txt = dnssdBuildTxtRecord(NULL, p, 1);
530 + regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
532 + if (p->avahi_group && p->ipp_txt && ipp_txt &&
533 + !avahi_string_list_equal (p->ipp_txt, ipp_txt))
536 + * Update the existing registration...
539 + avahi_string_list_free (p->ipp_txt);
541 + if (p->printer_txt)
542 + avahi_string_list_free (p->printer_txt);
545 + * Update the service group entry.
548 + regtype_copy = strdup (regtype);
549 + subtype = strchr (regtype_copy, ',');
553 + cupsdLogMessage (CUPSD_LOG_DEBUG,
554 + "Updating TXT record for %s (%s)", name, regtype_copy);
555 + ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
557 + AVAHI_PROTO_UNSPEC,
561 + free (regtype_copy);
564 + goto update_failed;
566 + p->ipp_txt = ipp_txt;
569 + if (BrowseLocalProtocols & BROWSE_LPD)
571 + ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
573 + AVAHI_PROTO_UNSPEC,
575 + "_printer._tcp", NULL,
578 + goto update_failed;
580 + p->printer_txt = printer_txt;
581 + printer_txt = NULL;
584 + ret = avahi_entry_group_commit (p->avahi_group);
588 + cupsdLogMessage (CUPSD_LOG_ERROR,
589 + "Failed to update TXT record for %s: %d",
591 + avahi_entry_group_reset (p->avahi_group);
592 + avahi_entry_group_free (p->avahi_group);
593 + p->avahi_group = NULL;
594 + ipp_txt = p->ipp_txt;
599 + if (!p->avahi_group)
602 + * Initial registration. Use the _fax subtype for fax queues...
605 + p->avahi_group = avahi_entry_group_new (AvahiCupsClient,
606 + avahi_entry_group_cb,
609 + cupsdLogMessage(CUPSD_LOG_DEBUG,
610 + "Registering Avahi printer %s with name \"%s\" and "
611 + "type \"%s\"", p->name, name, regtype);
613 + if (!p->avahi_group)
620 + * Add each service type (DNSSDRegType may contain several,
621 + * separated by commas).
624 + subtype = regtype_copy = strdup (regtype);
625 + while (subtype && *subtype)
627 + nextsubtype = strchr (subtype, ',');
629 + *nextsubtype++ = '\0';
631 + if (subtype == regtype_copy)
637 + cupsdLogMessage (CUPSD_LOG_DEBUG,
638 + "Adding TXT record for %s (%s)", name, regtype_copy);
639 + ret = avahi_entry_group_add_service_strlst (p->avahi_group,
641 + AVAHI_PROTO_UNSPEC,
642 + 0, name, regtype_copy,
653 + snprintf (fullsubtype, sizeof(fullsubtype),
654 + "%s._sub.%s", subtype, regtype_copy);
655 + cupsdLogMessage (CUPSD_LOG_DEBUG,
656 + "Adding TXT record for %s (%s)", name, fullsubtype);
657 + ret = avahi_entry_group_add_service_subtype (p->avahi_group,
659 + AVAHI_PROTO_UNSPEC,
662 + NULL, fullsubtype);
667 + free (regtype_copy);
671 + subtype = nextsubtype;
674 + free (regtype_copy);
675 + p->ipp_txt = ipp_txt;
678 + if (BrowseLocalProtocols & BROWSE_LPD)
680 + cupsdLogMessage(CUPSD_LOG_DEBUG,
681 + "Registering Avahi printer %s with name \"%s\" and "
682 + "type \"_printer._tcp\"", p->name, name);
684 + ret = avahi_entry_group_add_service_strlst (p->avahi_group,
686 + AVAHI_PROTO_UNSPEC,
688 + "_printer._tcp", NULL, NULL,
694 + p->printer_txt = printer_txt;
695 + printer_txt = NULL;
698 + ret = avahi_entry_group_commit (p->avahi_group);
703 + cupsdLogMessage (CUPSD_LOG_ERROR,
704 + "Failed to add Avahi entry for %s: %d",
706 + if (p->avahi_group)
708 + avahi_entry_group_reset (p->avahi_group);
709 + avahi_entry_group_free (p->avahi_group);
710 + p->avahi_group = NULL;
712 + ipp_txt = p->ipp_txt;
718 + avahi_string_list_free (ipp_txt);
721 + avahi_string_list_free (printer_txt);
722 +#endif /* HAVE_AVAHI */
726 @@ -2896,6 +3293,10 @@ dnssdStop(void)
728 cupsd_printer_t *p; /* Current printer */
733 +#endif /* HAVE_DNSSD */
736 * De-register the individual printers
737 @@ -2906,6 +3307,7 @@ dnssdStop(void)
738 p = (cupsd_printer_t *)cupsArrayNext(Printers))
739 dnssdDeregisterPrinter(p);
743 * Shutdown the rest of the service refs...
745 @@ -2926,14 +3328,17 @@ dnssdStop(void)
747 DNSServiceRefDeallocate(DNSSDRef);
749 +#endif /* HAVE_DNSSD */
751 cupsArrayDelete(DNSSDPrinters);
752 DNSSDPrinters = NULL;
756 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
761 * 'dnssdUpdate()' - Handle DNS-SD queries.
763 @@ -2955,6 +3360,147 @@ dnssdUpdate(void)
764 #endif /* HAVE_DNSSD */
769 + * 'avahiPackTxtRecord()' - Pack an array of key/value pairs into an
773 +static AvahiStringList * /* O - new string list */
774 +avahiPackTxtRecord(char *keyvalue[][2], /* I - Table of key value pairs */
775 + int count) /* I - Number of items in table */
777 + AvahiStringList *strlst = NULL;
782 + elements = malloc ((1 + count) * sizeof (char *));
786 + for (i = 0; i < count; i++)
788 + len = (1 + strlen (keyvalue[i][0]) +
789 + (keyvalue[i][1] ? 1 + strlen (keyvalue[i][1]) : 1));
790 + elements[i] = malloc (len * sizeof (char));
794 + snprintf (elements[i], len, "%s=%s", keyvalue[i][0], keyvalue[i][1]);
797 + strlst = avahi_string_list_new_from_array ((const char **) elements, count);
801 + free (elements[i]);
809 + * 'avahi_entry_group_cb()' - Avahi entry group callback function.
812 +avahi_entry_group_cb (AvahiEntryGroup *group,
813 + AvahiEntryGroupState state,
819 + name = ((cupsd_printer_t *) userdata)->reg_name;
821 + name = "CUPS web interface";
825 + case AVAHI_ENTRY_GROUP_UNCOMMITED:
826 + case AVAHI_ENTRY_GROUP_REGISTERING:
829 + case AVAHI_ENTRY_GROUP_ESTABLISHED:
830 + cupsdLogMessage (CUPSD_LOG_DEBUG,
831 + "Avahi entry group established for %s", name);
835 + cupsdLogMessage (CUPSD_LOG_DEBUG,
836 + "Avahi entry group %s has state %d",
844 + * 'avahi_client_cb()' - Avahi client callback function.
847 +avahi_client_cb (AvahiClient *client,
848 + AvahiClientState state,
851 + cupsd_printer_t *printer;
854 + case AVAHI_CLIENT_S_RUNNING:
856 + * Avahi client started successfully.
858 + AvahiCupsClient = client;
859 + AvahiCupsClientConnecting = 0;
860 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started");
862 + cupsdUpdateDNSSDName ();
864 + for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
866 + printer = (cupsd_printer_t *)cupsArrayNext(Printers))
867 + if (Browsing && (BrowseLocalProtocols & BROWSE_DNSSD) &&
868 + (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
869 + CUPS_PRINTER_SCANNER))) && printer->shared)
870 + dnssdRegisterPrinter (printer);
874 + case AVAHI_CLIENT_CONNECTING:
876 + * No Avahi daemon, client is waiting.
878 + AvahiCupsClientConnecting = 1;
879 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting");
882 + case AVAHI_CLIENT_FAILURE:
884 + * Avahi client failed, close it to allow a clean restart.
886 + cupsdLogMessage (CUPSD_LOG_ERROR,
887 + "Avahi client failed, "
888 + "closing client to allow a clean restart");
890 + for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
892 + printer = (cupsd_printer_t *)cupsArrayNext(Printers))
893 + dnssdDeregisterPrinter (printer);
895 + avahi_client_free(client);
896 + AvahiCupsClientConnecting = 0;
897 + AvahiCupsClient = NULL;
902 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client state: %d", state);
905 +#endif /* HAVE_AVAHI */
909 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
911 diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
912 index 99079bd..d53a179 100644
913 --- a/scheduler/dirsvc.h
914 +++ b/scheduler/dirsvc.h
916 * file is missing or damaged, see the license at "http://www.cups.org/".
920 +# include <avahi-client/publish.h>
921 +#endif /* HAVE_AVAHI */
924 * Browse protocols...
926 @@ -131,19 +135,22 @@ VAR int PollPipe VALUE(0);
929 /* Protocols to support for local printers */
931 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
932 VAR char *DNSSDComputerName VALUE(NULL),
933 /* Computer/server name */
934 *DNSSDHostName VALUE(NULL),
936 *DNSSDRegType VALUE(NULL);
937 /* Bonjour registration type */
938 -VAR cups_array_t *DNSSDAlias VALUE(NULL);
939 - /* List of dynamic ServerAlias's */
940 VAR int DNSSDPort VALUE(0);
941 /* Port number to register */
942 VAR cups_array_t *DNSSDPrinters VALUE(NULL);
943 /* Printers we have registered */
944 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
947 +VAR cups_array_t *DNSSDAlias VALUE(NULL);
948 + /* List of dynamic ServerAlias's */
949 VAR DNSServiceRef DNSSDRef VALUE(NULL),
950 /* Master DNS-SD service reference */
951 WebIFRef VALUE(NULL);
952 @@ -152,6 +159,17 @@ VAR DNSServiceRef DNSSDRef VALUE(NULL),
953 /* Remote printer browse reference */
954 #endif /* HAVE_DNSSD */
957 +VAR AvahiCupsPoll *AvahiCupsPollHandle VALUE(NULL);
958 + /* AvahiCupsPoll object */
959 +VAR AvahiClient *AvahiCupsClient VALUE(NULL);
960 + /* AvahiClient object */
961 +VAR int AvahiCupsClientConnecting VALUE(0);
962 + /* Is AvahiClient object connecting? */
963 +VAR AvahiEntryGroup *AvahiWebIFGroup VALUE(NULL);
964 + /* Web interface entry group */
965 +#endif /* HAVE_AVAHI */
967 VAR char *LPDConfigFile VALUE(NULL),
968 /* LPD configuration file */
969 *SMBConfigFile VALUE(NULL);
970 @@ -195,11 +213,12 @@ extern void cupsdRegisterPrinter(cupsd_printer_t *p);
972 extern void cupsdDeregisterPrinter(cupsd_printer_t *p, int removeit);
973 extern void cupsdRegisterPrinter(cupsd_printer_t *p);
974 +extern void cupsdStartAvahiClient(void);
975 extern void cupsdStartBrowsing(void);
976 extern void cupsdStopBrowsing(void);
978 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
979 extern void cupsdUpdateDNSSDName(void);
980 -#endif /* HAVE_DNSSD */
981 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
985 diff --git a/scheduler/ipp.c b/scheduler/ipp.c
986 index a048baa..9a3ab11 100644
987 --- a/scheduler/ipp.c
988 +++ b/scheduler/ipp.c
989 @@ -6087,7 +6087,7 @@ copy_printer_attrs(
990 ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
991 ippTimeToDate(curtime));
994 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
995 if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
997 if (printer->reg_name)
998 @@ -6097,7 +6097,7 @@ copy_printer_attrs(
999 ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
1000 "printer-dns-sd-name", 0);
1002 -#endif /* HAVE_DNSSD */
1003 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1005 if (!ra || cupsArrayFind(ra, "printer-error-policy"))
1006 ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
1007 diff --git a/scheduler/main.c b/scheduler/main.c
1008 index 1e60572..6c210e6 100644
1009 --- a/scheduler/main.c
1010 +++ b/scheduler/main.c
1011 @@ -120,6 +120,10 @@ main(int argc, /* I - Number of command-line args */
1012 cupsd_listener_t *lis; /* Current listener */
1013 time_t current_time, /* Current time */
1014 activity, /* Client activity timer */
1016 + avahi_client_time, /* Time for next Avahi client
1018 +#endif /* HAVE_AVAHI */
1019 senddoc_time, /* Send-Document time */
1020 expire_time, /* Subscription expire time */
1021 report_time, /* Malloc/client/job report time */
1022 @@ -662,6 +666,9 @@ main(int argc, /* I - Number of command-line args */
1025 current_time = time(NULL);
1027 + avahi_client_time = current_time;
1028 +#endif /* HAVE_AVAHI */
1029 event_time = current_time;
1030 expire_time = current_time;
1032 @@ -884,6 +891,16 @@ main(int argc, /* I - Number of command-line args */
1033 tmo = cupsdNextTimeout (&tmo_delay);
1034 if (tmo && tmo_delay == 0)
1035 cupsdRunTimeout (tmo);
1038 + * Try to restart the Avahi client every 10 seconds if needed...
1041 + if ((current_time - avahi_client_time) >= 10)
1043 + avahi_client_time = current_time;
1044 + cupsdStartAvahiClient();
1046 #endif /* HAVE_AVAHI */
1049 diff --git a/scheduler/printers.c b/scheduler/printers.c
1050 index 4686c4c..fac7bbc 100644
1051 --- a/scheduler/printers.c
1052 +++ b/scheduler/printers.c
1053 @@ -883,9 +883,9 @@ cupsdDeletePrinter(
1054 cupsdClearString(&p->alert);
1055 cupsdClearString(&p->alert_description);
1058 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1059 cupsdClearString(&p->pdl);
1060 -#endif /* HAVE_DNSSD */
1061 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1063 cupsArrayDelete(p->filetypes);
1065 @@ -3765,7 +3765,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
1066 attr->values[i].string.text = _cupsStrAlloc(mimetype);
1070 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1072 char pdl[1024]; /* Buffer to build pdl list */
1073 mime_filter_t *filter; /* MIME filter looping var */
1074 @@ -3821,7 +3821,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
1076 cupsdSetString(&p->pdl, pdl);
1078 -#endif /* HAVE_DNSSD */
1079 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1083 diff --git a/scheduler/printers.h b/scheduler/printers.h
1084 index 1751578..fb04651 100644
1085 --- a/scheduler/printers.h
1086 +++ b/scheduler/printers.h
1089 # include <dns_sd.h>
1090 #endif /* HAVE_DNSSD */
1092 +# include "avahi.h"
1093 +#endif /* HAVE_AVAHI */
1094 #include <cups/pwg-private.h>
1097 @@ -95,16 +98,23 @@ struct cupsd_printer_s
1098 time_t marker_time; /* Last time marker attributes were updated */
1099 _ppd_cache_t *pc; /* PPD cache and mapping data */
1102 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1103 char *reg_name, /* Name used for service registration */
1104 - *pdl, /* pdl value for TXT record */
1105 - *ipp_txt, /* IPP TXT record contents */
1106 + *pdl; /* pdl value for TXT record */
1107 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1109 + char *ipp_txt, /* IPP TXT record contents */
1110 *printer_txt; /* LPD TXT record contents */
1111 int ipp_len, /* IPP TXT record length */
1112 printer_len; /* LPD TXT record length */
1113 DNSServiceRef ipp_ref, /* Reference for _ipp._tcp,_cups */
1114 printer_ref; /* Reference for _printer._tcp */
1115 #endif /* HAVE_DNSSD */
1117 + AvahiStringList *ipp_txt, /* IPP TXT record */
1118 + *printer_txt; /* LPD TXT record */
1119 + AvahiEntryGroup *avahi_group; /* Avahi entry group */
1120 +#endif /* HAVE_AVAHI */