]> git.pld-linux.org Git - packages/cups.git/blame - cups-avahi-5-services.patch
- 1.5.1
[packages/cups.git] / cups-avahi-5-services.patch
CommitLineData
d07e62b1
ER
1diff --git a/scheduler/client.c b/scheduler/client.c
2index 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));
7 }
8
9-#ifdef HAVE_DNSSD
10+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
11 /*
12 * Check if the hostname is something.local (Bonjour); if so, allow it.
13 */
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)))
17 return (1);
18-#endif /* HAVE_DNSSD */
19+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
20
21 /*
22 * Check if the hostname is an IP address...
23diff --git a/scheduler/conf.c b/scheduler/conf.c
24index 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;
30
31-#ifdef HAVE_DNSSD
32+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
33 cupsdSetString(&DNSSDRegType, "_ipp._tcp,_cups");
34 #endif /* HAVE_DNSSD */
35
36diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
37index eb3c862..48dcef9 100644
38--- a/scheduler/dirsvc.c
39+++ b/scheduler/dirsvc.c
40@@ -27,6 +27,7 @@
1b240119
JR
41 * remote printers.
42 * cupsdRegisterPrinter() - Start sending broadcast information for a
43 * printer or update the broadcast contents.
d07e62b1 44+ * cupsdStartAvahiClient() - Start an Avahi client if needed
1b240119
JR
45 * cupsdStartBrowsing() - Start sending and receiving broadcast
46 * information.
47 * cupsdStopBrowsing() - Stop sending and receiving broadcast
d07e62b1 48@@ -45,6 +46,8 @@
1b240119
JR
49 * printer.
50 * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
51 * record format.
d07e62b1
ER
52+ * avahiPackTxtRecord() - Pack an array of key/value pairs into an
53+ * AvahiStringList.
1b240119
JR
54 * dnssdRegisterCallback() - DNSServiceRegister callback.
55 * dnssdRegisterPrinter() - Start sending broadcast information for a
56 * printer or update the broadcast contents.
d07e62b1
ER
57@@ -83,6 +86,7 @@
58 */
59
60 #include "cupsd.h"
61+#include <assert.h>
62 #include <grp.h>
63
64 #ifdef HAVE_DNSSD
65@@ -97,6 +101,17 @@
66 # endif /* HAVE_SYSTEMCONFIGURATION */
67 # endif /* __APPLE__ */
68 #endif /* HAVE_DNSSD */
69+#ifdef HAVE_AVAHI
70+# include <avahi-common/domain.h>
71+#endif /* HAVE_AVAHI */
72+
73+
74+#ifdef HAVE_DNSSD
75+typedef char *cupsd_txt_record_t;
76+#endif /* HAVE_DNSSD */
77+#ifdef HAVE_AVAHI
78+typedef AvahiStringList *cupsd_txt_record_t;
79+#endif /* HAVE_AVAHI */
80
81
82 /*
1b240119 83@@ -159,26 +174,39 @@ static void update_polling(void);
d07e62b1
ER
84 static void update_smb(int onoff);
85
86
87+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
88+static cupsd_txt_record_t dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
89+ int for_lpd);
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) */
95+
96 #ifdef HAVE_DNSSD
97 # ifdef HAVE_COREFOUNDATION
98 static void dnssdAddAlias(const void *key, const void *value,
99 void *context);
100 # endif /* HAVE_COREFOUNDATION */
101-static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
102- int for_lpd);
d07e62b1
ER
103-static void dnssdDeregisterPrinter(cupsd_printer_t *p);
104-static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
105- int count);
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 */
115
116+#ifdef HAVE_AVAHI
117+static AvahiStringList *avahiPackTxtRecord(char *keyvalue[][2],
118+ int count);
119+static void avahi_entry_group_cb (AvahiEntryGroup *group,
120+ AvahiEntryGroupState state,
121+ void *userdata);
122+static void avahi_client_cb (AvahiClient *client,
123+ AvahiClientState state,
124+ void *userdata);
125+#endif /* HAVE_AVAHI */
126+
1b240119
JR
127
128 /*
129 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
d07e62b1
ER
130@@ -283,10 +310,10 @@ cupsdDeregisterPrinter(
131 ldap_dereg_printer(p);
132 #endif /* HAVE_LDAP */
133
134-#ifdef HAVE_DNSSD
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) */
141 }
142
143
144@@ -702,10 +729,10 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
145 slpRegisterPrinter(p); */
146 #endif /* HAVE_LIBSLP */
147
148-#ifdef HAVE_DNSSD
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) */
155 }
156
157
158@@ -1419,6 +1446,27 @@ ldap_disconnect(LDAP *ld) /* I - LDAP handle */
159 #endif /* HAVE_LDAP */
160
161
162+#ifdef HAVE_AVAHI
163+/*
164+ * 'cupsdStartAvahiClient()' - Start an Avahi client if needed
165+ */
166+
167+void
168+cupsdStartAvahiClient(void)
169+{
170+ if (!AvahiCupsClient && !AvahiCupsClientConnecting)
171+ {
172+ if (!AvahiCupsPollHandle)
173+ AvahiCupsPollHandle = avahi_cups_poll_new ();
174+
175+ if (AvahiCupsPollHandle)
176+ avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle),
177+ AVAHI_CLIENT_NO_FAIL, avahi_client_cb, NULL, NULL);
178+ }
179+}
180+#endif /* HAVE_AVAHI */
181+
182+
183 /*
184 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
185 */
186@@ -1542,13 +1590,16 @@ cupsdStartBrowsing(void)
187 else
188 BrowseSocket = -1;
189
190-#ifdef HAVE_DNSSD
191+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1b240119 192 if (BrowseLocalProtocols & BROWSE_DNSSD)
d07e62b1
ER
193 {
194+#ifdef HAVE_DNSSD
195 DNSServiceErrorType error; /* Error from service creation */
196+#endif /* HAVE_DNSSD */
197 cupsd_listener_t *lis; /* Current listening socket */
198
199
200+#ifdef HAVE_DNSSD
201 /*
202 * First create a "master" connection for all registrations...
203 */
204@@ -1573,6 +1624,7 @@ cupsdStartBrowsing(void)
205 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
206
207 cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
208+#endif /* HAVE_DNSSD */
209
210 /*
211 * Then get the port we use for registrations. If we are not listening
212@@ -1606,9 +1658,16 @@ cupsdStartBrowsing(void)
213 */
214
215 cupsdUpdateDNSSDName();
216+
217+#ifdef HAVE_AVAHI
218+ cupsdStartAvahiClient ();
219+#endif /* HAVE_AVAHI */
220+
221+#ifdef HAVE_DNSSD
222 }
223- }
224 #endif /* HAVE_DNSSD */
225+ }
226+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
227
1b240119
JR
228 /*
229 * Enable LPD and SMB printer sharing as needed through external programs...
d07e62b1
ER
230@@ -1834,10 +1893,10 @@ cupsdStopBrowsing(void)
231 BrowseSocket = -1;
232 }
233
234-#ifdef HAVE_DNSSD
235- if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
236+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
237+ if ((BrowseLocalProtocols & BROWSE_DNSSD))
238 dnssdStop();
239-#endif /* HAVE_DNSSD */
240+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
241
242 #ifdef HAVE_LIBSLP
243 if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) &&
244@@ -1902,7 +1961,7 @@ cupsdStopPolling(void)
245 }
246
247
248-#ifdef HAVE_DNSSD
249+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
250 /*
251 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
252 */
253@@ -1910,8 +1969,14 @@ cupsdStopPolling(void)
254 void
255 cupsdUpdateDNSSDName(void)
256 {
257+#ifdef HAVE_DNSSD
258 DNSServiceErrorType error; /* Error from service creation */
259 char webif[1024]; /* Web interface share name */
260+#endif /* HAVE_DNSSD */
261+#ifdef HAVE_AVAHI
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)
269 else
270 strlcpy(webif, "CUPS Web Interface", sizeof(webif));
271
272+#ifdef HAVE_DNSSD
273 if (WebIFRef)
274 DNSServiceRefDeallocate(WebIFRef);
275
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 */
281+
282+#ifdef HAVE_AVAHI
283+ if (!AvahiCupsClient)
284+ /*
285+ * Client not yet running.
286+ */
287+ return;
288+
289+ if (AvahiWebIFGroup)
290+ avahi_entry_group_reset (AvahiWebIFGroup);
291+ else
292+ AvahiWebIFGroup = avahi_entry_group_new (AvahiCupsClient,
293+ avahi_entry_group_cb,
294+ NULL);
295+
296+ if (AvahiWebIFGroup)
297+ {
298+ ret = avahi_entry_group_add_service (AvahiWebIFGroup,
299+ AVAHI_IF_UNSPEC,
300+ AVAHI_PROTO_UNSPEC,
301+ 0, /* flags */
302+ webif, /* name */
303+ "_http._tcp", /* type */
304+ NULL, /* domain */
305+ NULL, /* host */
306+ DNSSDPort, /* port */
307+ "path=/", NULL);
308+ if (ret == 0)
309+ ret = avahi_entry_group_commit (AvahiWebIFGroup);
310+
311+ if (ret != 0)
312+ cupsdLogMessage (CUPSD_LOG_ERROR,
313+ "Avahi web interface registration failed: %d", ret);
314+ }
315+#endif /* HAVE_AVAHI */
316 }
317 }
318-#endif /* HAVE_DNSSD */
319+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
320
321
322 #ifdef HAVE_LDAP
323@@ -2334,13 +2436,15 @@ dnssdAddAlias(const void *key, /* I - Key */
324 "Bad Back to My Mac domain in dynamic store!");
325 }
326 # endif /* HAVE_COREFOUNDATION */
327+#endif /* HAVE_DNSSD */
328
329
330+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
331 /*
332 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
333 */
334
335-static char * /* O - TXT record */
336+static cupsd_txt_record_t /* O - TXT record */
337 dnssdBuildTxtRecord(
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";
343
344- snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
345+ snprintf(admin_hostname, sizeof(admin_hostname),
346+ "%s.local"
347+#ifdef HAVE_DNSSD
348+ "." /* terminating dot no good for Avahi */
349+#endif /* HAVE_DNSSD */
350+ , DNSSDHostName);
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...
356 */
357
358+#ifdef HAVE_DNSSD
359 return (dnssdPackTxtRecord(txt_len, keyvalue, i));
360+#endif /* HAVE_DNSSD */
361+#ifdef HAVE_AVAHI
362+ return (avahiPackTxtRecord(keyvalue, i));
363+#endif /* HAVE_AVAHI */
364 }
365
366
d07e62b1
ER
367@@ -2489,6 +2612,10 @@ dnssdDeregisterPrinter(
368 {
369 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
370
371+#ifdef HAVE_DNSSD
372+ if (!DNSSDRef)
373+ return;
374+
375 /*
376 * Closing the socket deregisters the service
377 */
378@@ -2524,6 +2651,24 @@ dnssdDeregisterPrinter(
379 free(p->printer_txt);
380 p->printer_txt = NULL;
381 }
382+#endif /* HAVE_DNSSD */
383+
384+#ifdef HAVE_AVAHI
385+ if (p->avahi_group)
386+ {
387+ avahi_entry_group_reset (p->avahi_group);
388+ avahi_entry_group_free (p->avahi_group);
389+ p->avahi_group = NULL;
390+
391+ if (p->ipp_txt)
392+ avahi_string_list_free (p->ipp_txt);
393+
394+ if (p->printer_txt)
395+ avahi_string_list_free (p->printer_txt);
396+
397+ p->ipp_txt = p->printer_txt = NULL;
398+ }
399+#endif /* HAVE_AVAHI */
400
401 /*
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);
406 }
407+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
408
409
410+#ifdef HAVE_DNSSD
411 /*
412 * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
413 * TXT record format.
414@@ -2644,8 +2791,10 @@ dnssdRegisterCallback(
415 LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
416 }
417 }
418+#endif /* HAVE_DNSSD */
419
420
421+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
422 /*
423 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
424 * or update the broadcast contents.
425@@ -2654,20 +2803,40 @@ dnssdRegisterCallback(
426 static void
427 dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
428 {
429+#ifdef HAVE_DNSSD
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 */
440+#ifdef HAVE_AVAHI
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 */
452
453
454+#ifdef HAVE_DNSSD
455+ if (!DNSSDRef)
456+ return;
457+
458 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
459 !p->ipp_ref ? "new" : "update");
460-
461+#endif /* HAVE_DNSSD */
462+#ifdef HAVE_AVAHI
463+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
464+ !p->avahi_group ? "new" : "update");
465+#endif /* HAVE_AVAHI */
466 /*
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)
471 {
472 if (DNSSDComputerName)
473- snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
474+ {
475+ /*
476+ * Make sure there is room for at least 15 characters of
477+ * DNSSDComputerName.
478+ */
479+
480+ assert(sizeof(name) >= 15 + 4);
481+ nameptr = name + strlcpy(name, p->info,
482+ sizeof(name) - 4 -
483+ strnlen(DNSSDComputerName, 15));
484+ nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
485+ strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
486+ }
487 else
488 strlcpy(name, p->info, sizeof(name));
489 }
490 else if (DNSSDComputerName)
491- snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
492+ {
493+ /*
494+ * Make sure there is room for at least 15 characters of
495+ * DNSSDComputerName.
496+ */
497+
498+ assert(sizeof(name) >= 15 + 4);
499+ nameptr = name + strlcpy(name, p->info,
500+ sizeof(name) - 4 -
501+ strnlen(DNSSDComputerName, 15));
502+ nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
503+ strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
504+ }
505 else
506 strlcpy(name, p->name, sizeof(name));
507
508@@ -2712,6 +2905,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
509 * Register IPP and (optionally) LPD...
510 */
511
512+#ifdef HAVE_DNSSD
513 ipp_len = 0; /* anti-compiler-warning-code */
514 ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
515
516@@ -2884,6 +3078,209 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
517
518 if (printer_txt)
519 free(printer_txt);
520+#endif /* HAVE_DNSSD */
521+#ifdef HAVE_AVAHI
522+ if (!AvahiCupsClient)
523+ /*
524+ * Client not running yet. The client callback will call us again later.
525+ */
526+ return;
527+
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;
531+
532+ if (p->avahi_group && p->ipp_txt && ipp_txt &&
533+ !avahi_string_list_equal (p->ipp_txt, ipp_txt))
534+ {
535+ /*
536+ * Update the existing registration...
537+ */
538+
539+ avahi_string_list_free (p->ipp_txt);
540+
541+ if (p->printer_txt)
542+ avahi_string_list_free (p->printer_txt);
543+
544+ /*
545+ * Update the service group entry.
546+ */
547+
548+ regtype_copy = strdup (regtype);
549+ subtype = strchr (regtype_copy, ',');
550+ if (subtype)
551+ *subtype = '\0';
552+
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,
556+ AVAHI_IF_UNSPEC,
557+ AVAHI_PROTO_UNSPEC,
558+ 0, name,
559+ regtype_copy,
560+ NULL, ipp_txt);
561+ free (regtype_copy);
562+
563+ if (ret < 0)
564+ goto update_failed;
565+
566+ p->ipp_txt = ipp_txt;
567+ ipp_txt = NULL;
568+
569+ if (BrowseLocalProtocols & BROWSE_LPD)
570+ {
571+ ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
572+ AVAHI_IF_UNSPEC,
573+ AVAHI_PROTO_UNSPEC,
574+ 0, name,
575+ "_printer._tcp", NULL,
576+ printer_txt);
577+ if (ret < 0)
578+ goto update_failed;
579+
580+ p->printer_txt = printer_txt;
581+ printer_txt = NULL;
582+ }
583+
584+ ret = avahi_entry_group_commit (p->avahi_group);
585+ if (ret < 0)
586+ {
587+ update_failed:
588+ cupsdLogMessage (CUPSD_LOG_ERROR,
589+ "Failed to update TXT record for %s: %d",
590+ name, ret);
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;
595+ p->ipp_txt = NULL;
596+ }
597+ }
598+
599+ if (!p->avahi_group)
600+ {
601+ /*
602+ * Initial registration. Use the _fax subtype for fax queues...
603+ */
604+
605+ p->avahi_group = avahi_entry_group_new (AvahiCupsClient,
606+ avahi_entry_group_cb,
607+ p);
608+
609+ cupsdLogMessage(CUPSD_LOG_DEBUG,
610+ "Registering Avahi printer %s with name \"%s\" and "
611+ "type \"%s\"", p->name, name, regtype);
612+
613+ if (!p->avahi_group)
614+ {
615+ ret = 0;
616+ goto add_failed;
617+ }
618+
619+ /*
620+ * Add each service type (DNSSDRegType may contain several,
621+ * separated by commas).
622+ */
623+
624+ subtype = regtype_copy = strdup (regtype);
625+ while (subtype && *subtype)
626+ {
627+ nextsubtype = strchr (subtype, ',');
628+ if (nextsubtype)
629+ *nextsubtype++ = '\0';
630+
631+ if (subtype == regtype_copy)
632+ {
633+ /*
634+ * Main type entry.
635+ */
636+
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,
640+ AVAHI_IF_UNSPEC,
641+ AVAHI_PROTO_UNSPEC,
642+ 0, name, regtype_copy,
643+ NULL, NULL,
644+ DNSSDPort,
645+ ipp_txt);
646+ }
647+ else
648+ {
649+ /*
650+ * Sub-type entry.
651+ */
652+
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,
658+ AVAHI_IF_UNSPEC,
659+ AVAHI_PROTO_UNSPEC,
660+ 0, name,
661+ regtype_copy,
662+ NULL, fullsubtype);
663+ }
664+
665+ if (ret < 0)
666+ {
667+ free (regtype_copy);
668+ goto add_failed;
669+ }
670+
671+ subtype = nextsubtype;
672+ }
673+
674+ free (regtype_copy);
675+ p->ipp_txt = ipp_txt;
676+ ipp_txt = NULL;
677+
678+ if (BrowseLocalProtocols & BROWSE_LPD)
679+ {
680+ cupsdLogMessage(CUPSD_LOG_DEBUG,
681+ "Registering Avahi printer %s with name \"%s\" and "
682+ "type \"_printer._tcp\"", p->name, name);
683+
684+ ret = avahi_entry_group_add_service_strlst (p->avahi_group,
685+ AVAHI_IF_UNSPEC,
686+ AVAHI_PROTO_UNSPEC,
687+ 0, name,
688+ "_printer._tcp", NULL, NULL,
689+ 515,
690+ printer_txt);
691+ if (ret < 0)
692+ goto add_failed;
693+
694+ p->printer_txt = printer_txt;
695+ printer_txt = NULL;
696+ }
697+
698+ ret = avahi_entry_group_commit (p->avahi_group);
699+
700+ if (ret < 0)
701+ {
702+ add_failed:
703+ cupsdLogMessage (CUPSD_LOG_ERROR,
704+ "Failed to add Avahi entry for %s: %d",
705+ name, ret);
706+ if (p->avahi_group)
707+ {
708+ avahi_entry_group_reset (p->avahi_group);
709+ avahi_entry_group_free (p->avahi_group);
710+ p->avahi_group = NULL;
711+ }
712+ ipp_txt = p->ipp_txt;
713+ p->ipp_txt = NULL;
714+ }
715+ }
716+
717+ if (ipp_txt)
718+ avahi_string_list_free (ipp_txt);
719+
720+ if (printer_txt)
721+ avahi_string_list_free (printer_txt);
722+#endif /* HAVE_AVAHI */
723 }
724
725
726@@ -2896,6 +3293,10 @@ dnssdStop(void)
727 {
728 cupsd_printer_t *p; /* Current printer */
729
730+#ifdef HAVE_DNSSD
731+ if (!DNSSDRef)
732+ return;
733+#endif /* HAVE_DNSSD */
734
735 /*
736 * De-register the individual printers
737@@ -2906,6 +3307,7 @@ dnssdStop(void)
738 p = (cupsd_printer_t *)cupsArrayNext(Printers))
739 dnssdDeregisterPrinter(p);
740
741+#ifdef HAVE_DNSSD
742 /*
743 * Shutdown the rest of the service refs...
744 */
745@@ -2926,14 +3328,17 @@ dnssdStop(void)
746
747 DNSServiceRefDeallocate(DNSSDRef);
748 DNSSDRef = NULL;
749+#endif /* HAVE_DNSSD */
750
751 cupsArrayDelete(DNSSDPrinters);
752 DNSSDPrinters = NULL;
753
754 DNSSDPort = 0;
755 }
756+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
757
758
759+#ifdef HAVE_DNSSD
760 /*
761 * 'dnssdUpdate()' - Handle DNS-SD queries.
762 */
763@@ -2955,6 +3360,147 @@ dnssdUpdate(void)
764 #endif /* HAVE_DNSSD */
765
766
767+#ifdef HAVE_AVAHI
768+/*
769+ * 'avahiPackTxtRecord()' - Pack an array of key/value pairs into an
770+ * AvahiStringList.
771+ */
772+
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 */
776+{
777+ AvahiStringList *strlst = NULL;
778+ char **elements;
779+ size_t len;
780+ int i = 0;
781+
782+ elements = malloc ((1 + count) * sizeof (char *));
783+ if (!elements)
784+ goto cleanup;
785+
786+ for (i = 0; i < count; i++)
787+ {
788+ len = (1 + strlen (keyvalue[i][0]) +
789+ (keyvalue[i][1] ? 1 + strlen (keyvalue[i][1]) : 1));
790+ elements[i] = malloc (len * sizeof (char));
791+ if (!elements[i])
792+ goto cleanup;
793+
794+ snprintf (elements[i], len, "%s=%s", keyvalue[i][0], keyvalue[i][1]);
795+ }
796+
797+ strlst = avahi_string_list_new_from_array ((const char **) elements, count);
798+
799+cleanup:
800+ while (--i >= 0)
801+ free (elements[i]);
802+
803+ free (elements);
804+ return (strlst);
805+}
806+
807+
808+/*
809+ * 'avahi_entry_group_cb()' - Avahi entry group callback function.
810+ */
811+static void
812+avahi_entry_group_cb (AvahiEntryGroup *group,
813+ AvahiEntryGroupState state,
814+ void *userdata)
815+{
816+ char *name;
817+
818+ if (userdata)
819+ name = ((cupsd_printer_t *) userdata)->reg_name;
820+ else
821+ name = "CUPS web interface";
822+
823+ switch (state)
824+ {
825+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
826+ case AVAHI_ENTRY_GROUP_REGISTERING:
827+ break;
828+
829+ case AVAHI_ENTRY_GROUP_ESTABLISHED:
830+ cupsdLogMessage (CUPSD_LOG_DEBUG,
831+ "Avahi entry group established for %s", name);
832+ break;
833+
834+ default:
835+ cupsdLogMessage (CUPSD_LOG_DEBUG,
836+ "Avahi entry group %s has state %d",
837+ name, state);
838+ break;
839+ }
840+}
841+
842+
843+/*
844+ * 'avahi_client_cb()' - Avahi client callback function.
845+ */
846+static void
847+avahi_client_cb (AvahiClient *client,
848+ AvahiClientState state,
849+ void *userdata)
850+{
851+ cupsd_printer_t *printer;
852+ switch (state)
853+ {
854+ case AVAHI_CLIENT_S_RUNNING:
855+ /*
856+ * Avahi client started successfully.
857+ */
858+ AvahiCupsClient = client;
859+ AvahiCupsClientConnecting = 0;
860+ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started");
861+
862+ cupsdUpdateDNSSDName ();
863+
864+ for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
865+ printer;
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);
871+
872+ break;
873+
874+ case AVAHI_CLIENT_CONNECTING:
875+ /*
876+ * No Avahi daemon, client is waiting.
877+ */
878+ AvahiCupsClientConnecting = 1;
879+ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting");
880+ break;
881+
882+ case AVAHI_CLIENT_FAILURE:
883+ /*
884+ * Avahi client failed, close it to allow a clean restart.
885+ */
886+ cupsdLogMessage (CUPSD_LOG_ERROR,
887+ "Avahi client failed, "
888+ "closing client to allow a clean restart");
889+
890+ for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
891+ printer;
892+ printer = (cupsd_printer_t *)cupsArrayNext(Printers))
893+ dnssdDeregisterPrinter (printer);
894+
895+ avahi_client_free(client);
896+ AvahiCupsClientConnecting = 0;
897+ AvahiCupsClient = NULL;
898+
899+ break;
900+
901+ default:
902+ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client state: %d", state);
903+ }
904+}
905+#endif /* HAVE_AVAHI */
906+
907+
908 /*
909 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
910 */
911diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
912index 99079bd..d53a179 100644
913--- a/scheduler/dirsvc.h
914+++ b/scheduler/dirsvc.h
915@@ -31,6 +31,10 @@
1b240119
JR
916 * file is missing or damaged, see the license at "http://www.cups.org/".
917 */
d07e62b1
ER
918
919+#ifdef HAVE_AVAHI
920+# include <avahi-client/publish.h>
921+#endif /* HAVE_AVAHI */
922+
923 /*
924 * Browse protocols...
925 */
926@@ -131,19 +135,22 @@ VAR int PollPipe VALUE(0);
1b240119
JR
927 BrowseLocalProtocols
928 VALUE(BROWSE_ALL);
929 /* Protocols to support for local printers */
d07e62b1
ER
930-#ifdef HAVE_DNSSD
931+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
932 VAR char *DNSSDComputerName VALUE(NULL),
933 /* Computer/server name */
934 *DNSSDHostName VALUE(NULL),
935 /* Hostname */
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) */
945+
946+#ifdef HAVE_DNSSD
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 */
1b240119 951 WebIFRef VALUE(NULL);
d07e62b1
ER
952@@ -152,6 +159,17 @@ VAR DNSServiceRef DNSSDRef VALUE(NULL),
953 /* Remote printer browse reference */
954 #endif /* HAVE_DNSSD */
955
956+#ifdef HAVE_AVAHI
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 */
966+
1b240119
JR
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);
971
972 extern void cupsdDeregisterPrinter(cupsd_printer_t *p, int removeit);
973 extern void cupsdRegisterPrinter(cupsd_printer_t *p);
d07e62b1
ER
974+extern void cupsdStartAvahiClient(void);
975 extern void cupsdStartBrowsing(void);
d07e62b1 976 extern void cupsdStopBrowsing(void);
d07e62b1
ER
977-#ifdef HAVE_DNSSD
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) */
1b240119
JR
982
983
984 /*
d07e62b1
ER
985diff --git a/scheduler/ipp.c b/scheduler/ipp.c
986index 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));
992
993-#ifdef HAVE_DNSSD
994+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
995 if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
996 {
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);
1001 }
1002-#endif /* HAVE_DNSSD */
1003+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1004
1005 if (!ra || cupsArrayFind(ra, "printer-error-policy"))
1006 ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
1007diff --git a/scheduler/main.c b/scheduler/main.c
1008index 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 */
1015+#ifdef HAVE_AVAHI
1016+ avahi_client_time, /* Time for next Avahi client
1017+ check */
1018+#endif /* HAVE_AVAHI */
d07e62b1
ER
1019 senddoc_time, /* Send-Document time */
1020 expire_time, /* Subscription expire time */
1b240119 1021 report_time, /* Malloc/client/job report time */
d07e62b1
ER
1022@@ -662,6 +666,9 @@ main(int argc, /* I - Number of command-line args */
1023 */
1024
1025 current_time = time(NULL);
1026+#ifdef HAVE_AVAHI
1027+ avahi_client_time = current_time;
1028+#endif /* HAVE_AVAHI */
d07e62b1
ER
1029 event_time = current_time;
1030 expire_time = current_time;
1b240119 1031 fds = 1;
d07e62b1
ER
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);
1036+
1037+ /*
1038+ * Try to restart the Avahi client every 10 seconds if needed...
1039+ */
1040+
1041+ if ((current_time - avahi_client_time) >= 10)
1042+ {
1043+ avahi_client_time = current_time;
1044+ cupsdStartAvahiClient();
1045+ }
1046 #endif /* HAVE_AVAHI */
1047
1048 #ifndef __APPLE__
1049diff --git a/scheduler/printers.c b/scheduler/printers.c
1050index 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);
1056
1057-#ifdef HAVE_DNSSD
1058+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1059 cupsdClearString(&p->pdl);
1060-#endif /* HAVE_DNSSD */
1061+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1062
1063 cupsArrayDelete(p->filetypes);
1064
1065@@ -3765,7 +3765,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
1066 attr->values[i].string.text = _cupsStrAlloc(mimetype);
1067 }
1068
1069-#ifdef HAVE_DNSSD
1070+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1071 {
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 */
1075
1076 cupsdSetString(&p->pdl, pdl);
1077 }
1078-#endif /* HAVE_DNSSD */
1079+#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1080 }
1081
1082
1083diff --git a/scheduler/printers.h b/scheduler/printers.h
1084index 1751578..fb04651 100644
1085--- a/scheduler/printers.h
1086+++ b/scheduler/printers.h
1087@@ -16,6 +16,9 @@
1088 #ifdef HAVE_DNSSD
1089 # include <dns_sd.h>
1090 #endif /* HAVE_DNSSD */
1091+#ifdef HAVE_AVAHI
1092+# include "avahi.h"
1093+#endif /* HAVE_AVAHI */
1094 #include <cups/pwg-private.h>
1095
1096
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 */
1100
1101-#ifdef HAVE_DNSSD
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) */
1108+#ifdef HAVE_DNSSD
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 */
1116+#ifdef HAVE_AVAHI
1117+ AvahiStringList *ipp_txt, /* IPP TXT record */
1118+ *printer_txt; /* LPD TXT record */
1119+ AvahiEntryGroup *avahi_group; /* Avahi entry group */
1120+#endif /* HAVE_AVAHI */
1121 };
1122
1123
This page took 1.090374 seconds and 4 git commands to generate.