]> git.pld-linux.org Git - packages/cups.git/blame - cups-avahi-2-backend.patch
- rel 1
[packages/cups.git] / cups-avahi-2-backend.patch
CommitLineData
d07e62b1
ER
1diff -up cups-1.5.0/backend/dnssd.c.avahi-2-backend cups-1.5.0/backend/dnssd.c
2--- cups-1.5.0/backend/dnssd.c.avahi-2-backend 2011-08-05 15:04:46.182591844 +0100
3+++ cups-1.5.0/backend/dnssd.c 2011-08-05 15:05:13.868710181 +0100
4@@ -15,14 +15,21 @@
5 *
6 * Contents:
7 *
8+ * next_txt_record() - Get next TXT record from a cups_txt_records_t.
9+ * parse_txt_record_pair() - Read key/value pair in cups_txt_records_t.
10 * main() - Browse for printers.
11 * browse_callback() - Browse devices.
12 * browse_local_callback() - Browse local devices.
13 * compare_devices() - Compare two devices.
14 * exec_backend() - Execute the backend that corresponds to the
15 * resolved service name.
16+ * device_type() - Get DNS-SD type enumeration from string.
17 * get_device() - Create or update a device.
18 * query_callback() - Process query data.
19+ * avahi_client_callback() - Avahi client callback function.
20+ * avahi_query_callback() - Avahi query callback function.
21+ * avahi_browse_callback() - Avahi browse callback function.
22+ * find_device() - Find a device from its name and domain.
23 * sigterm_handler() - Handle termination signals...
24 * unquote() - Unquote a name string.
25 */
26@@ -33,7 +40,18 @@
27
28 #include "backend-private.h"
29 #include <cups/array.h>
30-#include <dns_sd.h>
31+#ifdef HAVE_DNSSD
32+# include <dns_sd.h>
33+#endif /* HAVE_DNSSD */
34+#ifdef HAVE_AVAHI
35+# include <avahi-client/client.h>
36+# include <avahi-client/lookup.h>
37+# include <avahi-common/simple-watch.h>
38+# include <avahi-common/domain.h>
39+# include <avahi-common/error.h>
40+# include <avahi-common/malloc.h>
41+#define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
42+#endif /* HAVE_AVAHI */
43
44
45 /*
46@@ -53,7 +71,12 @@ typedef enum
47
48 typedef struct
49 {
50+#ifdef HAVE_DNSSD
51 DNSServiceRef ref; /* Service reference for resolve */
52+#endif /* HAVE_DNSSD */
53+#ifdef HAVE_AVAHI
54+ int resolved; /* Did we resolve the device? */
55+#endif /* HAVE_AVAHI */
56 char *name, /* Service name */
57 *domain, /* Domain name */
58 *fullName, /* Full name */
59@@ -65,6 +88,20 @@ typedef struct
60 sent; /* Did we list the device? */
61 } cups_device_t;
62
63+typedef struct
64+{
65+ char key[256];
66+ char value[256];
67+
68+#ifdef HAVE_DNSSD
69+ const uint8_t *data;
70+ const uint8_t *datanext;
71+ const uint8_t *dataend;
72+#else /* HAVE_AVAHI */
73+ AvahiStringList *txt;
74+#endif /* HAVE_DNSSD */
75+} cups_txt_records_t;
76+
77
78 /*
79 * Local globals...
80@@ -78,6 +115,7 @@ static int job_canceled = 0;
81 * Local functions...
82 */
83
84+#ifdef HAVE_DNSSD
85 static void browse_callback(DNSServiceRef sdRef,
86 DNSServiceFlags flags,
87 uint32_t interfaceIndex,
88@@ -93,12 +131,6 @@ static void browse_local_callback(DNSSe
89 const char *regtype,
90 const char *replyDomain,
91 void *context);
92-static int compare_devices(cups_device_t *a, cups_device_t *b);
93-static void exec_backend(char **argv);
94-static cups_device_t *get_device(cups_array_t *devices,
95- const char *serviceName,
96- const char *regtype,
97- const char *replyDomain);
98 static void query_callback(DNSServiceRef sdRef,
99 DNSServiceFlags flags,
100 uint32_t interfaceIndex,
101@@ -107,9 +139,118 @@ static void query_callback(DNSServiceRe
102 uint16_t rrclass, uint16_t rdlen,
103 const void *rdata, uint32_t ttl,
104 void *context);
105+#endif /* HAVE_DNSSD */
106+#ifdef HAVE_AVAHI
107+static void avahi_client_callback (AvahiClient *client,
108+ AvahiClientState state,
109+ void *context);
110+static void avahi_browse_callback (AvahiServiceBrowser *browser,
111+ AvahiIfIndex interface,
112+ AvahiProtocol protocol,
113+ AvahiBrowserEvent event,
114+ const char *serviceName,
115+ const char *regtype,
116+ const char *replyDomain,
117+ AvahiLookupResultFlags flags,
118+ void *context);
119+#endif /* HAVE_AVAHI */
120+
121+static cups_device_t * find_device (cups_array_t *devices,
122+ cups_txt_records_t *txt,
123+ cups_device_t *dkey);
124+static int compare_devices(cups_device_t *a, cups_device_t *b);
125+static void exec_backend(char **argv);
126+static cups_device_t *get_device(cups_array_t *devices,
127+ const char *serviceName,
128+ const char *regtype,
129+ const char *replyDomain);
130 static void sigterm_handler(int sig);
131 static void unquote(char *dst, const char *src, size_t dstsize);
132
133+#ifdef HAVE_AVAHI
134+static AvahiSimplePoll *simple_poll = NULL;
135+static int avahi_got_callback;
136+#endif /* HAVE_AVAHI */
137+
138+
139+/*
140+ * 'next_txt_record()' - Get next TXT record from a cups_txt_records_t.
141+ */
142+
143+static cups_txt_records_t *
144+next_txt_record (cups_txt_records_t *txt)
145+{
146+#ifdef HAVE_DNSSD
147+ txt->data = txt->datanext;
148+#else /* HAVE_AVAHI */
149+ txt->txt = avahi_string_list_get_next (txt->txt);
150+ if (txt->txt == NULL)
151+ return NULL;
152+#endif /* HAVE_DNSSD */
153+
154+ return txt;
155+}
156+
157+
158+/*
159+ * 'parse_txt_record_pair()' - Read key/value pair in cups_txt_records_t.
160+ */
161+
162+static int
163+parse_txt_record_pair (cups_txt_records_t *txt)
164+{
165+#ifdef HAVE_DNSSD
166+ uint8_t datalen;
167+ uint8_t *data = txt->data;
168+ char *ptr;
169+
170+ /*
171+ * Read a key/value pair starting with an 8-bit length. Since the
172+ * length is 8 bits and the size of the key/value buffers is 256, we
173+ * don't need to check for overflow...
174+ */
175+
176+ datalen = *data++;
b737a6ac 177+ if (!datalen || (data + datalen) > txt->dataend)
d07e62b1
ER
178+ return NULL;
179+ txt->datanext = data + datalen;
180+
181+ for (ptr = txt->key; data < txt->datanext && *data != '='; data ++)
182+ *ptr++ = *data;
183+ *ptr = '\0';
184+
185+ if (data < txt->datanext && *data == '=')
186+ {
187+ data++;
188+
189+ if (data < datanext)
190+ memcpy (txt->value, data, txt->datanext - data);
191+ value[txt->datanext - data] = '\0';
192+ }
193+ else
194+ return 1;
195+#else /* HAVE_AVAHI */
196+ char *key, *value;
197+ size_t len;
198+ avahi_string_list_get_pair (txt->txt, &key, &value, &len);
199+ if (len > sizeof (txt->value) - 1)
200+ len = sizeof (txt->value) - 1;
201+
202+ memcpy (txt->value, value, len);
203+ txt->value[len] = '\0';
204+ len = strlen (key);
205+ if (len > sizeof (txt->key) - 1)
206+ len = sizeof (txt->key) - 1;
207+
208+ memcpy (txt->key, key, len);
209+ txt->key[len] = '\0';
210+ avahi_free (key);
211+ avahi_free (value);
212+#endif /* HAVE_AVAHI */
213+
214+ return 0;
215+}
216+
217
218 /*
219 * 'main()' - Browse for printers.
220@@ -120,6 +261,13 @@ main(int argc, /* I - Number of comm
221 char *argv[]) /* I - Command-line arguments */
222 {
223 const char *name; /* Backend name */
224+ cups_array_t *devices; /* Device array */
225+ cups_device_t *device; /* Current device */
226+ char uriName[1024]; /* Unquoted fullName for URI */
227+#ifdef HAVE_DNSSD
228+ int fd; /* Main file descriptor */
229+ fd_set input; /* Input set for select() */
230+ struct timeval timeout; /* Timeout for select() */
231 DNSServiceRef main_ref, /* Main service reference */
232 fax_ipp_ref, /* IPP fax service reference */
233 ipp_ref, /* IPP service reference */
234@@ -133,12 +281,11 @@ main(int argc, /* I - Number of comm
235 pdl_datastream_ref, /* AppSocket service reference */
236 printer_ref, /* LPD service reference */
237 riousbprint_ref; /* Remote IO service reference */
238- int fd; /* Main file descriptor */
239- fd_set input; /* Input set for select() */
240- struct timeval timeout; /* Timeout for select() */
241- cups_array_t *devices; /* Device array */
242- cups_device_t *device; /* Current device */
243- char uriName[1024]; /* Unquoted fullName for URI */
244+#endif /* HAVE_DNSSD */
245+#ifdef HAVE_AVAHI
246+ AvahiClient *client;
247+ int error;
248+#endif /* HAVE_AVAHI */
249 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
250 struct sigaction action; /* Actions for POSIX signals */
251 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
252@@ -198,6 +345,49 @@ main(int argc, /* I - Number of comm
253 * Browse for different kinds of printers...
254 */
255
256+#ifdef HAVE_AVAHI
257+ if ((simple_poll = avahi_simple_poll_new ()) == NULL)
258+ {
259+ perror ("ERROR: Unable to create avahi simple poll object");
260+ return (1);
261+ }
262+
263+ client = avahi_client_new (avahi_simple_poll_get (simple_poll),
264+ 0, avahi_client_callback, NULL, &error);
265+ if (!client)
266+ {
267+ perror ("DEBUG: Unable to create avahi client");
268+ return (0);
269+ }
270+
271+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
272+ AVAHI_PROTO_UNSPEC,
273+ "_fax-ipp._tcp", NULL, 0,
274+ avahi_browse_callback, devices);
275+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
276+ AVAHI_PROTO_UNSPEC,
277+ "_ipp._tcp", NULL, 0,
278+ avahi_browse_callback, devices);
279+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
280+ AVAHI_PROTO_UNSPEC,
281+ "_ipp-tls._tcp", NULL, 0,
282+ avahi_browse_callback, devices);
283+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
284+ AVAHI_PROTO_UNSPEC,
285+ "_pdl-datastream._tcp",
286+ NULL, 0,
287+ avahi_browse_callback,
288+ devices);
289+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
290+ AVAHI_PROTO_UNSPEC,
291+ "_printer._tcp", NULL, 0,
292+ avahi_browse_callback, devices);
293+ avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
294+ AVAHI_PROTO_UNSPEC,
295+ "_riousbprint._tcp", NULL, 0,
296+ avahi_browse_callback, devices);
297+#endif /* HAVE_AVAHI */
298+#ifdef HAVE_DNSSD
299 if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
300 {
301 perror("ERROR: Unable to create service connection");
302@@ -258,6 +448,7 @@ main(int argc, /* I - Number of comm
303 riousbprint_ref = main_ref;
304 DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
305 "_riousbprint._tcp", NULL, browse_callback, devices);
306+#endif /* HAVE_DNSSD */
307
308 /*
309 * Loop until we are killed...
310@@ -265,6 +456,9 @@ main(int argc, /* I - Number of comm
311
312 while (!job_canceled)
313 {
314+ int announce = 0;
315+
316+#ifdef HAVE_DNSSD
317 FD_ZERO(&input);
318 FD_SET(fd, &input);
319
320@@ -284,11 +478,35 @@ main(int argc, /* I - Number of comm
321 }
322 else
323 {
324+ announce = 1;
325+ }
326+#else /* HAVE_AVAHI */
327+ int r;
328+ avahi_got_callback = 0;
329+ r = avahi_simple_poll_iterate (simple_poll, 1);
330+ if (r != 0 && r != EINTR)
331+ {
332+ /*
333+ * We've been told to exit the loop. Perhaps the connection to
334+ * avahi failed.
335+ */
336+
337+ break;
338+ }
339+
340+ if (avahi_got_callback)
341+ announce = 1;
342+#endif /* HAVE_DNSSD */
343+
344+ if (announce)
345+ {
346 /*
347 * Announce any devices we've found...
348 */
349
350+#ifdef HAVE_DNSSD
351 DNSServiceErrorType status; /* DNS query status */
352+#endif /* HAVE_DNSSD */
353 cups_device_t *best; /* Best matching device */
354 char device_uri[1024]; /* Device URI */
355 int count; /* Number of queries */
356@@ -302,6 +520,7 @@ main(int argc, /* I - Number of comm
357 if (device->sent)
358 sent ++;
359
360+#ifdef HAVE_DNSSD
361 if (device->ref)
362 count ++;
363
364@@ -333,14 +552,23 @@ main(int argc, /* I - Number of comm
365 count ++;
366 }
367 }
368- else if (!device->sent)
369+ else
370+#endif /* HAVE_DNSSD */
371+#ifdef HAVE_AVAHI
372+ if (!device->resolved)
373+ continue;
374+ else
375+#endif /* HAVE_AVAHI */
376+ if (!device->sent)
377 {
378+#ifdef HAVE_DNSSD
379 /*
380 * Got the TXT records, now report the device...
381 */
382
383 DNSServiceRefDeallocate(device->ref);
384 device->ref = 0;
385+#endif /* HAVE_DNSSD */
386
387 if (!best)
388 best = device;
389@@ -401,6 +629,7 @@ main(int argc, /* I - Number of comm
390 }
391
392
393+#ifdef HAVE_DNSSD
394 /*
395 * 'browse_callback()' - Browse devices.
396 */
397@@ -489,6 +718,7 @@ browse_local_callback(
398 device->fullName);
399 device->sent = 1;
400 }
401+#endif /* HAVE_DNSSD */
402
403
404 /*
405@@ -569,6 +799,41 @@ exec_backend(char **argv) /* I - Comman
406
407
408 /*
409+ * 'device_type()' - Get DNS-SD type enumeration from string.
410+ */
411+
412+static int
413+device_type (const char *regtype)
414+{
415+#ifdef HAVE_AVAHI
416+ if (!strcmp(regtype, "_ipp._tcp"))
417+ return (CUPS_DEVICE_IPP);
418+ else if (!strcmp(regtype, "_ipps._tcp") ||
419+ !strcmp(regtype, "_ipp-tls._tcp"))
420+ return (CUPS_DEVICE_IPPS);
421+ else if (!strcmp(regtype, "_fax-ipp._tcp"))
422+ return (CUPS_DEVICE_FAX_IPP);
423+ else if (!strcmp(regtype, "_printer._tcp"))
424+ return (CUPS_DEVICE_PDL_DATASTREAM);
425+#else
426+ if (!strcmp(regtype, "_ipp._tcp."))
427+ return (CUPS_DEVICE_IPP);
428+ else if (!strcmp(regtype, "_ipps._tcp.") ||
429+ !strcmp(regtype, "_ipp-tls._tcp."))
430+ return (CUPS_DEVICE_IPPS);
431+ else if (!strcmp(regtype, "_fax-ipp._tcp."))
432+ return (CUPS_DEVICE_FAX_IPP);
433+ else if (!strcmp(regtype, "_printer._tcp."))
434+ return (CUPS_DEVICE_PRINTER);
435+ else if (!strcmp(regtype, "_pdl-datastream._tcp."))
436+ return (CUPS_DEVICE_PDL_DATASTREAM);
437+#endif /* HAVE_AVAHI */
438+
439+ return (CUPS_DEVICE_RIOUSBPRINT);
440+}
441+
442+
443+/*
444 * 'get_device()' - Create or update a device.
445 */
446
447@@ -589,20 +854,7 @@ get_device(cups_array_t *devices, /* I -
448 */
449
450 key.name = (char *)serviceName;
451-
452- if (!strcmp(regtype, "_ipp._tcp."))
453- key.type = CUPS_DEVICE_IPP;
454- else if (!strcmp(regtype, "_ipps._tcp.") ||
455- !strcmp(regtype, "_ipp-tls._tcp."))
456- key.type = CUPS_DEVICE_IPPS;
457- else if (!strcmp(regtype, "_fax-ipp._tcp."))
458- key.type = CUPS_DEVICE_FAX_IPP;
459- else if (!strcmp(regtype, "_printer._tcp."))
460- key.type = CUPS_DEVICE_PRINTER;
461- else if (!strcmp(regtype, "_pdl-datastream._tcp."))
462- key.type = CUPS_DEVICE_PDL_DATASTREAM;
463- else
464- key.type = CUPS_DEVICE_RIOUSBPRINT;
465+ key.type = device_type (regtype);
466
467 for (device = cupsArrayFind(devices, &key);
468 device;
469@@ -622,8 +874,14 @@ get_device(cups_array_t *devices, /* I -
470 free(device->domain);
471 device->domain = strdup(replyDomain);
472
473+#ifdef HAVE_DNSSD
474 DNSServiceConstructFullName(fullName, device->name, regtype,
475 replyDomain);
476+#else /* HAVE_AVAHI */
477+ avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
478+ serviceName, regtype, replyDomain);
479+#endif /* HAVE_DNSSD */
480+
481 free(device->fullName);
482 device->fullName = strdup(fullName);
483 }
484@@ -643,6 +901,9 @@ get_device(cups_array_t *devices, /* I -
485 device->domain = strdup(replyDomain);
486 device->type = key.type;
487 device->priority = 50;
488+#ifdef HAVE_AVAHI
489+ device->resolved = 0;
490+#endif /* HAVE_AVAHI */
491
492 cupsArrayAdd(devices, device);
493
494@@ -650,13 +911,20 @@ get_device(cups_array_t *devices, /* I -
495 * Set the "full name" of this service, which is used for queries...
496 */
497
498+#ifdef HAVE_DNSSD
499 DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
500+#else /* HAVE_AVAHI */
501+ avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
502+ serviceName, regtype, replyDomain);
503+#endif /* HAVE_DNSSD */
504+
505 device->fullName = strdup(fullName);
506
507 return (device);
508 }
509
510
511+#ifdef HAVE_DNSSD
512 /*
513 * 'query_callback()' - Process query data.
514 */
515@@ -680,7 +948,7 @@ query_callback(
516 *ptr; /* Pointer into string */
517 cups_device_t dkey, /* Search key */
518 *device; /* Device */
519-
520+ cups_txt_records_t txt;
521
522 fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
523 "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
524@@ -714,94 +982,233 @@ query_callback(
525 if ((ptr = strstr(name, "._")) != NULL)
526 *ptr = '\0';
527
528- if (strstr(fullName, "_ipp._tcp."))
529- dkey.type = CUPS_DEVICE_IPP;
530- else if (strstr(fullName, "_ipps._tcp.") ||
531- strstr(fullName, "_ipp-tls._tcp."))
532- dkey.type = CUPS_DEVICE_IPPS;
533- else if (strstr(fullName, "_fax-ipp._tcp."))
534- dkey.type = CUPS_DEVICE_FAX_IPP;
535- else if (strstr(fullName, "_printer._tcp."))
536- dkey.type = CUPS_DEVICE_PRINTER;
537- else if (strstr(fullName, "_pdl-datastream._tcp."))
538- dkey.type = CUPS_DEVICE_PDL_DATASTREAM;
539+ dkey.type = device_type (fullName);
540+
541+ txt.data = rdata;
542+ txt.dataend = rdata + rdlen;
543+ device = find_device ((cups_array_t *) context, &txt, &dkey);
544+ if (!device)
545+ fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
546+}
547+#endif /* HAVE_DNSSD */
548+
549+
550+#ifdef HAVE_AVAHI
551+/*
552+ * 'avahi_client_callback()' - Avahi client callback function.
553+ */
554+
555+static void
556+avahi_client_callback(AvahiClient *client,
557+ AvahiClientState state,
558+ void *context)
559+{
560+ /*
561+ * If the connection drops, quit.
562+ */
563+
564+ if (state == AVAHI_CLIENT_FAILURE)
565+ {
566+ fprintf (stderr, "ERROR: Avahi connection failed\n");
567+ avahi_simple_poll_quit (simple_poll);
568+ }
569+}
570+
571+
572+/*
573+ * 'avahi_query_callback()' - Avahi query callback function.
574+ */
575+
576+static void
577+avahi_query_callback(AvahiServiceResolver *resolver,
578+ AvahiIfIndex interface,
579+ AvahiProtocol protocol,
580+ AvahiResolverEvent event,
581+ const char *name,
582+ const char *type,
583+ const char *domain,
584+ const char *host_name,
585+ const AvahiAddress *address,
586+ uint16_t port,
587+ AvahiStringList *txt,
588+ AvahiLookupResultFlags flags,
589+ void *context)
590+{
591+ AvahiClient *client;
592+ cups_device_t key,
593+ *device;
594+ char uqname[1024],
595+ *ptr;
596+ cups_txt_records_t txtr;
597+
598+ client = avahi_service_resolver_get_client (resolver);
599+ if (event != AVAHI_RESOLVER_FOUND)
600+ {
601+ if (event == AVAHI_RESOLVER_FAILURE)
602+ {
603+ fprintf (stderr, "ERROR: %s\n",
604+ avahi_strerror (avahi_client_errno (client)));
605+ }
606+
607+ avahi_service_resolver_free (resolver);
608+ return;
609+ }
610+
611+ /*
612+ * Set search key for device.
613+ */
614+
615+ key.name = uqname;
616+ unquote (uqname, name, sizeof (uqname));
617+ if ((ptr = strstr(name, "._")) != NULL)
618+ *ptr = '\0';
619+
620+ key.domain = (char *) domain;
621+ key.type = device_type (type);
622+
623+ /*
624+ * Find the device and the the TXT information.
625+ */
626+
627+ txtr.txt = txt;
628+ device = find_device ((cups_array_t *) context, &txtr, &key);
629+ if (device)
630+ {
631+ /*
632+ * Let the main loop know to announce the device.
633+ */
634+
635+ device->resolved = 1;
636+ avahi_got_callback = 1;
637+ }
638 else
639- dkey.type = CUPS_DEVICE_RIOUSBPRINT;
640+ fprintf (stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", name);
641+
642+ avahi_service_resolver_free (resolver);
643+}
644+
645+
646+/*
647+ * 'avahi_browse_callback()' - Avahi browse callback function.
648+ */
649+
650+static void
651+avahi_browse_callback(AvahiServiceBrowser *browser,
652+ AvahiIfIndex interface,
653+ AvahiProtocol protocol,
654+ AvahiBrowserEvent event,
655+ const char *name,
656+ const char *type,
657+ const char *domain,
658+ AvahiLookupResultFlags flags,
659+ void *context)
660+{
661+ AvahiClient *client = avahi_service_browser_get_client (browser);
662+
663+ switch (event)
664+ {
665+ case AVAHI_BROWSER_FAILURE:
666+ fprintf (stderr, "ERROR: %s\n",
667+ avahi_strerror (avahi_client_errno (client)));
668+ avahi_simple_poll_quit (simple_poll);
669+ return;
670+
671+ case AVAHI_BROWSER_NEW:
672+ /*
673+ * This object is new on the network.
674+ */
675+
676+ if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
677+ {
678+ /*
679+ * This comes from the local machine so ignore it.
680+ */
681+
682+ fprintf (stderr, "DEBUG: ignoring local service %s\n", name);
683+ }
684+ else
685+ {
686+ /*
687+ * Create a device entry for it if it doesn't yet exist.
688+ */
689+
690+ get_device ((cups_array_t *)context, name, type, domain);
691+
692+ /*
693+ * Now look for a TXT entry.
694+ */
695+
696+ if (avahi_service_resolver_new (client, interface, protocol,
697+ name, type, domain,
698+ AVAHI_PROTO_UNSPEC, 0,
699+ avahi_query_callback, context) == NULL)
700+ {
701+ fprintf (stderr, "ERROR: failed to resolve service %s: %s\n",
702+ name, avahi_strerror (avahi_client_errno (client)));
703+ }
704+ }
705+
706+ break;
707+
708+ case AVAHI_BROWSER_REMOVE:
709+ case AVAHI_BROWSER_ALL_FOR_NOW:
710+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
711+ break;
712+ }
713+}
714+#endif /* HAVE_AVAHI */
715+
716
717- for (device = cupsArrayFind(devices, &dkey);
718+/*
719+ * 'find_device()' - Find a device from its name and domain.
720+ */
721+
722+static cups_device_t *
723+find_device (cups_array_t *devices,
724+ cups_txt_records_t *txt,
725+ cups_device_t *dkey)
726+{
727+ cups_device_t *device;
728+ char *ptr;
729+
730+ for (device = cupsArrayFind(devices, dkey);
731 device;
732 device = cupsArrayNext(devices))
733 {
734- if (_cups_strcasecmp(device->name, dkey.name) ||
735- _cups_strcasecmp(device->domain, dkey.domain))
736+ if (_cups_strcasecmp(device->name, dkey->name) ||
737+ _cups_strcasecmp(device->domain, dkey->domain))
738 {
739 device = NULL;
740 break;
741 }
742- else if (device->type == dkey.type)
743+ else if (device->type == dkey->type)
744 {
745 /*
746 * Found it, pull out the priority and make and model from the TXT
747 * record and save it...
748 */
749
750- const uint8_t *data, /* Pointer into data */
751- *datanext, /* Next key/value pair */
752- *dataend; /* End of entire TXT record */
753- uint8_t datalen; /* Length of current key/value pair */
754- char key[256], /* Key string */
755- value[256], /* Value string */
756- make_and_model[512],
757+ char make_and_model[512],
758 /* Manufacturer and model */
759 model[256], /* Model */
760- device_id[2048];/* 1284 device ID */
761-
762+ device_id[2048]; /* 1284 device ID */
763
764 device_id[0] = '\0';
765 make_and_model[0] = '\0';
766
767 strcpy(model, "Unknown");
768
769- for (data = rdata, dataend = data + rdlen;
770- data < dataend;
771- data = datanext)
772+ for (;;)
773 {
774- /*
775- * Read a key/value pair starting with an 8-bit length. Since the
776- * length is 8 bits and the size of the key/value buffers is 256, we
777- * don't need to check for overflow...
778- */
779-
780- datalen = *data++;
781-
1b240119 782- if (!datalen || (data + datalen) > dataend)
d07e62b1
ER
783- break;
784-
785- datanext = data + datalen;
786-
787- for (ptr = key; data < datanext && *data != '='; data ++)
788- *ptr++ = *data;
789- *ptr = '\0';
790+ char *key;
791+ char *value;
792
793- if (data < datanext && *data == '=')
794- {
795- data ++;
796-
797- if (data < datanext)
798- memcpy(value, data, datanext - data);
799- value[datanext - data] = '\0';
800+ if (parse_txt_record_pair (txt))
801+ goto next;
802
803- fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
804- key, value);
805- }
806- else
807- {
808- fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
809- key);
810- continue;
811- }
812-
813- if (!_cups_strncasecmp(key, "usb_", 4))
814+ key = txt->key;
815+ value = txt->value;
816+ if (!strncasecmp(key, "usb_", 4))
817 {
818 /*
819 * Add USB device ID information...
820@@ -856,6 +1263,10 @@ query_callback(
821 if (device->type == CUPS_DEVICE_PRINTER)
822 device->sent = 1;
823 }
824+
825+ next:
826+ if (next_txt_record (txt) == NULL)
827+ break;
828 }
829
830 if (device->device_id)
831@@ -912,11 +1323,9 @@ query_callback(
832 }
833 }
834
835- if (!device)
836- fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
837+ return device;
838 }
839
840-
841 /*
842 * 'sigterm_handler()' - Handle termination signals...
843 */
844diff -up cups-1.5.0/cups/http-support.c.avahi-2-backend cups-1.5.0/cups/http-support.c
845--- cups-1.5.0/cups/http-support.c.avahi-2-backend 2011-06-10 23:06:26.000000000 +0100
846+++ cups-1.5.0/cups/http-support.c 2011-08-05 15:05:13.870710117 +0100
847@@ -43,6 +43,10 @@
848 * http_copy_decode() - Copy and decode a URI.
849 * http_copy_encode() - Copy and encode a URI.
850 * http_resolve_cb() - Build a device URI for the given service name.
851+ * avahi_resolve_uri_client_cb()
852+ * - Avahi client callback for resolving URI.
853+ * avahi_resolve_uri_resolver_cb()
854+ * - Avahi resolver callback for resolving URI.
855 */
856
857 /*
858@@ -60,6 +64,11 @@
859 # include <sys/select.h>
860 # endif /* WIN32 */
861 #endif /* HAVE_DNSSD */
862+#ifdef HAVE_AVAHI
863+# include <avahi-client/client.h>
864+# include <avahi-client/lookup.h>
865+# include <avahi-common/simple-watch.h>
866+#endif /* HAVE_AVAHI */
867
868
869 /*
870@@ -127,6 +136,24 @@ static void DNSSD_API http_resolve_cb(DN
871 void *context);
872 #endif /* HAVE_DNSSD */
873
874+#ifdef HAVE_AVAHI
875+static void avahi_resolve_uri_client_cb(AvahiClient *client,
876+ AvahiClientState state,
877+ void *simple_poll);
878+static void avahi_resolve_uri_resolver_cb(AvahiServiceResolver *resolver,
879+ AvahiIfIndex interface,
880+ AvahiProtocol protocol,
881+ AvahiResolverEvent event,
882+ const char *name,
883+ const char *type,
884+ const char *domain,
885+ const char *host_name,
886+ const AvahiAddress *address,
887+ uint16_t port,
888+ AvahiStringList *txt,
889+ AvahiLookupResultFlags flags,
890+ void *context);
891+#endif /* HAVE_AVAHI */
892
893 /*
894 * 'httpAssembleURI()' - Assemble a uniform resource identifier from its
895@@ -1431,6 +1458,9 @@ _httpResolveURI(
896
897 if (strstr(hostname, "._tcp"))
898 {
899+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
900+ char *regtype, /* Pointer to type in hostname */
901+ *domain; /* Pointer to domain in hostname */
902 #ifdef HAVE_DNSSD
903 # ifdef WIN32
904 # pragma comment(lib, "dnssd.lib")
905@@ -1449,6 +1479,17 @@ _httpResolveURI(
906 fd_set input_set; /* Input set for select() */
907 struct timeval stimeout; /* Timeout value for select() */
908 #endif /* HAVE_POLL */
909+#else /* HAVE_AVAHI */
910+ AvahiSimplePoll *simple_poll;
911+ AvahiClient *client;
912+ int error;
913+ struct
914+ {
915+ AvahiSimplePoll *poll;
916+ _http_uribuf_t uribuf;
917+ } user_data;
918+#endif /* HAVE_DNSSD */
919+
920
921 if (options & _HTTP_RESOLVE_STDERR)
922 fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
923@@ -1485,9 +1526,16 @@ _httpResolveURI(
924 if (domain)
925 *domain++ = '\0';
926
927+#ifdef HAVE_DNSSD
928 uribuf.buffer = resolved_uri;
929 uribuf.bufsize = resolved_size;
930 uribuf.options = options;
931+#else
932+ user_data.uribuf.buffer = resolved_uri;
933+ user_data.uribuf.bufsize = resolved_size;
934+ user_data.uribuf.options = options;
935+#endif
936+
937 resolved_uri[0] = '\0';
938
939 DEBUG_printf(("6_httpResolveURI: Resolving hostname=\"%s\", regtype=\"%s\", "
940@@ -1501,6 +1549,7 @@ _httpResolveURI(
941
942 uri = NULL;
943
944+#ifdef HAVE_DNSSD
945 if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
946 {
947 localref = ref;
948@@ -1608,6 +1657,36 @@ _httpResolveURI(
949
950 DNSServiceRefDeallocate(ref);
951 }
952+#else /* HAVE_AVAHI */
953+ if ((simple_poll = avahi_simple_poll_new ()) != NULL)
954+ {
955+ if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll),
956+ 0, avahi_resolve_uri_client_cb,
957+ &simple_poll, &error)) != NULL)
958+ {
959+ user_data.poll = simple_poll;
960+ if (avahi_service_resolver_new (client, AVAHI_IF_UNSPEC,
961+ AVAHI_PROTO_UNSPEC, hostname,
962+ regtype, domain, AVAHI_PROTO_UNSPEC, 0,
963+ avahi_resolve_uri_resolver_cb,
964+ &user_data) != NULL)
965+ {
966+ avahi_simple_poll_loop (simple_poll);
967+
968+ /*
969+ * Collect the result.
970+ */
971+
972+ if (resolved_uri[0])
973+ uri = resolved_uri;
974+ }
975+
976+ avahi_client_free (client);
977+ }
978+
979+ avahi_simple_poll_free (simple_poll);
980+ }
981+#endif /* HAVE_DNSSD */
982
983 if (options & _HTTP_RESOLVE_STDERR)
984 {
985@@ -1619,13 +1698,13 @@ _httpResolveURI(
986 fputs("STATE: -connecting-to-device,offline-report\n", stderr);
987 }
988
989-#else
990+#else /* HAVE_DNSSD || HAVE_AVAHI */
991 /*
992 * No DNS-SD support...
993 */
994
995 uri = NULL;
996-#endif /* HAVE_DNSSD */
997+#endif /* HAVE_DNSSD || HAVE_AVAHI */
998
999 if ((options & _HTTP_RESOLVE_STDERR) && !uri)
1000 _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
1001@@ -1895,6 +1974,116 @@ http_resolve_cb(
1002 #endif /* HAVE_DNSSD */
1003
1004
1005+#ifdef HAVE_AVAHI
1006+/*
1007+ * 'avahi_resolve_uri_client_cb()' - Avahi client callback for resolving URI.
1008+ */
1009+
1010+static void
1011+avahi_resolve_uri_client_cb (AvahiClient *client,
1012+ AvahiClientState state,
1013+ void *simple_poll)
1014+{
1015+ DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, "
1016+ "simple_poll=%p)\n", client, state, simple_poll));
1017+
1018+ /*
1019+ * If the connection drops, quit.
1020+ */
1021+
1022+ if (state == AVAHI_CLIENT_FAILURE)
1023+ avahi_simple_poll_quit (simple_poll);
1024+}
1025+
1026+
1027+/*
1028+ * 'avahi_resolve_uri_resolver_cb()' - Avahi resolver callback for resolving
1029+ * URI.
1030+ */
1031+
1032+static void
1033+avahi_resolve_uri_resolver_cb (AvahiServiceResolver *resolver,
1034+ AvahiIfIndex interface,
1035+ AvahiProtocol protocol,
1036+ AvahiResolverEvent event,
1037+ const char *name,
1038+ const char *type,
1039+ const char *domain,
1040+ const char *host_name,
1041+ const AvahiAddress *address,
1042+ uint16_t port,
1043+ AvahiStringList *txt,
1044+ AvahiLookupResultFlags flags,
1045+ void *context)
1046+{
1047+ const char *scheme; /* URI scheme */
1048+ char rp[256]; /* Remote printer */
1049+ AvahiStringList *pair;
1050+ char *value;
1051+ size_t valueLen = 0;
1052+ char addr[AVAHI_ADDRESS_STR_MAX];
1053+ struct
1054+ {
1055+ AvahiSimplePoll *poll;
1056+ _http_uribuf_t uribuf;
1057+ } *poll_uribuf = context;
1058+
1059+ DEBUG_printf(("avahi_resolve_uri_resolver_callback(resolver=%p, "
1060+ "interface=%d, protocol=%d, event=%d, name=\"%s\", "
1061+ "type=\"%s\", domain=\"%s\", host_name=\"%s\", address=%p, "
1062+ "port=%d, txt=%p, flags=%d, context=%p)\n",
1063+ resolver, interface, protocol, event, name, type, domain,
1064+ host_name, address, port, txt, flags, context));
1065+
1066+ if (event != AVAHI_RESOLVER_FOUND)
1067+ {
1068+ avahi_service_resolver_free (resolver);
1069+ avahi_simple_poll_quit (poll_uribuf->poll);
1070+ return;
1071+ }
1072+
1073+ /*
1074+ * Figure out the scheme from the full name...
1075+ */
1076+
1077+ if (strstr(type, "_ipp."))
1078+ scheme = "ipp";
1079+ else if (strstr(type, "_printer."))
1080+ scheme = "lpd";
1081+ else if (strstr(type, "_pdl-datastream."))
1082+ scheme = "socket";
1083+ else
1084+ scheme = "riousbprint";
1085+
1086+ /*
1087+ * Extract the "remote printer key from the TXT record...
1088+ */
1089+
1090+ if ((pair = avahi_string_list_find (txt, "rp")) != NULL)
1091+ {
1092+ avahi_string_list_get_pair (pair, NULL, &value, &valueLen);
1093+ rp[0] = '/';
1094+ memcpy (rp + 1, value, valueLen);
1095+ rp[valueLen + 1] = '\0';
1096+ }
1097+ else
1098+ rp[0] = '\0';
1099+
1100+ /*
1101+ * Assemble the final device URI...
1102+ */
1103+
1104+ avahi_address_snprint (addr, AVAHI_ADDRESS_STR_MAX, address);
1105+ httpAssembleURI(HTTP_URI_CODING_ALL, poll_uribuf->uribuf.buffer,
1106+ poll_uribuf->uribuf.bufsize, scheme, NULL,
1107+ addr, port, rp);
1108+ DEBUG_printf(("avahi_resolve_uri_resolver_callback: Resolved URI is \"%s\"\n",
1109+ poll_uribuf->uribuf.buffer));
1110+ avahi_simple_poll_quit (poll_uribuf->poll);
1111+}
1112+#endif /* HAVE_AVAHI */
1113+
1114+
1115 /*
1116 * End of "$Id$".
1117 */
This page took 1.173048 seconds and 4 git commands to generate.