Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1642 - (show 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 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 */