Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1786 - (hide annotations) (download)
Mon May 21 13:12:01 2012 UTC (11 years, 11 months ago) by niro
File size: 30922 byte(s)
-added patch for 1.5.3
1 niro 1786 diff -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
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     @@ -95,13 +133,6 @@ static void browse_local_callback(DNSSe
89     const char *replyDomain,
90     void *context)
91     __attribute__((nonnull(1,5,6,7,8)));
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     - __attribute__((nonnull(1,2,3,4)));
99     static void query_callback(DNSServiceRef sdRef,
100     DNSServiceFlags flags,
101     uint32_t interfaceIndex,
102     @@ -111,10 +142,119 @@ static void query_callback(DNSServiceRe
103     const void *rdata, uint32_t ttl,
104     void *context)
105     __attribute__((nonnull(1,5,9,11)));
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 */
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     + __attribute__((nonnull(1,2,3,4)));
131     static void sigterm_handler(int sig);
132     static void unquote(char *dst, const char *src, size_t dstsize)
133     __attribute__((nonnull(1,2)));
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++;
179     + if (!datalen || (data + datalen) > txt->dataend)
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.
222     @@ -125,6 +265,13 @@ main(int argc, /* I - Number of comm
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 */
236     @@ -138,12 +285,11 @@ main(int argc, /* I - Number of comm
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 */
254     @@ -203,6 +349,49 @@ main(int argc, /* I - Number of comm
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");
304     @@ -263,6 +452,7 @@ main(int argc, /* I - Number of comm
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...
312     @@ -270,6 +460,9 @@ main(int argc, /* I - Number of comm
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    
322     @@ -289,11 +482,35 @@ main(int argc, /* I - Number of comm
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 */
358     @@ -307,6 +524,7 @@ main(int argc, /* I - Number of comm
359     if (device->sent)
360     sent ++;
361    
362     +#ifdef HAVE_DNSSD
363     if (device->ref)
364     count ++;
365    
366     @@ -338,14 +556,23 @@ main(int argc, /* I - Number of comm
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;
391     @@ -406,6 +633,7 @@ main(int argc, /* I - Number of comm
392     }
393    
394    
395     +#ifdef HAVE_DNSSD
396     /*
397     * 'browse_callback()' - Browse devices.
398     */
399     @@ -494,6 +722,7 @@ browse_local_callback(
400     device->fullName);
401     device->sent = 1;
402     }
403     +#endif /* HAVE_DNSSD */
404    
405    
406     /*
407     @@ -574,6 +803,41 @@ exec_backend(char **argv) /* I - Comman
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    
449     @@ -594,20 +858,7 @@ get_device(cups_array_t *devices, /* I -
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;
471     @@ -627,8 +878,14 @@ get_device(cups_array_t *devices, /* I -
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     }
486     @@ -648,6 +905,9 @@ get_device(cups_array_t *devices, /* I -
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    
496     @@ -655,13 +915,20 @@ get_device(cups_array_t *devices, /* I -
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     */
517     @@ -685,7 +952,7 @@ query_callback(
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\", "
526     @@ -719,94 +986,233 @@ query_callback(
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);
643    
644     - for (device = cupsArrayFind(devices, &dkey);
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     +
719     +
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     -
784     - if (!datalen || (data + datalen) > dataend)
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...
822     @@ -861,6 +1267,10 @@ query_callback(
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)
833     @@ -917,11 +1327,9 @@ query_callback(
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     */
846     diff -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
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
897     @@ -1434,6 +1461,9 @@ _httpResolveURI(
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")
907     @@ -1452,6 +1482,17 @@ _httpResolveURI(
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);
925     @@ -1488,9 +1529,16 @@ _httpResolveURI(
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\", "
942     @@ -1504,6 +1552,7 @@ _httpResolveURI(
943    
944     uri = NULL;
945    
946     +#ifdef HAVE_DNSSD
947     if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
948     {
949     localref = ref;
950     @@ -1611,6 +1660,36 @@ _httpResolveURI(
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     {
987     @@ -1622,13 +1701,13 @@ _httpResolveURI(
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."));
1003     @@ -1916,6 +1995,115 @@ http_resolve_cb(
1004     }
1005     #endif /* HAVE_DNSSD */
1006    
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     +
1116    
1117     /*
1118     * End of "$Id: http-support.c 10284 2012-02-15 01:06:12Z mike $".