Magellan Linux

Annotation of /trunk/cups/patches/cups-1.5.2-avahi-2-backend.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1642 - (hide annotations) (download)
Thu Feb 16 08:44:18 2012 UTC (12 years, 2 months ago) by niro
File size: 30788 byte(s)
-added redhat/fedora avahi patches
1 niro 1642 diff -up cups-1.5.2/backend/dnssd.c.avahi-2-backend cups-1.5.2/backend/dnssd.c
2     --- cups-1.5.2/backend/dnssd.c.avahi-2-backend 2012-02-06 11:09:08.318644741 +0100
3     +++ cups-1.5.2/backend/dnssd.c 2012-02-06 11:09:08.326644641 +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++;
177     + if (!datalen || (data + datalen) >= txt->dataend)
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     -
782     - if (!datalen || (data + datalen) > dataend)
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     */
844     diff -up cups-1.5.2/cups/http-support.c.avahi-2-backend cups-1.5.2/cups/http-support.c
845     --- cups-1.5.2/cups/http-support.c.avahi-2-backend 2011-09-26 20:46:46.000000000 +0200
846     +++ cups-1.5.2/cups/http-support.c 2012-02-06 11:09:08.327644629 +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     @@ -1914,6 +1993,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: http-support.c 10017 2011-09-26 18:46:46Z mike $".
1117     */