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