Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1786 - (show 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 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 $".