Tim Waugh b85faf
diff -up cups-1.4b2/backend/dnssd.c.avahi cups-1.4b2/backend/dnssd.c
Tim Waugh b85faf
--- cups-1.4b2/backend/dnssd.c.avahi	2008-10-07 20:10:35.000000000 +0100
Tim Waugh b85faf
+++ cups-1.4b2/backend/dnssd.c	2009-02-12 13:14:34.000000000 +0000
Tim Waugh b85faf
@@ -20,7 +20,8 @@
Tim Waugh b85faf
  *   browse_local_callback() - Browse local devices.
Tim Waugh b85faf
  *   compare_devices()       - Compare two devices.
Tim Waugh b85faf
  *   get_device()            - Create or update a device.
Tim Waugh b85faf
- *   query_callback()        - Process query data.
Tim Waugh b85faf
+ *   query_callback()        - Process query data from DNS-SD
Tim Waugh b85faf
+ *   find_device()	     - Process query data.
Tim Waugh b85faf
  *   unquote()               - Unquote a name string.
Tim Waugh b85faf
  */
Tim Waugh b85faf
 
Tim Waugh b85faf
@@ -30,7 +31,16 @@
Tim Waugh b85faf
 
Tim Waugh b85faf
 #include "backend-private.h"
Tim Waugh b85faf
 #include <cups/array.h>
Tim Waugh b85faf
-#include <dns_sd.h>
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+# include <avahi-client/client.h>
Tim Waugh b85faf
+# include <avahi-client/lookup.h>
Tim Waugh b85faf
+# include <avahi-common/simple-watch.h>
Tim Waugh b85faf
+# include <avahi-common/domain.h>
Tim Waugh b85faf
+# include <avahi-common/error.h>
Tim Waugh b85faf
+#define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+# include <dns_sd.h>
Tim Waugh b85faf
+#endif /* Avahi */
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
@@ -49,7 +59,9 @@ typedef enum
Tim Waugh b85faf
 
Tim Waugh b85faf
 typedef struct
Tim Waugh b85faf
 {
Tim Waugh b85faf
+#ifdef HAVE_DNSSD
Tim Waugh b85faf
   DNSServiceRef	ref;			/* Service reference for resolve */
Tim Waugh b85faf
+#endif /* HAVE_DNSSD */
Tim Waugh b85faf
   char		*name,			/* Service name */
Tim Waugh b85faf
 		*domain,		/* Domain name */
Tim Waugh b85faf
 		*fullName,		/* Full name */
Tim Waugh b85faf
@@ -65,6 +77,26 @@ typedef struct
Tim Waugh b85faf
  * Local functions...
Tim Waugh b85faf
  */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+/*
Tim Waugh b85faf
+ * Avahi callback functions
Tim Waugh b85faf
+ */
Tim Waugh b85faf
+static void	avahi_client_callback(AvahiClient *client,
Tim Waugh b85faf
+				      AvahiClientState state,
Tim Waugh b85faf
+				      void *context);
Tim Waugh b85faf
+static void	avahi_browse_callback(AvahiServiceBrowser *browser,
Tim Waugh b85faf
+				      AvahiIfIndex interface,
Tim Waugh b85faf
+				      AvahiProtocol protocol,
Tim Waugh b85faf
+				      AvahiBrowserEvent event,
Tim Waugh b85faf
+				      const char *serviceName,
Tim Waugh b85faf
+				      const char *regtype,
Tim Waugh b85faf
+				      const char *replyDomain,
Tim Waugh b85faf
+				      AvahiLookupResultFlags flags,
Tim Waugh b85faf
+				      void *context);
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+/*
Tim Waugh b85faf
+ * libdns_sd callback functions
Tim Waugh b85faf
+ */
Tim Waugh b85faf
 static void		browse_callback(DNSServiceRef sdRef,
Tim Waugh b85faf
 			                DNSServiceFlags flags,
Tim Waugh b85faf
 				        uint32_t interfaceIndex,
Tim Waugh b85faf
@@ -80,12 +112,6 @@ static void		browse_local_callback(DNSSe
Tim Waugh b85faf
 					      const char *regtype,
Tim Waugh b85faf
 					      const char *replyDomain,
Tim Waugh b85faf
 					      void *context);
Tim Waugh b85faf
-static int		compare_devices(cups_device_t *a, cups_device_t *b);
Tim Waugh b85faf
-static void		exec_backend(char **argv);
Tim Waugh b85faf
-static cups_device_t	*get_device(cups_array_t *devices,
Tim Waugh b85faf
-			            const char *serviceName,
Tim Waugh b85faf
-			            const char *regtype,
Tim Waugh b85faf
-				    const char *replyDomain);
Tim Waugh b85faf
 static void		query_callback(DNSServiceRef sdRef,
Tim Waugh b85faf
 			               DNSServiceFlags flags,
Tim Waugh b85faf
 				       uint32_t interfaceIndex,
Tim Waugh b85faf
@@ -94,7 +120,31 @@ static void		query_callback(DNSServiceRe
Tim Waugh b85faf
 				       uint16_t rrclass, uint16_t rdlen,
Tim Waugh b85faf
 				       const void *rdata, uint32_t ttl,
Tim Waugh b85faf
 				       void *context);
Tim Waugh b85faf
+#endif
Tim Waugh b85faf
+
Tim Waugh b85faf
+static cups_device_t *find_device (cups_array_t *devices,
Tim Waugh b85faf
+				   cups_device_t *key,
Tim Waugh b85faf
+				   const char *priority, size_t priority_len,
Tim Waugh b85faf
+				   const char *mfg, size_t mfg_len,
Tim Waugh b85faf
+				   const char *mdl, size_t mdl_len,
Tim Waugh b85faf
+				   const char *product, size_t product_len,
Tim Waugh b85faf
+				   const char *ty, size_t ty_len,
Tim Waugh b85faf
+				   const char *printer_type,
Tim Waugh b85faf
+				   size_t printer_type_len);
Tim Waugh b85faf
+static int		compare_devices(cups_device_t *a, cups_device_t *b);
Tim Waugh b85faf
+static void		exec_backend(char **argv);
Tim Waugh b85faf
+static cups_device_t	*get_device(cups_array_t *devices,
Tim Waugh b85faf
+			            const char *serviceName,
Tim Waugh b85faf
+			            const char *regtype,
Tim Waugh b85faf
+				    const char *replyDomain);
Tim Waugh b85faf
 static void		unquote(char *dst, const char *src, size_t dstsize);
Tim Waugh b85faf
+static int		device_type(const char *regtype);
Tim Waugh b85faf
+
Tim Waugh b85faf
+
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+static AvahiSimplePoll *simple_poll = NULL;
Tim Waugh b85faf
+static int avahi_got_callback;
Tim Waugh b85faf
+#endif /* HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
@@ -106,6 +156,16 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
      char *argv[])			/* I - Command-line arguments */
Tim Waugh b85faf
 {
Tim Waugh b85faf
   const char	*name;			/* Backend name */
Tim Waugh b85faf
+  int		fd;			/* Main file descriptor */
Tim Waugh b85faf
+  fd_set	input;			/* Input set for select() */
Tim Waugh b85faf
+  struct timeval timeout;		/* Timeout for select() */
Tim Waugh b85faf
+  cups_array_t	*devices;		/* Device array */
Tim Waugh b85faf
+  cups_device_t	*device;		/* Current device */
Tim Waugh b85faf
+  char		uriName[1024];		/* Unquoted fullName for URI */
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+  AvahiClient	*client;
Tim Waugh b85faf
+  int		error;
Tim Waugh b85faf
+#else
Tim Waugh b85faf
   DNSServiceRef	main_ref,		/* Main service reference */
Tim Waugh b85faf
 		fax_ipp_ref,		/* IPP fax service reference */
Tim Waugh b85faf
 		ipp_ref,		/* IPP service reference */
Tim Waugh b85faf
@@ -117,11 +177,7 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
 		pdl_datastream_ref,	/* AppSocket service reference */
Tim Waugh b85faf
 		printer_ref,		/* LPD service reference */
Tim Waugh b85faf
 		riousbprint_ref;	/* Remote IO service reference */
Tim Waugh b85faf
-  int		fd;			/* Main file descriptor */
Tim Waugh b85faf
-  fd_set	input;			/* Input set for select() */
Tim Waugh b85faf
-  struct timeval timeout;		/* Timeout for select() */
Tim Waugh b85faf
-  cups_array_t	*devices;		/* Device array */
Tim Waugh b85faf
-  cups_device_t	*device;		/* Current device */
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
  /*
Tim Waugh b85faf
@@ -161,6 +217,48 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
   * Browse for different kinds of printers...
Tim Waugh b85faf
   */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+  if ((simple_poll = avahi_simple_poll_new ()) == NULL)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    perror ("ERROR: Unable to create avahi simple poll object");
Tim Waugh b85faf
+    return (1);
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+
Tim Waugh b85faf
+  client = avahi_client_new (avahi_simple_poll_get (simple_poll),
Tim Waugh b85faf
+			     0, avahi_client_callback, NULL, &error);
Tim Waugh b85faf
+  if (!client)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    perror ("ERROR: Unable to create avahi client");
Tim Waugh b85faf
+    return (1);
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_fax-ipp._tcp", NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback, devices);
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_ipp._tcp", NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback, devices);
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_ipp-tls._tcp", NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback, devices);
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_pdl-datastream._tcp",
Tim Waugh b85faf
+			     NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback,
Tim Waugh b85faf
+			     devices);
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_printer._tcp", NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback, devices);
Tim Waugh b85faf
+  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+			     AVAHI_PROTO_UNSPEC,
Tim Waugh b85faf
+			     "_riousbprint._tcp", NULL, 0,
Tim Waugh b85faf
+			     avahi_browse_callback, devices);
Tim Waugh b85faf
+#else
Tim Waugh b85faf
   if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
Tim Waugh b85faf
   {
Tim Waugh b85faf
     perror("ERROR: Unable to create service connection");
Tim Waugh b85faf
@@ -212,6 +310,7 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
   riousbprint_ref = main_ref;
Tim Waugh b85faf
   DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
Tim Waugh b85faf
                    "_riousbprint._tcp", NULL, browse_callback, devices);
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
  /*
Tim Waugh b85faf
   * Loop until we are killed...
Tim Waugh b85faf
@@ -219,6 +318,25 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
 
Tim Waugh b85faf
   for (;;)
Tim Waugh b85faf
   {
Tim Waugh b85faf
+    int announce = 0;
Tim Waugh b85faf
+
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+    int r;
Tim Waugh b85faf
+    avahi_got_callback = 0;
Tim Waugh b85faf
+    r = avahi_simple_poll_iterate (simple_poll, 1);
Tim Waugh b85faf
+    if (r != 0 && r != EINTR)
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+     /*
Tim Waugh b85faf
+      * We've been told to exit the loop.  Perhaps the connection to
Tim Waugh b85faf
+      * avahi failed.
Tim Waugh b85faf
+      */
Tim Waugh b85faf
+
Tim Waugh b85faf
+      break;
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+
Tim Waugh b85faf
+    if (avahi_got_callback)
Tim Waugh b85faf
+      announce = 1;
Tim Waugh b85faf
+#else
Tim Waugh b85faf
     FD_ZERO(&input);
Tim Waugh b85faf
     FD_SET(fd, &input);
Tim Waugh b85faf
 
Tim Waugh b85faf
@@ -238,11 +356,19 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
     }
Tim Waugh b85faf
     else
Tim Waugh b85faf
     {
Tim Waugh b85faf
+      announce = 1;
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
+    if (announce)
Tim Waugh b85faf
+    {
Tim Waugh b85faf
      /*
Tim Waugh b85faf
       * Announce any devices we've found...
Tim Waugh b85faf
       */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifndef HAVE_AVAHI
Tim Waugh b85faf
       DNSServiceErrorType status;	/* DNS query status */
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
       cups_device_t *best;		/* Best matching device */
Tim Waugh b85faf
       char	device_uri[1024];	/* Device URI */
Tim Waugh b85faf
       int	count;			/* Number of queries */
Tim Waugh b85faf
@@ -255,6 +381,7 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
                best = NULL, count = 0;
Tim Waugh b85faf
            device;
Tim Waugh b85faf
 	   device = (cups_device_t *)cupsArrayNext(devices))
Tim Waugh b85faf
+#ifndef HAVE_AVAHI
Tim Waugh b85faf
         if (!device->ref && !device->sent)
Tim Waugh b85faf
 	{
Tim Waugh b85faf
 	 /*
Tim Waugh b85faf
@@ -283,14 +410,19 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
 	      count ++;
Tim Waugh b85faf
           }
Tim Waugh b85faf
 	}
Tim Waugh b85faf
-	else if (!device->sent)
Tim Waugh b85faf
+	else
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
+	if (!device->sent)
Tim Waugh b85faf
 	{
Tim Waugh b85faf
+#ifndef HAVE_AVAHI
Tim Waugh b85faf
 	 /*
Tim Waugh b85faf
 	  * Got the TXT records, now report the device...
Tim Waugh b85faf
 	  */
Tim Waugh b85faf
 
Tim Waugh b85faf
 	  DNSServiceRefDeallocate(device->ref);
Tim Waugh b85faf
 	  device->ref = 0;
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
           if (!best)
Tim Waugh b85faf
 	    best = device;
Tim Waugh b85faf
@@ -332,6 +464,204 @@ main(int  argc,				/* I - Number of comm
Tim Waugh b85faf
 }
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_client_callback(
Tim Waugh b85faf
+  AvahiClient *client,
Tim Waugh b85faf
+  AvahiClientState state,
Tim Waugh b85faf
+  void *context)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * If the connection drops, quit.
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if (state == AVAHI_CLIENT_FAILURE)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    fprintf (stderr, "ERROR: Avahi connection failed\n");
Tim Waugh b85faf
+    avahi_simple_poll_quit (simple_poll);
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+}
Tim Waugh b85faf
+
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_query_callback(
Tim Waugh b85faf
+  AvahiServiceResolver *resolver,
Tim Waugh b85faf
+  AvahiIfIndex interface,
Tim Waugh b85faf
+  AvahiProtocol protocol,
Tim Waugh b85faf
+  AvahiResolverEvent event,
Tim Waugh b85faf
+  const char *name,
Tim Waugh b85faf
+  const char *type,
Tim Waugh b85faf
+  const char *domain,
Tim Waugh b85faf
+  const char *host_name,
Tim Waugh b85faf
+  const AvahiAddress *address,
Tim Waugh b85faf
+  uint16_t port,
Tim Waugh b85faf
+  AvahiStringList *txt,
Tim Waugh b85faf
+  AvahiLookupResultFlags flags,
Tim Waugh b85faf
+  void *context)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+  AvahiStringList	*pair;
Tim Waugh b85faf
+  AvahiClient		*client;
Tim Waugh b85faf
+  cups_device_t		key,
Tim Waugh b85faf
+			*device;
Tim Waugh b85faf
+  char			uqname[1024],
Tim Waugh b85faf
+			*ptr;
Tim Waugh b85faf
+  char			*priority = NULL,
Tim Waugh b85faf
+			*mfg = NULL,
Tim Waugh b85faf
+			*mdl = NULL,
Tim Waugh b85faf
+			*product = NULL,
Tim Waugh b85faf
+			*ty = NULL,
Tim Waugh b85faf
+			*printer_type = NULL;
Tim Waugh b85faf
+  size_t		priority_len = 0,
Tim Waugh b85faf
+			mfg_len = 0,
Tim Waugh b85faf
+			mdl_len = 0,
Tim Waugh b85faf
+			product_len = 0,
Tim Waugh b85faf
+			ty_len = 0,
Tim Waugh b85faf
+			printer_type_len = 0;
Tim Waugh b85faf
+
Tim Waugh b85faf
+  client = avahi_service_resolver_get_client (resolver);
Tim Waugh b85faf
+  if (event != AVAHI_RESOLVER_FOUND)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    if (event == AVAHI_RESOLVER_FAILURE)
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+      fprintf (stderr, "ERROR: %s\n",
Tim Waugh b85faf
+	       avahi_strerror (avahi_client_errno (client)));
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+
Tim Waugh b85faf
+    avahi_service_resolver_free (resolver);
Tim Waugh b85faf
+    return;
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Set search key for device.
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  key.name = uqname;
Tim Waugh b85faf
+  unquote (uqname, name, sizeof (uqname));
Tim Waugh b85faf
+  if ((ptr = strstr(name, "._")) != NULL)
Tim Waugh b85faf
+    *ptr = '\0';
Tim Waugh b85faf
+
Tim Waugh b85faf
+  key.domain = (char *) domain;
Tim Waugh b85faf
+  key.type = device_type (type);
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Look for information in the TXT string.
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "priority")) != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &priority, &priority_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "usb_MFG")) == NULL)
Tim Waugh b85faf
+    pair = avahi_string_list_find (txt, "usb_MANUFACTURER");
Tim Waugh b85faf
+  if (pair != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &mfg, &mfg_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "usb_MDL")) == NULL)
Tim Waugh b85faf
+    pair = avahi_string_list_find (txt, "usb_MODEL");
Tim Waugh b85faf
+  if (pair != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &mdl, &mdl_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "product")) != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &product, &product_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "ty")) != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &ty, &ty_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "printer-type")) != NULL)
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &printer_type, &printer_type_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Find the device and the the TXT information.
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  device = find_device ((cups_array_t *) context,
Tim Waugh b85faf
+			&key,
Tim Waugh b85faf
+			priority, priority_len,
Tim Waugh b85faf
+			mfg, mfg_len,
Tim Waugh b85faf
+			mdl, mdl_len,
Tim Waugh b85faf
+			product, product_len,
Tim Waugh b85faf
+			ty, ty_len,
Tim Waugh b85faf
+			printer_type, printer_type_len);
Tim Waugh b85faf
+  if (device)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+   /*
Tim Waugh b85faf
+    * Let the main loop know to announce the device.
Tim Waugh b85faf
+    */
Tim Waugh b85faf
+
Tim Waugh b85faf
+    avahi_got_callback = 1;
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+  else
Tim Waugh b85faf
+    fprintf (stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", name);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  avahi_service_resolver_free (resolver);
Tim Waugh b85faf
+}
Tim Waugh b85faf
+
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_browse_callback(
Tim Waugh b85faf
+  AvahiServiceBrowser *browser,
Tim Waugh b85faf
+  AvahiIfIndex interface,
Tim Waugh b85faf
+  AvahiProtocol protocol,
Tim Waugh b85faf
+  AvahiBrowserEvent event,
Tim Waugh b85faf
+  const char *name,
Tim Waugh b85faf
+  const char *type,
Tim Waugh b85faf
+  const char *domain,
Tim Waugh b85faf
+  AvahiLookupResultFlags flags,
Tim Waugh b85faf
+  void *context)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+  AvahiClient *client = avahi_service_browser_get_client (browser);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  switch (event)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+  case AVAHI_BROWSER_FAILURE:
Tim Waugh b85faf
+    fprintf (stderr, "ERROR: %s\n",
Tim Waugh b85faf
+	     avahi_strerror (avahi_client_errno (client)));
Tim Waugh b85faf
+    avahi_simple_poll_quit (simple_poll);
Tim Waugh b85faf
+    return;
Tim Waugh b85faf
+
Tim Waugh b85faf
+  case AVAHI_BROWSER_NEW:
Tim Waugh b85faf
+   /*
Tim Waugh b85faf
+    * This object is new on the network.
Tim Waugh b85faf
+    */
Tim Waugh b85faf
+
Tim Waugh b85faf
+    if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+     /*
Tim Waugh b85faf
+      * This comes from the local machine so ignore it.
Tim Waugh b85faf
+      */
Tim Waugh b85faf
+
Tim Waugh b85faf
+      fprintf (stderr, "DEBUG: ignoring local service %s\n", name);
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+    else
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+     /*
Tim Waugh b85faf
+      * Create a device entry for it if it doesn't yet exist.
Tim Waugh b85faf
+      */
Tim Waugh b85faf
+
Tim Waugh b85faf
+      get_device ((cups_array_t *)context, name, type, domain);
Tim Waugh b85faf
+
Tim Waugh b85faf
+     /*
Tim Waugh b85faf
+      * Now look for a TXT entry.
Tim Waugh b85faf
+      */
Tim Waugh b85faf
+
Tim Waugh b85faf
+      if (avahi_service_resolver_new (client, interface, protocol,
Tim Waugh b85faf
+				      name, type, domain,
Tim Waugh b85faf
+				      AVAHI_PROTO_UNSPEC, 0,
Tim Waugh b85faf
+				      avahi_query_callback, context) == NULL)
Tim Waugh b85faf
+      {
Tim Waugh b85faf
+	fprintf (stderr, "ERROR: failed to resolve service %s: %s\n",
Tim Waugh b85faf
+		 name, avahi_strerror (avahi_client_errno (client)));
Tim Waugh b85faf
+      }
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+
Tim Waugh b85faf
+    break;
Tim Waugh b85faf
+
Tim Waugh b85faf
+  case AVAHI_BROWSER_REMOVE:
Tim Waugh b85faf
+  case AVAHI_BROWSER_ALL_FOR_NOW:
Tim Waugh b85faf
+  case AVAHI_BROWSER_CACHE_EXHAUSTED:
Tim Waugh b85faf
+    break;
Tim Waugh b85faf
+  }  
Tim Waugh b85faf
+}
Tim Waugh b85faf
+
Tim Waugh b85faf
+#else /* !HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
 /*
Tim Waugh b85faf
  * 'browse_callback()' - Browse devices.
Tim Waugh b85faf
  */
Tim Waugh b85faf
@@ -420,6 +750,7 @@ browse_local_callback(
Tim Waugh b85faf
 	  device->fullName);
Tim Waugh b85faf
   device->sent = 1;
Tim Waugh b85faf
 }
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
@@ -518,18 +849,7 @@ get_device(cups_array_t *devices,	/* I -
Tim Waugh b85faf
 
Tim Waugh b85faf
   key.name   = (char *)serviceName;
Tim Waugh b85faf
   key.domain = (char *)replyDomain;
Tim Waugh b85faf
-
Tim Waugh b85faf
-  if (!strcmp(regtype, "_ipp._tcp.") ||
Tim Waugh b85faf
-      !strcmp(regtype, "_ipp-tls._tcp."))
Tim Waugh b85faf
-    key.type = CUPS_DEVICE_IPP;
Tim Waugh b85faf
-  else if (!strcmp(regtype, "_fax-ipp._tcp."))
Tim Waugh b85faf
-    key.type = CUPS_DEVICE_FAX_IPP;
Tim Waugh b85faf
-  else if (!strcmp(regtype, "_printer._tcp."))
Tim Waugh b85faf
-    key.type = CUPS_DEVICE_PRINTER;
Tim Waugh b85faf
-  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
Tim Waugh b85faf
-    key.type = CUPS_DEVICE_PDL_DATASTREAM;
Tim Waugh b85faf
-  else
Tim Waugh b85faf
-    key.type = CUPS_DEVICE_RIOUSBPRINT;
Tim Waugh b85faf
+  key.type = device_type (regtype);
Tim Waugh b85faf
 
Tim Waugh b85faf
   for (device = cupsArrayFind(devices, &key);
Tim Waugh b85faf
        device;
Tim Waugh b85faf
@@ -559,13 +879,20 @@ get_device(cups_array_t *devices,	/* I -
Tim Waugh b85faf
   * Set the "full name" of this service, which is used for queries...
Tim Waugh b85faf
   */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+  avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
Tim Waugh b85faf
+			   serviceName, regtype, replyDomain);
Tim Waugh b85faf
+  device->fullName = strdup(fullName);
Tim Waugh b85faf
+#else
Tim Waugh b85faf
   DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
Tim Waugh b85faf
   device->fullName = strdup(fullName);
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
   return (device);
Tim Waugh b85faf
 }
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifndef HAVE_AVAHI
Tim Waugh b85faf
 /*
Tim Waugh b85faf
  * 'query_callback()' - Process query data.
Tim Waugh b85faf
  */
Tim Waugh b85faf
@@ -584,12 +911,21 @@ query_callback(
Tim Waugh b85faf
     uint32_t            ttl,		/* I - Time-to-live */
Tim Waugh b85faf
     void                *context)	/* I - Devices array */
Tim Waugh b85faf
 {
Tim Waugh b85faf
-  cups_array_t	*devices;		/* Device array */
Tim Waugh b85faf
   char		name[1024],		/* Service name */
Tim Waugh b85faf
 		*ptr;			/* Pointer into name */
Tim Waugh b85faf
-  cups_device_t	key,			/* Search key */
Tim Waugh b85faf
-		*device;		/* Device */
Tim Waugh b85faf
-
Tim Waugh b85faf
+  cups_device_t	key;			/* Search key */
Tim Waugh b85faf
+  const char	*priority,
Tim Waugh b85faf
+		*mfg,
Tim Waugh b85faf
+		*mdl,
Tim Waugh b85faf
+		*product,
Tim Waugh b85faf
+		*ty,
Tim Waugh b85faf
+		*printer_type;
Tim Waugh b85faf
+  uint8_t	priority_len,
Tim Waugh b85faf
+		mfg_len,
Tim Waugh b85faf
+		mdl_len,
Tim Waugh b85faf
+		product_len,
Tim Waugh b85faf
+		ty_len,
Tim Waugh b85faf
+		printer_type_len;
Tim Waugh b85faf
 
Tim Waugh b85faf
   fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
Tim Waugh b85faf
                   "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
Tim Waugh b85faf
@@ -610,7 +946,6 @@ query_callback(
Tim Waugh b85faf
   * Lookup the service in the devices array.
Tim Waugh b85faf
   */
Tim Waugh b85faf
 
Tim Waugh b85faf
-  devices  = (cups_array_t *)context;
Tim Waugh b85faf
   key.name = name;
Tim Waugh b85faf
 
Tim Waugh b85faf
   unquote(name, fullName, sizeof(name));
Tim Waugh b85faf
@@ -635,88 +970,111 @@ query_callback(
Tim Waugh b85faf
   else
Tim Waugh b85faf
     key.type = CUPS_DEVICE_RIOUSBPRINT;
Tim Waugh b85faf
 
Tim Waugh b85faf
-  for (device = cupsArrayFind(devices, &key);
Tim Waugh b85faf
+  priority = TXTRecordGetValuePtr(rdlen, rdata, "priority", &priority_len);
Tim Waugh b85faf
+  if ((mfg = TXTRecordGetValuePtr(rdlen, rdata, "usb_MFG", &mfg_len)) == NULL)
Tim Waugh b85faf
+    mfg = TXTRecordGetValuePtr(rdlen, rdata, "usb_MANUFACTURER", &mfg_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((mdl = TXTRecordGetValuePtr(rdlen, rdata, "usb_MDL", &mdl_len)) == NULL)
Tim Waugh b85faf
+    mdl = TXTRecordGetValuePtr(rdlen, rdata, "usb_MODEL", &mdl_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  product = TXTRecordGetValuePtr(rdlen, rdata, "product", &product_len);
Tim Waugh b85faf
+  ty = TXTRecordGetValuePtr(rdlen, rdata, "ty", &ty_len);
Tim Waugh b85faf
+  printer_type = TXTRecordGetValuePtr(rdlen, rdata, "printer-type",
Tim Waugh b85faf
+				      &printer_type_len);
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if (!find_device ((cups_array_t *) context,
Tim Waugh b85faf
+		    &key,
Tim Waugh b85faf
+		    priority, priority_len,
Tim Waugh b85faf
+		    mfg, mfg_len,
Tim Waugh b85faf
+		    mdl, mdl_len,
Tim Waugh b85faf
+		    product, product_len,
Tim Waugh b85faf
+		    ty, ty_len,
Tim Waugh b85faf
+		    printer_type, printer_type_len))
Tim Waugh b85faf
+    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
Tim Waugh b85faf
+}
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
+
Tim Waugh b85faf
+static cups_device_t *
Tim Waugh b85faf
+find_device (cups_array_t *devices,
Tim Waugh b85faf
+	     cups_device_t *key,
Tim Waugh b85faf
+	     const char *priority, size_t priority_len,
Tim Waugh b85faf
+	     const char *mfg, size_t mfg_len,
Tim Waugh b85faf
+	     const char *mdl, size_t mdl_len,
Tim Waugh b85faf
+	     const char *product, size_t product_len,
Tim Waugh b85faf
+	     const char *ty, size_t ty_len,
Tim Waugh b85faf
+	     const char *printer_type, size_t printer_type_len)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+  cups_device_t *device;
Tim Waugh b85faf
+
Tim Waugh b85faf
+  for (device = cupsArrayFind(devices, key);
Tim Waugh b85faf
        device;
Tim Waugh b85faf
        device = cupsArrayNext(devices))
Tim Waugh b85faf
   {
Tim Waugh b85faf
-    if (strcasecmp(device->name, key.name) ||
Tim Waugh b85faf
-        strcasecmp(device->domain, key.domain))
Tim Waugh b85faf
+    if (strcasecmp(device->name, key->name) ||
Tim Waugh b85faf
+        strcasecmp(device->domain, key->domain))
Tim Waugh b85faf
     {
Tim Waugh b85faf
       device = NULL;
Tim Waugh b85faf
       break;
Tim Waugh b85faf
     }
Tim Waugh b85faf
-    else if (device->type == key.type)
Tim Waugh b85faf
+    else if (device->type == key->type)
Tim Waugh b85faf
     {
Tim Waugh b85faf
      /*
Tim Waugh b85faf
       * Found it, pull out the priority and make and model from the TXT
Tim Waugh b85faf
       * record and save it...
Tim Waugh b85faf
       */
Tim Waugh b85faf
 
Tim Waugh b85faf
-      const void *value;		/* Pointer to value */
Tim Waugh b85faf
-      uint8_t	valueLen;		/* Length of value (max 255) */
Tim Waugh b85faf
       char	make_and_model[512],	/* Manufacturer and model */
Tim Waugh b85faf
 		model[256],		/* Model */
Tim Waugh b85faf
-		priority[256];		/* Priority */
Tim Waugh b85faf
-
Tim Waugh b85faf
+		priority_buf[256],	/* Priority */
Tim Waugh b85faf
+		*ptr;
Tim Waugh b85faf
 
Tim Waugh b85faf
-      value = TXTRecordGetValuePtr(rdlen, rdata, "priority", &valueLen);
Tim Waugh b85faf
 
Tim Waugh b85faf
-      if (value && valueLen)
Tim Waugh b85faf
+      if (priority && priority_len)
Tim Waugh b85faf
       {
Tim Waugh b85faf
-	memcpy(priority, value, valueLen);
Tim Waugh b85faf
-	priority[valueLen] = '\0';
Tim Waugh b85faf
-	device->priority = atoi(priority);
Tim Waugh b85faf
+	memcpy(priority_buf, priority, priority_len);
Tim Waugh b85faf
+	priority_buf[priority_len] = '\0';
Tim Waugh b85faf
+	device->priority = atoi(priority_buf);
Tim Waugh b85faf
       }
Tim Waugh b85faf
 
Tim Waugh b85faf
-      if ((value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MFG",
Tim Waugh b85faf
-					&valueLen)) == NULL)
Tim Waugh b85faf
-	value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MANUFACTURER",
Tim Waugh b85faf
-	                             &valueLen);
Tim Waugh b85faf
-
Tim Waugh b85faf
-      if (value && valueLen)
Tim Waugh b85faf
+      if (mfg && mfg_len)
Tim Waugh b85faf
       {
Tim Waugh b85faf
-	memcpy(make_and_model, value, valueLen);
Tim Waugh b85faf
-	make_and_model[valueLen] = '\0';
Tim Waugh b85faf
+	memcpy(make_and_model, mfg, mfg_len);
Tim Waugh b85faf
+	make_and_model[mfg_len] = '\0';
Tim Waugh b85faf
       }
Tim Waugh b85faf
       else
Tim Waugh b85faf
 	make_and_model[0] = '\0';
Tim Waugh b85faf
 
Tim Waugh b85faf
-      if ((value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MDL",
Tim Waugh b85faf
-					&valueLen)) == NULL)
Tim Waugh b85faf
-	value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MODEL", &valueLen);
Tim Waugh b85faf
-
Tim Waugh b85faf
-      if (value && valueLen)
Tim Waugh b85faf
+      if (mdl && mdl_len)
Tim Waugh b85faf
       {
Tim Waugh b85faf
-	memcpy(model, value, valueLen);
Tim Waugh b85faf
-	model[valueLen] = '\0';
Tim Waugh b85faf
+	memcpy(model, mdl, mdl_len);
Tim Waugh b85faf
+	model[mdl_len] = '\0';
Tim Waugh b85faf
       }
Tim Waugh b85faf
-      else if ((value = TXTRecordGetValuePtr(rdlen, rdata, "product",
Tim Waugh b85faf
-					     &valueLen)) != NULL && valueLen > 2)
Tim Waugh b85faf
+      else if (product && product_len > 2)
Tim Waugh b85faf
       {
Tim Waugh b85faf
-	if (((char *)value)[0] == '(')
Tim Waugh b85faf
+	if (product[0] == '(')
Tim Waugh b85faf
 	{
Tim Waugh b85faf
 	 /*
Tim Waugh b85faf
 	  * Strip parenthesis...
Tim Waugh b85faf
 	  */
Tim Waugh b85faf
 
Tim Waugh b85faf
-	  memcpy(model, value + 1, valueLen - 2);
Tim Waugh b85faf
-	  model[valueLen - 2] = '\0';
Tim Waugh b85faf
+	  memcpy(model, product + 1, product_len - 2);
Tim Waugh b85faf
+	  model[product_len - 2] = '\0';
Tim Waugh b85faf
 	}
Tim Waugh b85faf
 	else
Tim Waugh b85faf
 	{
Tim Waugh b85faf
-	  memcpy(model, value, valueLen);
Tim Waugh b85faf
-	  model[valueLen] = '\0';
Tim Waugh b85faf
+	  memcpy(model, product, product_len);
Tim Waugh b85faf
+	  model[product_len] = '\0';
Tim Waugh b85faf
 	}
Tim Waugh b85faf
 
Tim Waugh b85faf
 	if (!strcasecmp(model, "GPL Ghostscript") ||
Tim Waugh b85faf
 	    !strcasecmp(model, "GNU Ghostscript") ||
Tim Waugh b85faf
 	    !strcasecmp(model, "ESP Ghostscript"))
Tim Waugh b85faf
 	{
Tim Waugh b85faf
-	  if ((value = TXTRecordGetValuePtr(rdlen, rdata, "ty",
Tim Waugh b85faf
-					    &valueLen)) != NULL)
Tim Waugh b85faf
+	  if (ty && ty_len)
Tim Waugh b85faf
 	  {
Tim Waugh b85faf
-	    memcpy(model, value, valueLen);
Tim Waugh b85faf
-	    model[valueLen] = '\0';
Tim Waugh b85faf
+	    memcpy(model, ty, ty_len);
Tim Waugh b85faf
+	    model[ty_len] = '\0';
Tim Waugh b85faf
 
Tim Waugh b85faf
 	    if ((ptr = strchr(model, ',')) != NULL)
Tim Waugh b85faf
 	      *ptr = '\0';
Tim Waugh b85faf
@@ -742,7 +1100,7 @@ query_callback(
Tim Waugh b85faf
 
Tim Waugh b85faf
       if ((device->type == CUPS_DEVICE_IPP ||
Tim Waugh b85faf
 	   device->type == CUPS_DEVICE_PRINTER) &&
Tim Waugh b85faf
-	  TXTRecordGetValuePtr(rdlen, rdata, "printer-type", &valueLen))
Tim Waugh b85faf
+	  printer_type)
Tim Waugh b85faf
       {
Tim Waugh b85faf
        /*
Tim Waugh b85faf
 	* This is a CUPS printer!
Tim Waugh b85faf
@@ -758,8 +1116,7 @@ query_callback(
Tim Waugh b85faf
     }
Tim Waugh b85faf
   }
Tim Waugh b85faf
 
Tim Waugh b85faf
-  if (!device)
Tim Waugh b85faf
-    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
Tim Waugh b85faf
+  return device;
Tim Waugh b85faf
 }
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
@@ -797,6 +1154,35 @@ unquote(char       *dst,		/* I - Destina
Tim Waugh b85faf
 }
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
+static int
Tim Waugh b85faf
+device_type (const char *regtype)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+  if (!strcmp(regtype, "_ipp._tcp") ||
Tim Waugh b85faf
+      !strcmp(regtype, "_ipp-tls._tcp"))
Tim Waugh b85faf
+    return (CUPS_DEVICE_IPP);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_fax-ipp._tcp"))
Tim Waugh b85faf
+    return (CUPS_DEVICE_FAX_IPP);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_printer._tcp"))
Tim Waugh b85faf
+    return (CUPS_DEVICE_PRINTER);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_pdl-datastream._tcp"))
Tim Waugh b85faf
+    return (CUPS_DEVICE_PDL_DATASTREAM);
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+  if (!strcmp(regtype, "_ipp._tcp.") ||
Tim Waugh b85faf
+      !strcmp(regtype, "_ipp-tls._tcp."))
Tim Waugh b85faf
+    return (CUPS_DEVICE_IPP);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_fax-ipp._tcp."))
Tim Waugh b85faf
+    return (CUPS_DEVICE_FAX_IPP);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_printer._tcp."))
Tim Waugh b85faf
+    return (CUPS_DEVICE_PRINTER);
Tim Waugh b85faf
+  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
Tim Waugh b85faf
+    return (CUPS_DEVICE_PDL_DATASTREAM);
Tim Waugh b85faf
+#endif /* !HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  return (CUPS_DEVICE_RIOUSBPRINT);
Tim Waugh b85faf
+}
Tim Waugh b85faf
+
Tim Waugh b85faf
+
Tim Waugh b85faf
 /*
Tim Waugh b85faf
  * End of "$Id: dnssd.c 8023 2008-10-07 19:10:35Z mike $".
Tim Waugh b85faf
  */
Tim Waugh b85faf
diff -up cups-1.4b2/config.h.in.avahi cups-1.4b2/config.h.in
Tim Waugh b85faf
--- cups-1.4b2/config.h.in.avahi	2008-09-08 23:03:01.000000000 +0100
Tim Waugh b85faf
+++ cups-1.4b2/config.h.in	2009-02-12 13:13:51.000000000 +0000
Tim Waugh b85faf
@@ -344,6 +344,13 @@
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
+ * Do we have Avahi for DNS Service Discovery?
Tim Waugh b85faf
+ */
Tim Waugh b85faf
+
Tim Waugh b85faf
+#undef HAVE_AVAHI
Tim Waugh b85faf
+
Tim Waugh b85faf
+
Tim Waugh b85faf
+/*
Tim Waugh b85faf
  * Do we have <sys/ioctl.h>?
Tim Waugh b85faf
  */
Tim Waugh b85faf
 
Tim Waugh b85faf
diff -up cups-1.4b2/config-scripts/cups-dnssd.m4.avahi cups-1.4b2/config-scripts/cups-dnssd.m4
Tim Waugh b85faf
--- cups-1.4b2/config-scripts/cups-dnssd.m4.avahi	2008-08-29 23:19:39.000000000 +0100
Tim Waugh b85faf
+++ cups-1.4b2/config-scripts/cups-dnssd.m4	2009-02-12 13:13:51.000000000 +0000
Tim Waugh b85faf
@@ -27,6 +27,21 @@ AC_ARG_WITH(dnssd-includes, [  --with-dn
Tim Waugh b85faf
 DNSSDLIBS=""
Tim Waugh b85faf
 DNSSD_BACKEND=""
Tim Waugh b85faf
 
Tim Waugh b85faf
+AC_ARG_ENABLE(avahi, [  --enable-avahi          turn on DNS Service Discovery support, default=no],
Tim Waugh b85faf
+	      [if test x$enable_avahi = xyes; then
Tim Waugh b85faf
+		       AC_MSG_CHECKING(for Avahi)
Tim Waugh b85faf
+		       if $PKGCONFIG --exists avahi-client; then
Tim Waugh b85faf
+			       AC_MSG_RESULT(yes)
Tim Waugh b85faf
+			       CFLAGS="$CFLAGS `$PKGCONFIG --cflags avahi-client`"
Tim Waugh b85faf
+			       DNSSDLIBS="`$PKGCONFIG --libs avahi-client`"
Tim Waugh b85faf
+			       DNSSD_BACKEND="dnssd"
Tim Waugh b85faf
+			       AC_DEFINE(HAVE_AVAHI)
Tim Waugh b85faf
+			       enable_dnssd=no
Tim Waugh b85faf
+		       else
Tim Waugh b85faf
+			       AC_MSG_RESULT(no)
Tim Waugh b85faf
+		       fi
Tim Waugh b85faf
+	       fi])
Tim Waugh b85faf
+
Tim Waugh b85faf
 if test x$enable_dnssd != xno; then
Tim Waugh b85faf
 	AC_CHECK_HEADER(dns_sd.h, [
Tim Waugh b85faf
 		case "$uname" in
Tim Waugh b85faf
diff -up cups-1.4b2/cups/http-support.c.avahi cups-1.4b2/cups/http-support.c
Tim Waugh b85faf
--- cups-1.4b2/cups/http-support.c.avahi	2008-12-10 05:03:11.000000000 +0000
Tim Waugh b85faf
+++ cups-1.4b2/cups/http-support.c	2009-02-12 13:18:24.000000000 +0000
Tim Waugh b85faf
@@ -53,6 +53,11 @@
Tim Waugh b85faf
 #ifdef HAVE_DNSSD
Tim Waugh b85faf
 #  include <dns_sd.h>
Tim Waugh b85faf
 #endif /* HAVE_DNSSD */
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+# include <avahi-client/client.h>
Tim Waugh b85faf
+# include <avahi-client/lookup.h>
Tim Waugh b85faf
+# include <avahi-common/simple-watch.h>
Tim Waugh b85faf
+#endif /* HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
@@ -119,6 +124,27 @@ static void		resolve_callback(DNSService
Tim Waugh b85faf
 					 void *context);
Tim Waugh b85faf
 #endif /* HAVE_DNSSD */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_resolve_uri_client_callback (AvahiClient *client,
Tim Waugh b85faf
+				   AvahiClientState state,
Tim Waugh b85faf
+				   void *simple_poll);
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_resolve_uri_resolver_callback (AvahiServiceResolver *resolver,
Tim Waugh b85faf
+				     AvahiIfIndex interface,
Tim Waugh b85faf
+				     AvahiProtocol protocol,
Tim Waugh b85faf
+				     AvahiResolverEvent event,
Tim Waugh b85faf
+				     const char *name,
Tim Waugh b85faf
+				     const char *type,
Tim Waugh b85faf
+				     const char *domain,
Tim Waugh b85faf
+				     const char *host_name,
Tim Waugh b85faf
+				     const AvahiAddress *address,
Tim Waugh b85faf
+				     uint16_t port,
Tim Waugh b85faf
+				     AvahiStringList *txt,
Tim Waugh b85faf
+				     AvahiLookupResultFlags flags,
Tim Waugh b85faf
+				     void *context);
Tim Waugh b85faf
+#endif /* HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
  * 'httpAssembleURI()' - Assemble a uniform resource identifier from its
Tim Waugh b85faf
@@ -1337,11 +1363,22 @@ _httpResolveURI(
Tim Waugh b85faf
 
Tim Waugh b85faf
   if (strstr(hostname, "._tcp"))
Tim Waugh b85faf
   {
Tim Waugh b85faf
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
Tim Waugh b85faf
 #ifdef HAVE_DNSSD
Tim Waugh b85faf
     DNSServiceRef	ref;		/* DNS-SD service reference */
Tim Waugh b85faf
+    _http_uribuf_t	uribuf;		/* URI buffer */
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+    AvahiSimplePoll	*simple_poll;
Tim Waugh b85faf
+    AvahiClient		*client;
Tim Waugh b85faf
+    int			error;
Tim Waugh b85faf
+    struct 
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+      AvahiSimplePoll	*poll;
Tim Waugh b85faf
+      _http_uribuf_t	uribuf;
Tim Waugh b85faf
+    }			user_data;
Tim Waugh b85faf
+#endif /* HAVE_DNSSD */
Tim Waugh b85faf
     char		*regtype,	/* Pointer to type in hostname */
Tim Waugh b85faf
 			*domain;	/* Pointer to domain in hostname */
Tim Waugh b85faf
-    _http_uribuf_t	uribuf;		/* URI buffer */
Tim Waugh b85faf
 
Tim Waugh b85faf
    /*
Tim Waugh b85faf
     * Separate the hostname into service name, registration type, and domain...
Tim Waugh b85faf
@@ -1379,8 +1416,13 @@ _httpResolveURI(
Tim Waugh b85faf
     if (domain)
Tim Waugh b85faf
       *domain++ = '\0';
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_DNSSD
Tim Waugh b85faf
     uribuf.buffer  = resolved_uri;
Tim Waugh b85faf
     uribuf.bufsize = resolved_size;
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+    user_data.uribuf.buffer = resolved_uri;
Tim Waugh b85faf
+    user_data.uribuf.bufsize = resolved_size;
Tim Waugh b85faf
+#endif
Tim Waugh b85faf
 
Tim Waugh b85faf
     resolved_uri[0] = '\0';
Tim Waugh b85faf
 
Tim Waugh b85faf
@@ -1394,6 +1436,7 @@ _httpResolveURI(
Tim Waugh b85faf
       _cupsLangPuts(stderr, _("INFO: Looking for printer...\n"));
Tim Waugh b85faf
     }
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_DNSSD
Tim Waugh b85faf
     if (DNSServiceResolve(&ref, 0, 0, hostname, regtype, domain,
Tim Waugh b85faf
 			  resolve_callback,
Tim Waugh b85faf
 			  &uribuf) == kDNSServiceErr_NoError)
Tim Waugh b85faf
@@ -1409,16 +1452,49 @@ _httpResolveURI(
Tim Waugh b85faf
     else
Tim Waugh b85faf
       uri = NULL;
Tim Waugh b85faf
 
Tim Waugh b85faf
+#else
Tim Waugh b85faf
+    if ((simple_poll = avahi_simple_poll_new ()) != NULL)
Tim Waugh b85faf
+    {
Tim Waugh b85faf
+      if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll),
Tim Waugh b85faf
+				      0, avahi_resolve_uri_client_callback,
Tim Waugh b85faf
+				      &simple_poll, &error)) != NULL)
Tim Waugh b85faf
+      {
Tim Waugh b85faf
+	user_data.poll = simple_poll;
Tim Waugh b85faf
+	if (avahi_service_resolver_new (client, AVAHI_IF_UNSPEC,
Tim Waugh b85faf
+					AVAHI_PROTO_UNSPEC, hostname,
Tim Waugh b85faf
+					regtype, domain, AVAHI_PROTO_UNSPEC, 0,
Tim Waugh b85faf
+					avahi_resolve_uri_resolver_callback,
Tim Waugh b85faf
+					&user_data) != NULL)
Tim Waugh b85faf
+	{
Tim Waugh b85faf
+	  avahi_simple_poll_loop (simple_poll);
Tim Waugh b85faf
+
Tim Waugh b85faf
+	 /*
Tim Waugh b85faf
+	  * Collect the result.
Tim Waugh b85faf
+	  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+	  if (resolved_uri[0])
Tim Waugh b85faf
+	    uri = resolved_uri;
Tim Waugh b85faf
+	  else
Tim Waugh b85faf
+	    uri = NULL;
Tim Waugh b85faf
+	}
Tim Waugh b85faf
+
Tim Waugh b85faf
+	avahi_client_free (client);
Tim Waugh b85faf
+      }
Tim Waugh b85faf
+
Tim Waugh b85faf
+      avahi_simple_poll_free (simple_poll);
Tim Waugh b85faf
+    }
Tim Waugh b85faf
+#endif
Tim Waugh b85faf
+
Tim Waugh b85faf
     if (log)
Tim Waugh b85faf
       fputs("STATE: -connecting-to-device\n", stderr);
Tim Waugh b85faf
 
Tim Waugh b85faf
-#else
Tim Waugh b85faf
-   /*
Tim Waugh b85faf
-    * No DNS-SD support...
Tim Waugh b85faf
-    */
Tim Waugh b85faf
-
Tim Waugh b85faf
+#else /* HAVE_DNSSD || HAVE_AVAHI */
Tim Waugh b85faf
+    /*
Tim Waugh b85faf
+     * No DNS-SD support...
Tim Waugh b85faf
+     */
Tim Waugh b85faf
+  
Tim Waugh b85faf
     uri = NULL;
Tim Waugh b85faf
-#endif /* HAVE_DNSSD */
Tim Waugh b85faf
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
Tim Waugh b85faf
 
Tim Waugh b85faf
     if (log && !uri)
Tim Waugh b85faf
       _cupsLangPuts(stderr, _("Unable to find printer!\n"));
Tim Waugh b85faf
@@ -1623,6 +1699,105 @@ resolve_callback(
Tim Waugh b85faf
 }
Tim Waugh b85faf
 #endif /* HAVE_DNSSD */
Tim Waugh b85faf
 
Tim Waugh b85faf
+#ifdef HAVE_AVAHI
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_resolve_uri_client_callback (AvahiClient *client,
Tim Waugh b85faf
+				   AvahiClientState state,
Tim Waugh b85faf
+				   void *simple_poll)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+  DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, "
Tim Waugh b85faf
+		"simple_poll=%p)\n", client, state, simple_poll));
Tim Waugh b85faf
+
Tim Waugh b85faf
+  /*
Tim Waugh b85faf
+   * If the connection drops, quit.
Tim Waugh b85faf
+   */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if (state == AVAHI_CLIENT_FAILURE)
Tim Waugh b85faf
+    avahi_simple_poll_quit (simple_poll);
Tim Waugh b85faf
+}
Tim Waugh b85faf
+
Tim Waugh b85faf
+static void
Tim Waugh b85faf
+avahi_resolve_uri_resolver_callback (AvahiServiceResolver *resolver,
Tim Waugh b85faf
+				     AvahiIfIndex interface,
Tim Waugh b85faf
+				     AvahiProtocol protocol,
Tim Waugh b85faf
+				     AvahiResolverEvent event,
Tim Waugh b85faf
+				     const char *name,
Tim Waugh b85faf
+				     const char *type,
Tim Waugh b85faf
+				     const char *domain,
Tim Waugh b85faf
+				     const char *host_name,
Tim Waugh b85faf
+				     const AvahiAddress *address,
Tim Waugh b85faf
+				     uint16_t port,
Tim Waugh b85faf
+				     AvahiStringList *txt,
Tim Waugh b85faf
+				     AvahiLookupResultFlags flags,
Tim Waugh b85faf
+				     void *context)
Tim Waugh b85faf
+{
Tim Waugh b85faf
+  const char		*scheme;	/* URI scheme */
Tim Waugh b85faf
+  char			rp[256];	/* Remote printer */
Tim Waugh b85faf
+  AvahiStringList	*pair;
Tim Waugh b85faf
+  char			*value;
Tim Waugh b85faf
+  size_t		valueLen = 0;
Tim Waugh b85faf
+  char			addr[AVAHI_ADDRESS_STR_MAX];
Tim Waugh b85faf
+  struct
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    AvahiSimplePoll	*poll;
Tim Waugh b85faf
+    _http_uribuf_t	uribuf;
Tim Waugh b85faf
+  }		*poll_uribuf = context;
Tim Waugh b85faf
+
Tim Waugh b85faf
+  DEBUG_printf(("avahi_resolve_uri_resolver_callback(resolver=%p, "
Tim Waugh b85faf
+		"interface=%d, protocol=%d, event=%d, name=\"%s\", "
Tim Waugh b85faf
+		"type=\"%s\", domain=\"%s\", host_name=\"%s\", address=%p, "
Tim Waugh b85faf
+		"port=%d, txt=%p, flags=%d, context=%p)\n",
Tim Waugh b85faf
+		resolver, interface, protocol, event, name, type, domain,
Tim Waugh b85faf
+		host_name, address, port, txt, flags, context));
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if (event != AVAHI_RESOLVER_FOUND)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    avahi_service_resolver_free (resolver);
Tim Waugh b85faf
+    avahi_simple_poll_quit (poll_uribuf->poll);
Tim Waugh b85faf
+    return;
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Figure out the scheme from the full name...
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if (strstr(type, "_ipp."))
Tim Waugh b85faf
+    scheme = "ipp";
Tim Waugh b85faf
+  else if (strstr(type, "_printer."))
Tim Waugh b85faf
+    scheme = "lpd";
Tim Waugh b85faf
+  else if (strstr(type, "_pdl-datastream."))
Tim Waugh b85faf
+    scheme = "socket";
Tim Waugh b85faf
+  else
Tim Waugh b85faf
+    scheme = "riousbprint";
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Extract the "remote printer key from the TXT record...
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  if ((pair = avahi_string_list_find (txt, "rp")) != NULL)
Tim Waugh b85faf
+  {
Tim Waugh b85faf
+    avahi_string_list_get_pair (pair, NULL, &value, &valueLen);
Tim Waugh b85faf
+    rp[0] = '/';
Tim Waugh b85faf
+    memcpy (rp + 1, value, valueLen);
Tim Waugh b85faf
+    rp[valueLen + 1] = '\0';
Tim Waugh b85faf
+  }
Tim Waugh b85faf
+  else
Tim Waugh b85faf
+    rp[0] = '\0';
Tim Waugh b85faf
+
Tim Waugh b85faf
+ /*
Tim Waugh b85faf
+  * Assemble the final device URI...
Tim Waugh b85faf
+  */
Tim Waugh b85faf
+
Tim Waugh b85faf
+  avahi_address_snprint (addr, AVAHI_ADDRESS_STR_MAX, address);
Tim Waugh b85faf
+  httpAssembleURI(HTTP_URI_CODING_ALL, poll_uribuf->uribuf.buffer,
Tim Waugh b85faf
+		  poll_uribuf->uribuf.bufsize, scheme, NULL,
Tim Waugh b85faf
+		  addr, port, rp);
Tim Waugh b85faf
+  DEBUG_printf(("avahi_resolve_uri_resolver_callback: Resolved URI is \"%s\"\n",
Tim Waugh b85faf
+		poll_uribuf->uribuf.buffer));
Tim Waugh b85faf
+  avahi_simple_poll_quit (poll_uribuf->poll);
Tim Waugh b85faf
+}
Tim Waugh b85faf
+#endif /* HAVE_AVAHI */
Tim Waugh b85faf
+
Tim Waugh b85faf
 
Tim Waugh b85faf
 /*
Tim Waugh b85faf
  * End of "$Id: http-support.c 8179 2008-12-10 05:03:11Z mike $".