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
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.
28 #include "backend-private.h"
29 #include <cups/array.h>
33 +#endif /* HAVE_DNSSD */
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 */
46 @@ -53,7 +71,12 @@ typedef enum
51 DNSServiceRef ref; /* Service reference for resolve */
52 +#endif /* HAVE_DNSSD */
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? */
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;
80 @@ -78,6 +115,7 @@ static int job_canceled = 0;
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,
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,
105 __attribute__((nonnull(1,5,9,11)));
106 +#endif /* HAVE_DNSSD */
108 +static void avahi_client_callback (AvahiClient *client,
109 + AvahiClientState state,
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,
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)));
136 +static AvahiSimplePoll *simple_poll = NULL;
137 +static int avahi_got_callback;
138 +#endif /* HAVE_AVAHI */
142 + * 'next_txt_record()' - Get next TXT record from a cups_txt_records_t.
145 +static cups_txt_records_t *
146 +next_txt_record (cups_txt_records_t *txt)
149 + txt->data = txt->datanext;
150 +#else /* HAVE_AVAHI */
151 + txt->txt = avahi_string_list_get_next (txt->txt);
152 + if (txt->txt == NULL)
154 +#endif /* HAVE_DNSSD */
161 + * 'parse_txt_record_pair()' - Read key/value pair in cups_txt_records_t.
165 +parse_txt_record_pair (cups_txt_records_t *txt)
169 + uint8_t *data = txt->data;
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...
179 + if (!datalen || (data + datalen) > txt->dataend)
181 + txt->datanext = data + datalen;
183 + for (ptr = txt->key; data < txt->datanext && *data != '='; data ++)
187 + if (data < txt->datanext && *data == '=')
191 + if (data < datanext)
192 + memcpy (txt->value, data, txt->datanext - data);
193 + value[txt->datanext - data] = '\0';
197 +#else /* HAVE_AVAHI */
200 + avahi_string_list_get_pair (txt->txt, &key, &value, &len);
201 + if (len > sizeof (txt->value) - 1)
202 + len = sizeof (txt->value) - 1;
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;
210 + memcpy (txt->key, key, len);
211 + txt->key[len] = '\0';
213 + avahi_free (value);
214 +#endif /* HAVE_AVAHI */
221 * 'main()' - Browse for printers.
222 @@ -125,6 +265,13 @@ main(int argc, /* I - Number of comm
223 char *argv[]) /* I - Command-line arguments */
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 */
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 */
248 + AvahiClient *client;
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...
259 + if ((simple_poll = avahi_simple_poll_new ()) == NULL)
261 + perror ("ERROR: Unable to create avahi simple poll object");
265 + client = avahi_client_new (avahi_simple_poll_get (simple_poll),
266 + 0, avahi_client_callback, NULL, &error);
269 + perror ("DEBUG: Unable to create avahi client");
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",
289 + avahi_browse_callback,
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 */
301 if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
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 */
311 * Loop until we are killed...
312 @@ -270,6 +460,9 @@ main(int argc, /* I - Number of comm
314 while (!job_canceled)
322 @@ -289,11 +482,35 @@ main(int argc, /* I - Number of comm
328 +#else /* HAVE_AVAHI */
330 + avahi_got_callback = 0;
331 + r = avahi_simple_poll_iterate (simple_poll, 1);
332 + if (r != 0 && r != EINTR)
335 + * We've been told to exit the loop. Perhaps the connection to
342 + if (avahi_got_callback)
344 +#endif /* HAVE_DNSSD */
349 * Announce any devices we've found...
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
366 @@ -338,14 +556,23 @@ main(int argc, /* I - Number of comm
370 - else if (!device->sent)
372 +#endif /* HAVE_DNSSD */
374 + if (!device->resolved)
377 +#endif /* HAVE_AVAHI */
382 * Got the TXT records, now report the device...
385 DNSServiceRefDeallocate(device->ref);
387 +#endif /* HAVE_DNSSD */
391 @@ -406,6 +633,7 @@ main(int argc, /* I - Number of comm
397 * 'browse_callback()' - Browse devices.
399 @@ -494,6 +722,7 @@ browse_local_callback(
403 +#endif /* HAVE_DNSSD */
407 @@ -574,6 +803,41 @@ exec_backend(char **argv) /* I - Comman
411 + * 'device_type()' - Get DNS-SD type enumeration from string.
415 +device_type (const char *regtype)
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);
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 */
441 + return (CUPS_DEVICE_RIOUSBPRINT);
446 * 'get_device()' - Create or update a device.
449 @@ -594,20 +858,7 @@ get_device(cups_array_t *devices, /* I -
452 key.name = (char *)serviceName;
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;
466 - key.type = CUPS_DEVICE_RIOUSBPRINT;
467 + key.type = device_type (regtype);
469 for (device = cupsArrayFind(devices, &key);
471 @@ -627,8 +878,14 @@ get_device(cups_array_t *devices, /* I -
472 free(device->domain);
473 device->domain = strdup(replyDomain);
476 DNSServiceConstructFullName(fullName, device->name, regtype,
478 +#else /* HAVE_AVAHI */
479 + avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
480 + serviceName, regtype, replyDomain);
481 +#endif /* HAVE_DNSSD */
483 free(device->fullName);
484 device->fullName = strdup(fullName);
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;
491 + device->resolved = 0;
492 +#endif /* HAVE_AVAHI */
494 cupsArrayAdd(devices, device);
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...
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 */
507 device->fullName = strdup(fullName);
515 * 'query_callback()' - Process query data.
517 @@ -685,7 +952,7 @@ query_callback(
518 *ptr; /* Pointer into string */
519 cups_device_t dkey, /* Search key */
520 *device; /* Device */
522 + cups_txt_records_t txt;
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)
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);
544 + txt.dataend = rdata + rdlen;
545 + device = find_device ((cups_array_t *) context, &txt, &dkey);
547 + fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
549 +#endif /* HAVE_DNSSD */
554 + * 'avahi_client_callback()' - Avahi client callback function.
558 +avahi_client_callback(AvahiClient *client,
559 + AvahiClientState state,
563 + * If the connection drops, quit.
566 + if (state == AVAHI_CLIENT_FAILURE)
568 + fprintf (stderr, "ERROR: Avahi connection failed\n");
569 + avahi_simple_poll_quit (simple_poll);
575 + * 'avahi_query_callback()' - Avahi query callback function.
579 +avahi_query_callback(AvahiServiceResolver *resolver,
580 + AvahiIfIndex interface,
581 + AvahiProtocol protocol,
582 + AvahiResolverEvent event,
585 + const char *domain,
586 + const char *host_name,
587 + const AvahiAddress *address,
589 + AvahiStringList *txt,
590 + AvahiLookupResultFlags flags,
593 + AvahiClient *client;
598 + cups_txt_records_t txtr;
600 + client = avahi_service_resolver_get_client (resolver);
601 + if (event != AVAHI_RESOLVER_FOUND)
603 + if (event == AVAHI_RESOLVER_FAILURE)
605 + fprintf (stderr, "ERROR: %s\n",
606 + avahi_strerror (avahi_client_errno (client)));
609 + avahi_service_resolver_free (resolver);
614 + * Set search key for device.
618 + unquote (uqname, name, sizeof (uqname));
619 + if ((ptr = strstr(name, "._")) != NULL)
622 + key.domain = (char *) domain;
623 + key.type = device_type (type);
626 + * Find the device and the the TXT information.
630 + device = find_device ((cups_array_t *) context, &txtr, &key);
634 + * Let the main loop know to announce the device.
637 + device->resolved = 1;
638 + avahi_got_callback = 1;
641 - dkey.type = CUPS_DEVICE_RIOUSBPRINT;
642 + fprintf (stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", name);
644 - for (device = cupsArrayFind(devices, &dkey);
645 + avahi_service_resolver_free (resolver);
650 + * 'avahi_browse_callback()' - Avahi browse callback function.
654 +avahi_browse_callback(AvahiServiceBrowser *browser,
655 + AvahiIfIndex interface,
656 + AvahiProtocol protocol,
657 + AvahiBrowserEvent event,
660 + const char *domain,
661 + AvahiLookupResultFlags flags,
664 + AvahiClient *client = avahi_service_browser_get_client (browser);
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);
674 + case AVAHI_BROWSER_NEW:
676 + * This object is new on the network.
679 + if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
682 + * This comes from the local machine so ignore it.
685 + fprintf (stderr, "DEBUG: ignoring local service %s\n", name);
690 + * Create a device entry for it if it doesn't yet exist.
693 + get_device ((cups_array_t *)context, name, type, domain);
696 + * Now look for a TXT entry.
699 + if (avahi_service_resolver_new (client, interface, protocol,
700 + name, type, domain,
701 + AVAHI_PROTO_UNSPEC, 0,
702 + avahi_query_callback, context) == NULL)
704 + fprintf (stderr, "ERROR: failed to resolve service %s: %s\n",
705 + name, avahi_strerror (avahi_client_errno (client)));
711 + case AVAHI_BROWSER_REMOVE:
712 + case AVAHI_BROWSER_ALL_FOR_NOW:
713 + case AVAHI_BROWSER_CACHE_EXHAUSTED:
717 +#endif /* HAVE_AVAHI */
721 + * 'find_device()' - Find a device from its name and domain.
724 +static cups_device_t *
725 +find_device (cups_array_t *devices,
726 + cups_txt_records_t *txt,
727 + cups_device_t *dkey)
729 + cups_device_t *device;
732 + for (device = cupsArrayFind(devices, dkey);
734 device = cupsArrayNext(devices))
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))
744 - else if (device->type == dkey.type)
745 + else if (device->type == dkey->type)
748 * Found it, pull out the priority and make and model from the TXT
749 * record and save it...
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 */
764 + device_id[2048]; /* 1284 device ID */
767 make_and_model[0] = '\0';
769 strcpy(model, "Unknown");
771 - for (data = rdata, dataend = data + rdlen;
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...
784 - if (!datalen || (data + datalen) > dataend)
787 - datanext = data + datalen;
789 - for (ptr = key; data < datanext && *data != '='; data ++)
795 - if (data < datanext && *data == '=')
799 - if (data < datanext)
800 - memcpy(value, data, datanext - data);
801 - value[datanext - data] = '\0';
802 + if (parse_txt_record_pair (txt))
805 - fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
810 - fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
815 - if (!_cups_strncasecmp(key, "usb_", 4))
817 + value = txt->value;
818 + if (!strncasecmp(key, "usb_", 4))
821 * Add USB device ID information...
822 @@ -861,6 +1267,10 @@ query_callback(
823 if (device->type == CUPS_DEVICE_PRINTER)
828 + if (next_txt_record (txt) == NULL)
832 if (device->device_id)
833 @@ -917,11 +1327,9 @@ query_callback(
838 - fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
844 * 'sigterm_handler()' - Handle termination signals...
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
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.
861 # include <sys/select.h>
863 #endif /* HAVE_DNSSD */
865 +# include <avahi-client/client.h>
866 +# include <avahi-client/lookup.h>
867 +# include <avahi-common/simple-watch.h>
868 +#endif /* HAVE_AVAHI */
872 @@ -127,6 +136,24 @@ static void DNSSD_API http_resolve_cb(DN
874 #endif /* HAVE_DNSSD */
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,
886 + const char *domain,
887 + const char *host_name,
888 + const AvahiAddress *address,
890 + AvahiStringList *txt,
891 + AvahiLookupResultFlags flags,
893 +#endif /* HAVE_AVAHI */
896 * 'httpAssembleURI()' - Assemble a uniform resource identifier from its
897 @@ -1434,6 +1461,9 @@ _httpResolveURI(
899 if (strstr(hostname, "._tcp"))
901 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
902 + char *regtype, /* Pointer to type in hostname */
903 + *domain; /* Pointer to domain in hostname */
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;
917 + AvahiSimplePoll *poll;
918 + _http_uribuf_t uribuf;
920 +#endif /* HAVE_DNSSD */
923 if (options & _HTTP_RESOLVE_STDERR)
924 fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
925 @@ -1488,9 +1529,16 @@ _httpResolveURI(
930 uribuf.buffer = resolved_uri;
931 uribuf.bufsize = resolved_size;
932 uribuf.options = options;
934 + user_data.uribuf.buffer = resolved_uri;
935 + user_data.uribuf.bufsize = resolved_size;
936 + user_data.uribuf.options = options;
939 resolved_uri[0] = '\0';
941 DEBUG_printf(("6_httpResolveURI: Resolving hostname=\"%s\", regtype=\"%s\", "
942 @@ -1504,6 +1552,7 @@ _httpResolveURI(
947 if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
950 @@ -1611,6 +1660,36 @@ _httpResolveURI(
952 DNSServiceRefDeallocate(ref);
954 +#else /* HAVE_AVAHI */
955 + if ((simple_poll = avahi_simple_poll_new ()) != NULL)
957 + if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll),
958 + 0, avahi_resolve_uri_client_cb,
959 + &simple_poll, &error)) != NULL)
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)
968 + avahi_simple_poll_loop (simple_poll);
971 + * Collect the result.
974 + if (resolved_uri[0])
975 + uri = resolved_uri;
978 + avahi_client_free (client);
981 + avahi_simple_poll_free (simple_poll);
983 +#endif /* HAVE_DNSSD */
985 if (options & _HTTP_RESOLVE_STDERR)
987 @@ -1622,13 +1701,13 @@ _httpResolveURI(
988 fputs("STATE: -connecting-to-device,offline-report\n", stderr);
992 +#else /* HAVE_DNSSD || HAVE_AVAHI */
994 * No DNS-SD support...
998 -#endif /* HAVE_DNSSD */
999 +#endif /* HAVE_DNSSD || HAVE_AVAHI */
1001 if ((options & _HTTP_RESOLVE_STDERR) && !uri)
1002 _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
1003 @@ -1916,6 +1995,115 @@ http_resolve_cb(
1005 #endif /* HAVE_DNSSD */
1009 + * 'avahi_resolve_uri_client_cb()' - Avahi client callback for resolving URI.
1013 +avahi_resolve_uri_client_cb (AvahiClient *client,
1014 + AvahiClientState state,
1015 + void *simple_poll)
1017 + DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, "
1018 + "simple_poll=%p)\n", client, state, simple_poll));
1021 + * If the connection drops, quit.
1024 + if (state == AVAHI_CLIENT_FAILURE)
1025 + avahi_simple_poll_quit (simple_poll);
1030 + * 'avahi_resolve_uri_resolver_cb()' - Avahi resolver callback for resolving
1035 +avahi_resolve_uri_resolver_cb (AvahiServiceResolver *resolver,
1036 + AvahiIfIndex interface,
1037 + AvahiProtocol protocol,
1038 + AvahiResolverEvent event,
1041 + const char *domain,
1042 + const char *host_name,
1043 + const AvahiAddress *address,
1045 + AvahiStringList *txt,
1046 + AvahiLookupResultFlags flags,
1049 + const char *scheme; /* URI scheme */
1050 + char rp[256]; /* Remote printer */
1051 + AvahiStringList *pair;
1053 + size_t valueLen = 0;
1054 + char addr[AVAHI_ADDRESS_STR_MAX];
1057 + AvahiSimplePoll *poll;
1058 + _http_uribuf_t uribuf;
1059 + } *poll_uribuf = context;
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));
1068 + if (event != AVAHI_RESOLVER_FOUND)
1070 + avahi_service_resolver_free (resolver);
1071 + avahi_simple_poll_quit (poll_uribuf->poll);
1076 + * Figure out the scheme from the full name...
1079 + if (strstr(type, "_ipp."))
1081 + else if (strstr(type, "_printer."))
1083 + else if (strstr(type, "_pdl-datastream."))
1084 + scheme = "socket";
1086 + scheme = "riousbprint";
1089 + * Extract the "remote printer key from the TXT record...
1092 + if ((pair = avahi_string_list_find (txt, "rp")) != NULL)
1094 + avahi_string_list_get_pair (pair, NULL, &value, &valueLen);
1096 + memcpy (rp + 1, value, valueLen);
1097 + rp[valueLen + 1] = '\0';
1103 + * Assemble the final device URI...
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,
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);
1114 +#endif /* HAVE_AVAHI */