]> git.pld-linux.org Git - packages/cups.git/blob - cups-avahi-2-backend.patch
- enable dnssd via avahi (using patches from fedora)
[packages/cups.git] / cups-avahi-2-backend.patch
1 diff -up cups-1.5.0/backend/dnssd.c.avahi-2-backend cups-1.5.0/backend/dnssd.c
2 --- cups-1.5.0/backend/dnssd.c.avahi-2-backend  2011-08-05 15:04:46.182591844 +0100
3 +++ cups-1.5.0/backend/dnssd.c  2011-08-05 15:05:13.868710181 +0100
4 @@ -15,14 +15,21 @@
5   *
6   * Contents:
7   *
8 + *   next_txt_record()       - Get next TXT record from a cups_txt_records_t.
9 + *   parse_txt_record_pair() - Read key/value pair in cups_txt_records_t.
10   *   main()                  - Browse for printers.
11   *   browse_callback()       - Browse devices.
12   *   browse_local_callback() - Browse local devices.
13   *   compare_devices()       - Compare two devices.
14   *   exec_backend()          - Execute the backend that corresponds to the
15   *                             resolved service name.
16 + *   device_type()           - Get DNS-SD type enumeration from string.
17   *   get_device()            - Create or update a device.
18   *   query_callback()        - Process query data.
19 + *   avahi_client_callback() - Avahi client callback function.
20 + *   avahi_query_callback()  - Avahi query callback function.
21 + *   avahi_browse_callback() - Avahi browse callback function.
22 + *   find_device()           - Find a device from its name and domain.
23   *   sigterm_handler()       - Handle termination signals...
24   *   unquote()               - Unquote a name string.
25   */
26 @@ -33,7 +40,18 @@
27  
28  #include "backend-private.h"
29  #include <cups/array.h>
30 -#include <dns_sd.h>
31 +#ifdef HAVE_DNSSD
32 +#  include <dns_sd.h>
33 +#endif /* HAVE_DNSSD */
34 +#ifdef HAVE_AVAHI
35 +#  include <avahi-client/client.h>
36 +#  include <avahi-client/lookup.h>
37 +#  include <avahi-common/simple-watch.h>
38 +#  include <avahi-common/domain.h>
39 +#  include <avahi-common/error.h>
40 +#  include <avahi-common/malloc.h>
41 +#define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
42 +#endif /* HAVE_AVAHI */
43  
44  
45  /*
46 @@ -53,7 +71,12 @@ typedef enum
47  
48  typedef struct
49  {
50 +#ifdef HAVE_DNSSD
51    DNSServiceRef        ref;                    /* Service reference for resolve */
52 +#endif /* HAVE_DNSSD */
53 +#ifdef HAVE_AVAHI
54 +  int          resolved;               /* Did we resolve the device? */
55 +#endif /* HAVE_AVAHI */
56    char         *name,                  /* Service name */
57                 *domain,                /* Domain name */
58                 *fullName,              /* Full name */
59 @@ -65,6 +88,20 @@ typedef struct
60                 sent;                   /* Did we list the device? */
61  } cups_device_t;
62  
63 +typedef struct
64 +{
65 +  char key[256];
66 +  char value[256];
67 +
68 +#ifdef HAVE_DNSSD
69 +  const uint8_t *data;
70 +  const uint8_t *datanext;
71 +  const uint8_t *dataend;
72 +#else /* HAVE_AVAHI */
73 +  AvahiStringList *txt;
74 +#endif /* HAVE_DNSSD */
75 +} cups_txt_records_t;
76 +
77  
78  /*
79   * Local globals...
80 @@ -78,6 +115,7 @@ static int           job_canceled = 0;
81   * Local functions...
82   */
83  
84 +#ifdef HAVE_DNSSD
85  static void            browse_callback(DNSServiceRef sdRef,
86                                         DNSServiceFlags flags,
87                                         uint32_t interfaceIndex,
88 @@ -93,12 +131,6 @@ static void         browse_local_callback(DNSSe
89                                               const char *regtype,
90                                               const char *replyDomain,
91                                               void *context);
92 -static int             compare_devices(cups_device_t *a, cups_device_t *b);
93 -static void            exec_backend(char **argv);
94 -static cups_device_t   *get_device(cups_array_t *devices,
95 -                                   const char *serviceName,
96 -                                   const char *regtype,
97 -                                   const char *replyDomain);
98  static void            query_callback(DNSServiceRef sdRef,
99                                        DNSServiceFlags flags,
100                                        uint32_t interfaceIndex,
101 @@ -107,9 +139,118 @@ static void               query_callback(DNSServiceRe
102                                        uint16_t rrclass, uint16_t rdlen,
103                                        const void *rdata, uint32_t ttl,
104                                        void *context);
105 +#endif /* HAVE_DNSSD */
106 +#ifdef HAVE_AVAHI
107 +static void            avahi_client_callback (AvahiClient *client,
108 +                                              AvahiClientState state,
109 +                                              void *context);
110 +static void            avahi_browse_callback (AvahiServiceBrowser *browser,
111 +                                              AvahiIfIndex interface,
112 +                                              AvahiProtocol protocol,
113 +                                              AvahiBrowserEvent event,
114 +                                              const char *serviceName,
115 +                                              const char *regtype,
116 +                                              const char *replyDomain,
117 +                                              AvahiLookupResultFlags flags,
118 +                                              void *context);
119 +#endif /* HAVE_AVAHI */
120 +
121 +static cups_device_t * find_device (cups_array_t *devices,
122 +                                    cups_txt_records_t *txt,
123 +                                    cups_device_t *dkey);
124 +static int             compare_devices(cups_device_t *a, cups_device_t *b);
125 +static void            exec_backend(char **argv);
126 +static cups_device_t   *get_device(cups_array_t *devices,
127 +                                   const char *serviceName,
128 +                                   const char *regtype,
129 +                                   const char *replyDomain);
130  static void            sigterm_handler(int sig);
131  static void            unquote(char *dst, const char *src, size_t dstsize);
132  
133 +#ifdef HAVE_AVAHI
134 +static AvahiSimplePoll *simple_poll = NULL;
135 +static int avahi_got_callback;
136 +#endif /* HAVE_AVAHI */
137 +
138 +
139 +/*
140 + * 'next_txt_record()' - Get next TXT record from a cups_txt_records_t.
141 + */
142 +
143 +static cups_txt_records_t *
144 +next_txt_record (cups_txt_records_t *txt)
145 +{
146 +#ifdef HAVE_DNSSD
147 +  txt->data = txt->datanext;
148 +#else /* HAVE_AVAHI */
149 +  txt->txt = avahi_string_list_get_next (txt->txt);
150 +  if (txt->txt == NULL)
151 +    return NULL;
152 +#endif /* HAVE_DNSSD */
153 +
154 +  return txt;
155 +}
156 +
157 +
158 +/*
159 + * 'parse_txt_record_pair()' - Read key/value pair in cups_txt_records_t.
160 + */
161 +
162 +static int
163 +parse_txt_record_pair (cups_txt_records_t *txt)
164 +{
165 +#ifdef HAVE_DNSSD
166 +  uint8_t      datalen;
167 +  uint8_t      *data = txt->data;
168 +  char         *ptr;
169 +
170 + /*
171 +  * Read a key/value pair starting with an 8-bit length.  Since the
172 +  * length is 8 bits and the size of the key/value buffers is 256, we
173 +  * don't need to check for overflow...
174 +  */
175 +
176 +  datalen = *data++;
177 +  if (!datalen || (data + datalen) >= txt->dataend)
178 +    return NULL;
179 +  txt->datanext = data + datalen;
180 +
181 +  for (ptr = txt->key; data < txt->datanext && *data != '='; data ++)
182 +    *ptr++ = *data;
183 +  *ptr = '\0';
184 +
185 +  if (data < txt->datanext && *data == '=')
186 +  {
187 +    data++;
188 +
189 +    if (data < datanext)
190 +      memcpy (txt->value, data, txt->datanext - data);
191 +    value[txt->datanext - data] = '\0';
192 +  }
193 +  else
194 +    return 1;
195 +#else /* HAVE_AVAHI */
196 +  char *key, *value;
197 +  size_t len;
198 +  avahi_string_list_get_pair (txt->txt, &key, &value, &len);
199 +  if (len > sizeof (txt->value) - 1)
200 +    len = sizeof (txt->value) - 1;
201 +
202 +  memcpy (txt->value, value, len);
203 +  txt->value[len] = '\0';
204 +  len = strlen (key);
205 +  if (len > sizeof (txt->key) - 1)
206 +    len = sizeof (txt->key) - 1;
207 +
208 +  memcpy (txt->key, key, len);
209 +  txt->key[len] = '\0';
210 +  avahi_free (key);
211 +  avahi_free (value);
212 +#endif /* HAVE_AVAHI */
213 +
214 +  return 0;
215 +}
216 +
217  
218  /*
219   * 'main()' - Browse for printers.
220 @@ -120,6 +261,13 @@ main(int  argc,                            /* I - Number of comm
221       char *argv[])                     /* I - Command-line arguments */
222  {
223    const char   *name;                  /* Backend name */
224 +  cups_array_t *devices;               /* Device array */
225 +  cups_device_t        *device;                /* Current device */
226 +  char         uriName[1024];          /* Unquoted fullName for URI */
227 +#ifdef HAVE_DNSSD
228 +  int          fd;                     /* Main file descriptor */
229 +  fd_set       input;                  /* Input set for select() */
230 +  struct timeval timeout;              /* Timeout for select() */
231    DNSServiceRef        main_ref,               /* Main service reference */
232                 fax_ipp_ref,            /* IPP fax service reference */
233                 ipp_ref,                /* IPP service reference */
234 @@ -133,12 +281,11 @@ main(int  argc,                           /* I - Number of comm
235                 pdl_datastream_ref,     /* AppSocket service reference */
236                 printer_ref,            /* LPD service reference */
237                 riousbprint_ref;        /* Remote IO service reference */
238 -  int          fd;                     /* Main file descriptor */
239 -  fd_set       input;                  /* Input set for select() */
240 -  struct timeval timeout;              /* Timeout for select() */
241 -  cups_array_t *devices;               /* Device array */
242 -  cups_device_t        *device;                /* Current device */
243 -  char         uriName[1024];          /* Unquoted fullName for URI */
244 +#endif /* HAVE_DNSSD */
245 +#ifdef HAVE_AVAHI
246 +  AvahiClient  *client;
247 +  int          error;
248 +#endif /* HAVE_AVAHI */
249  #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
250    struct sigaction action;             /* Actions for POSIX signals */
251  #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
252 @@ -198,6 +345,49 @@ main(int  argc,                            /* I - Number of comm
253    * Browse for different kinds of printers...
254    */
255  
256 +#ifdef HAVE_AVAHI
257 +  if ((simple_poll = avahi_simple_poll_new ()) == NULL)
258 +  {
259 +    perror ("ERROR: Unable to create avahi simple poll object");
260 +    return (1);
261 +  }
262 +
263 +  client = avahi_client_new (avahi_simple_poll_get (simple_poll),
264 +                            0, avahi_client_callback, NULL, &error);
265 +  if (!client)
266 +  {
267 +    perror ("DEBUG: Unable to create avahi client");
268 +    return (0);
269 +  }
270 +
271 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
272 +                            AVAHI_PROTO_UNSPEC,
273 +                            "_fax-ipp._tcp", NULL, 0,
274 +                            avahi_browse_callback, devices);
275 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
276 +                            AVAHI_PROTO_UNSPEC,
277 +                            "_ipp._tcp", NULL, 0,
278 +                            avahi_browse_callback, devices);
279 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
280 +                            AVAHI_PROTO_UNSPEC,
281 +                            "_ipp-tls._tcp", NULL, 0,
282 +                            avahi_browse_callback, devices);
283 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
284 +                            AVAHI_PROTO_UNSPEC,
285 +                            "_pdl-datastream._tcp",
286 +                            NULL, 0,
287 +                            avahi_browse_callback,
288 +                            devices);
289 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
290 +                            AVAHI_PROTO_UNSPEC,
291 +                            "_printer._tcp", NULL, 0,
292 +                            avahi_browse_callback, devices);
293 +  avahi_service_browser_new (client, AVAHI_IF_UNSPEC,
294 +                            AVAHI_PROTO_UNSPEC,
295 +                            "_riousbprint._tcp", NULL, 0,
296 +                            avahi_browse_callback, devices);
297 +#endif /* HAVE_AVAHI */
298 +#ifdef HAVE_DNSSD
299    if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
300    {
301      perror("ERROR: Unable to create service connection");
302 @@ -258,6 +448,7 @@ main(int  argc,                             /* I - Number of comm
303    riousbprint_ref = main_ref;
304    DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
305                     "_riousbprint._tcp", NULL, browse_callback, devices);
306 +#endif /* HAVE_DNSSD */
307  
308   /*
309    * Loop until we are killed...
310 @@ -265,6 +456,9 @@ main(int  argc,                             /* I - Number of comm
311  
312    while (!job_canceled)
313    {
314 +    int announce = 0;
315 +
316 +#ifdef HAVE_DNSSD
317      FD_ZERO(&input);
318      FD_SET(fd, &input);
319  
320 @@ -284,11 +478,35 @@ main(int  argc,                           /* I - Number of comm
321      }
322      else
323      {
324 +      announce = 1;
325 +    }
326 +#else /* HAVE_AVAHI */
327 +    int r;
328 +    avahi_got_callback = 0;
329 +    r = avahi_simple_poll_iterate (simple_poll, 1);
330 +    if (r != 0 && r != EINTR)
331 +    {
332 +     /*
333 +      * We've been told to exit the loop.  Perhaps the connection to
334 +      * avahi failed.
335 +      */
336 +
337 +      break;
338 +    }
339 +
340 +    if (avahi_got_callback)
341 +      announce = 1;
342 +#endif /* HAVE_DNSSD */
343 +
344 +    if (announce)
345 +    {
346       /*
347        * Announce any devices we've found...
348        */
349  
350 +#ifdef HAVE_DNSSD
351        DNSServiceErrorType status;      /* DNS query status */
352 +#endif /* HAVE_DNSSD */
353        cups_device_t *best;             /* Best matching device */
354        char     device_uri[1024];       /* Device URI */
355        int      count;                  /* Number of queries */
356 @@ -302,6 +520,7 @@ main(int  argc,                             /* I - Number of comm
357          if (device->sent)
358           sent ++;
359  
360 +#ifdef HAVE_DNSSD
361          if (device->ref)
362           count ++;
363  
364 @@ -333,14 +552,23 @@ main(int  argc,                           /* I - Number of comm
365               count ++;
366            }
367         }
368 -       else if (!device->sent)
369 +       else
370 +#endif /* HAVE_DNSSD */
371 +#ifdef HAVE_AVAHI
372 +       if (!device->resolved)
373 +         continue;
374 +        else
375 +#endif /* HAVE_AVAHI */
376 +       if (!device->sent)
377         {
378 +#ifdef HAVE_DNSSD
379          /*
380           * Got the TXT records, now report the device...
381           */
382  
383           DNSServiceRefDeallocate(device->ref);
384           device->ref = 0;
385 +#endif /* HAVE_DNSSD */
386  
387            if (!best)
388             best = device;
389 @@ -401,6 +629,7 @@ main(int  argc,                             /* I - Number of comm
390  }
391  
392  
393 +#ifdef HAVE_DNSSD
394  /*
395   * 'browse_callback()' - Browse devices.
396   */
397 @@ -489,6 +718,7 @@ browse_local_callback(
398           device->fullName);
399    device->sent = 1;
400  }
401 +#endif /* HAVE_DNSSD */
402  
403  
404  /*
405 @@ -569,6 +799,41 @@ exec_backend(char **argv)          /* I - Comman
406  
407  
408  /*
409 + * 'device_type()' - Get DNS-SD type enumeration from string.
410 + */
411 +
412 +static int
413 +device_type (const char *regtype)
414 +{
415 +#ifdef HAVE_AVAHI
416 +  if (!strcmp(regtype, "_ipp._tcp"))
417 +    return (CUPS_DEVICE_IPP);
418 +  else if (!strcmp(regtype, "_ipps._tcp") ||
419 +          !strcmp(regtype, "_ipp-tls._tcp"))
420 +    return (CUPS_DEVICE_IPPS);
421 +  else if (!strcmp(regtype, "_fax-ipp._tcp"))
422 +    return (CUPS_DEVICE_FAX_IPP);
423 +  else if (!strcmp(regtype, "_printer._tcp"))
424 +    return (CUPS_DEVICE_PDL_DATASTREAM);
425 +#else
426 +  if (!strcmp(regtype, "_ipp._tcp."))
427 +    return (CUPS_DEVICE_IPP);
428 +  else if (!strcmp(regtype, "_ipps._tcp.") ||
429 +          !strcmp(regtype, "_ipp-tls._tcp."))
430 +    return (CUPS_DEVICE_IPPS);
431 +  else if (!strcmp(regtype, "_fax-ipp._tcp."))
432 +    return (CUPS_DEVICE_FAX_IPP);
433 +  else if (!strcmp(regtype, "_printer._tcp."))
434 +    return (CUPS_DEVICE_PRINTER);
435 +  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
436 +    return (CUPS_DEVICE_PDL_DATASTREAM);
437 +#endif /* HAVE_AVAHI */
438 +
439 +  return (CUPS_DEVICE_RIOUSBPRINT);
440 +}
441 +
442 +
443 +/*
444   * 'get_device()' - Create or update a device.
445   */
446  
447 @@ -589,20 +854,7 @@ get_device(cups_array_t *devices,  /* I -
448    */
449  
450    key.name = (char *)serviceName;
451 -
452 -  if (!strcmp(regtype, "_ipp._tcp."))
453 -    key.type = CUPS_DEVICE_IPP;
454 -  else if (!strcmp(regtype, "_ipps._tcp.") ||
455 -          !strcmp(regtype, "_ipp-tls._tcp."))
456 -    key.type = CUPS_DEVICE_IPPS;
457 -  else if (!strcmp(regtype, "_fax-ipp._tcp."))
458 -    key.type = CUPS_DEVICE_FAX_IPP;
459 -  else if (!strcmp(regtype, "_printer._tcp."))
460 -    key.type = CUPS_DEVICE_PRINTER;
461 -  else if (!strcmp(regtype, "_pdl-datastream._tcp."))
462 -    key.type = CUPS_DEVICE_PDL_DATASTREAM;
463 -  else
464 -    key.type = CUPS_DEVICE_RIOUSBPRINT;
465 +  key.type = device_type (regtype);
466  
467    for (device = cupsArrayFind(devices, &key);
468         device;
469 @@ -622,8 +874,14 @@ get_device(cups_array_t *devices,  /* I -
470          free(device->domain);
471         device->domain = strdup(replyDomain);
472  
473 +#ifdef HAVE_DNSSD
474         DNSServiceConstructFullName(fullName, device->name, regtype,
475                                     replyDomain);
476 +#else /* HAVE_AVAHI */
477 +       avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
478 +                                serviceName, regtype, replyDomain);
479 +#endif /* HAVE_DNSSD */
480 +
481         free(device->fullName);
482         device->fullName = strdup(fullName);
483        }
484 @@ -643,6 +901,9 @@ get_device(cups_array_t *devices,   /* I -
485    device->domain   = strdup(replyDomain);
486    device->type     = key.type;
487    device->priority = 50;
488 +#ifdef HAVE_AVAHI
489 +  device->resolved = 0;
490 +#endif /* HAVE_AVAHI */
491  
492    cupsArrayAdd(devices, device);
493  
494 @@ -650,13 +911,20 @@ get_device(cups_array_t *devices, /* I -
495    * Set the "full name" of this service, which is used for queries...
496    */
497  
498 +#ifdef HAVE_DNSSD
499    DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
500 +#else /* HAVE_AVAHI */
501 +  avahi_service_name_join (fullName, kDNSServiceMaxDomainName,
502 +                          serviceName, regtype, replyDomain);
503 +#endif /* HAVE_DNSSD */
504 +
505    device->fullName = strdup(fullName);
506  
507    return (device);
508  }
509  
510  
511 +#ifdef HAVE_DNSSD
512  /*
513   * 'query_callback()' - Process query data.
514   */
515 @@ -680,7 +948,7 @@ query_callback(
516                 *ptr;                   /* Pointer into string */
517    cups_device_t        dkey,                   /* Search key */
518                 *device;                /* Device */
519 -
520 +  cups_txt_records_t txt;
521  
522    fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
523                    "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
524 @@ -714,94 +982,233 @@ query_callback(
525    if ((ptr = strstr(name, "._")) != NULL)
526      *ptr = '\0';
527  
528 -  if (strstr(fullName, "_ipp._tcp."))
529 -    dkey.type = CUPS_DEVICE_IPP;
530 -  else if (strstr(fullName, "_ipps._tcp.") ||
531 -           strstr(fullName, "_ipp-tls._tcp."))
532 -    dkey.type = CUPS_DEVICE_IPPS;
533 -  else if (strstr(fullName, "_fax-ipp._tcp."))
534 -    dkey.type = CUPS_DEVICE_FAX_IPP;
535 -  else if (strstr(fullName, "_printer._tcp."))
536 -    dkey.type = CUPS_DEVICE_PRINTER;
537 -  else if (strstr(fullName, "_pdl-datastream._tcp."))
538 -    dkey.type = CUPS_DEVICE_PDL_DATASTREAM;
539 +  dkey.type = device_type (fullName);
540 +
541 +  txt.data = rdata;
542 +  txt.dataend = rdata + rdlen;
543 +  device = find_device ((cups_array_t *) context, &txt, &dkey);
544 +  if (!device)
545 +    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
546 +}
547 +#endif /* HAVE_DNSSD */
548 +
549 +
550 +#ifdef HAVE_AVAHI
551 +/*
552 + * 'avahi_client_callback()' - Avahi client callback function.
553 + */
554 +
555 +static void
556 +avahi_client_callback(AvahiClient *client,
557 +                     AvahiClientState state,
558 +                     void *context)
559 +{
560 + /*
561 +  * If the connection drops, quit.
562 +  */
563 +
564 +  if (state == AVAHI_CLIENT_FAILURE)
565 +  {
566 +    fprintf (stderr, "ERROR: Avahi connection failed\n");
567 +    avahi_simple_poll_quit (simple_poll);
568 +  }
569 +}
570 +
571 +
572 +/*
573 + * 'avahi_query_callback()' - Avahi query callback function.
574 + */
575 +
576 +static void
577 +avahi_query_callback(AvahiServiceResolver *resolver,
578 +                    AvahiIfIndex interface,
579 +                    AvahiProtocol protocol,
580 +                    AvahiResolverEvent event,
581 +                    const char *name,
582 +                    const char *type,
583 +                    const char *domain,
584 +                    const char *host_name,
585 +                    const AvahiAddress *address,
586 +                    uint16_t port,
587 +                    AvahiStringList *txt,
588 +                    AvahiLookupResultFlags flags,
589 +                    void *context)
590 +{
591 +  AvahiClient          *client;
592 +  cups_device_t                key,
593 +                       *device;
594 +  char                 uqname[1024],
595 +                       *ptr;
596 +  cups_txt_records_t   txtr;
597 +
598 +  client = avahi_service_resolver_get_client (resolver);
599 +  if (event != AVAHI_RESOLVER_FOUND)
600 +  {
601 +    if (event == AVAHI_RESOLVER_FAILURE)
602 +    {
603 +      fprintf (stderr, "ERROR: %s\n",
604 +              avahi_strerror (avahi_client_errno (client)));
605 +    }
606 +
607 +    avahi_service_resolver_free (resolver);
608 +    return;
609 +  }
610 +
611 + /*
612 +  * Set search key for device.
613 +  */
614 +
615 +  key.name = uqname;
616 +  unquote (uqname, name, sizeof (uqname));
617 +  if ((ptr = strstr(name, "._")) != NULL)
618 +    *ptr = '\0';
619 +
620 +  key.domain = (char *) domain;
621 +  key.type = device_type (type);
622 +
623 + /*
624 +  * Find the device and the the TXT information.
625 +  */
626 +
627 +  txtr.txt = txt;
628 +  device = find_device ((cups_array_t *) context, &txtr, &key);
629 +  if (device)
630 +  {
631 +   /*
632 +    * Let the main loop know to announce the device.
633 +    */
634 +
635 +    device->resolved = 1;
636 +    avahi_got_callback = 1;
637 +  }
638    else
639 -    dkey.type = CUPS_DEVICE_RIOUSBPRINT;
640 +    fprintf (stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", name);
641 +
642 +  avahi_service_resolver_free (resolver);
643 +}
644 +
645 +
646 +/*
647 + * 'avahi_browse_callback()' - Avahi browse callback function.
648 + */
649 +
650 +static void
651 +avahi_browse_callback(AvahiServiceBrowser *browser,
652 +                     AvahiIfIndex interface,
653 +                     AvahiProtocol protocol,
654 +                     AvahiBrowserEvent event,
655 +                     const char *name,
656 +                     const char *type,
657 +                     const char *domain,
658 +                     AvahiLookupResultFlags flags,
659 +                     void *context)
660 +{
661 +  AvahiClient *client = avahi_service_browser_get_client (browser);
662 +
663 +  switch (event)
664 +  {
665 +  case AVAHI_BROWSER_FAILURE:
666 +    fprintf (stderr, "ERROR: %s\n",
667 +            avahi_strerror (avahi_client_errno (client)));
668 +    avahi_simple_poll_quit (simple_poll);
669 +    return;
670 +
671 +  case AVAHI_BROWSER_NEW:
672 +   /*
673 +    * This object is new on the network.
674 +    */
675 +
676 +    if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
677 +    {
678 +     /*
679 +      * This comes from the local machine so ignore it.
680 +      */
681 +
682 +      fprintf (stderr, "DEBUG: ignoring local service %s\n", name);
683 +    }
684 +    else
685 +    {
686 +     /*
687 +      * Create a device entry for it if it doesn't yet exist.
688 +      */
689 +
690 +      get_device ((cups_array_t *)context, name, type, domain);
691 +
692 +     /*
693 +      * Now look for a TXT entry.
694 +      */
695 +
696 +      if (avahi_service_resolver_new (client, interface, protocol,
697 +                                     name, type, domain,
698 +                                     AVAHI_PROTO_UNSPEC, 0,
699 +                                     avahi_query_callback, context) == NULL)
700 +      {
701 +       fprintf (stderr, "ERROR: failed to resolve service %s: %s\n",
702 +                name, avahi_strerror (avahi_client_errno (client)));
703 +      }
704 +    }
705 +
706 +    break;
707 +
708 +  case AVAHI_BROWSER_REMOVE:
709 +  case AVAHI_BROWSER_ALL_FOR_NOW:
710 +  case AVAHI_BROWSER_CACHE_EXHAUSTED:
711 +    break;
712 +  }
713 +}
714 +#endif /* HAVE_AVAHI */
715 +
716  
717 -  for (device = cupsArrayFind(devices, &dkey);
718 +/*
719 + * 'find_device()' - Find a device from its name and domain.
720 + */
721 +
722 +static cups_device_t *
723 +find_device (cups_array_t *devices,
724 +            cups_txt_records_t *txt,
725 +            cups_device_t *dkey)
726 +{
727 +  cups_device_t        *device;
728 +  char         *ptr;
729 +
730 +  for (device = cupsArrayFind(devices, dkey);
731         device;
732         device = cupsArrayNext(devices))
733    {
734 -    if (_cups_strcasecmp(device->name, dkey.name) ||
735 -        _cups_strcasecmp(device->domain, dkey.domain))
736 +    if (_cups_strcasecmp(device->name, dkey->name) ||
737 +        _cups_strcasecmp(device->domain, dkey->domain))
738      {
739        device = NULL;
740        break;
741      }
742 -    else if (device->type == dkey.type)
743 +    else if (device->type == dkey->type)
744      {
745       /*
746        * Found it, pull out the priority and make and model from the TXT
747        * record and save it...
748        */
749  
750 -      const uint8_t    *data,          /* Pointer into data */
751 -                       *datanext,      /* Next key/value pair */
752 -                       *dataend;       /* End of entire TXT record */
753 -      uint8_t          datalen;        /* Length of current key/value pair */
754 -      char             key[256],       /* Key string */
755 -                       value[256],     /* Value string */
756 -                       make_and_model[512],
757 +      char             make_and_model[512],
758                                         /* Manufacturer and model */
759                         model[256],     /* Model */
760 -                       device_id[2048];/* 1284 device ID */
761 -
762 +                       device_id[2048]; /* 1284 device ID */
763  
764        device_id[0]      = '\0';
765        make_and_model[0] = '\0';
766  
767        strcpy(model, "Unknown");
768  
769 -      for (data = rdata, dataend = data + rdlen;
770 -           data < dataend;
771 -           data = datanext)
772 +      for (;;)
773        {
774 -       /*
775 -        * Read a key/value pair starting with an 8-bit length.  Since the
776 -       * length is 8 bits and the size of the key/value buffers is 256, we
777 -       * don't need to check for overflow...
778 -       */
779 -
780 -        datalen = *data++;
781 -
782 -        if (!datalen || (data + datalen) >= dataend)
783 -         break;
784 -
785 -        datanext = data + datalen;
786 -
787 -        for (ptr = key; data < datanext && *data != '='; data ++)
788 -         *ptr++ = *data;
789 -       *ptr = '\0';
790 +       char *key;
791 +       char *value;
792  
793 -       if (data < datanext && *data == '=')
794 -       {
795 -         data ++;
796 -
797 -         if (data < datanext)
798 -           memcpy(value, data, datanext - data);
799 -         value[datanext - data] = '\0';
800 +       if (parse_txt_record_pair (txt))
801 +         goto next;
802  
803 -         fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
804 -                 key, value);
805 -       }
806 -       else
807 -       {
808 -         fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
809 -                 key);
810 -         continue;
811 -       }
812 -
813 -        if (!_cups_strncasecmp(key, "usb_", 4))
814 +       key = txt->key;
815 +       value = txt->value;
816 +        if (!strncasecmp(key, "usb_", 4))
817         {
818          /*
819           * Add USB device ID information...
820 @@ -856,6 +1263,10 @@ query_callback(
821           if (device->type == CUPS_DEVICE_PRINTER)
822             device->sent = 1;
823         }
824 +
825 +      next:
826 +       if (next_txt_record (txt) == NULL)
827 +         break;
828        }
829  
830        if (device->device_id)
831 @@ -912,11 +1323,9 @@ query_callback(
832      }
833    }
834  
835 -  if (!device)
836 -    fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
837 +  return device;
838  }
839  
840 -
841  /*
842   * 'sigterm_handler()' - Handle termination signals...
843   */
844 diff -up cups-1.5.0/cups/http-support.c.avahi-2-backend cups-1.5.0/cups/http-support.c
845 --- cups-1.5.0/cups/http-support.c.avahi-2-backend      2011-06-10 23:06:26.000000000 +0100
846 +++ cups-1.5.0/cups/http-support.c      2011-08-05 15:05:13.870710117 +0100
847 @@ -43,6 +43,10 @@
848   *   http_copy_decode()   - Copy and decode a URI.
849   *   http_copy_encode()   - Copy and encode a URI.
850   *   http_resolve_cb()    - Build a device URI for the given service name.
851 + *   avahi_resolve_uri_client_cb()
852 + *                        - Avahi client callback for resolving URI.
853 + *   avahi_resolve_uri_resolver_cb()
854 + *                        - Avahi resolver callback for resolving URI.
855   */
856  
857  /*
858 @@ -60,6 +64,11 @@
859  #    include <sys/select.h>
860  #  endif /* WIN32 */
861  #endif /* HAVE_DNSSD */
862 +#ifdef HAVE_AVAHI
863 +#  include <avahi-client/client.h>
864 +#  include <avahi-client/lookup.h>
865 +#  include <avahi-common/simple-watch.h>
866 +#endif /* HAVE_AVAHI */
867  
868  
869  /*
870 @@ -127,6 +136,24 @@ static void DNSSD_API      http_resolve_cb(DN
871                                         void *context);
872  #endif /* HAVE_DNSSD */
873  
874 +#ifdef HAVE_AVAHI
875 +static void    avahi_resolve_uri_client_cb(AvahiClient *client,
876 +                                           AvahiClientState state,
877 +                                           void *simple_poll);
878 +static void    avahi_resolve_uri_resolver_cb(AvahiServiceResolver *resolver,
879 +                                             AvahiIfIndex interface,
880 +                                             AvahiProtocol protocol,
881 +                                             AvahiResolverEvent event,
882 +                                             const char *name,
883 +                                             const char *type,
884 +                                             const char *domain,
885 +                                             const char *host_name,
886 +                                             const AvahiAddress *address,
887 +                                             uint16_t port,
888 +                                             AvahiStringList *txt,
889 +                                             AvahiLookupResultFlags flags,
890 +                                             void *context);
891 +#endif /* HAVE_AVAHI */
892  
893  /*
894   * 'httpAssembleURI()' - Assemble a uniform resource identifier from its
895 @@ -1431,6 +1458,9 @@ _httpResolveURI(
896  
897    if (strstr(hostname, "._tcp"))
898    {
899 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
900 +    char               *regtype,       /* Pointer to type in hostname */
901 +                       *domain;        /* Pointer to domain in hostname */
902  #ifdef HAVE_DNSSD
903  #  ifdef WIN32
904  #    pragma comment(lib, "dnssd.lib")
905 @@ -1449,6 +1479,17 @@ _httpResolveURI(
906      fd_set             input_set;      /* Input set for select() */
907      struct timeval     stimeout;       /* Timeout value for select() */
908  #endif /* HAVE_POLL */
909 +#else /* HAVE_AVAHI */
910 +    AvahiSimplePoll    *simple_poll;
911 +    AvahiClient                *client;
912 +    int                        error;
913 +    struct
914 +    {
915 +      AvahiSimplePoll  *poll;
916 +      _http_uribuf_t   uribuf;
917 +    } user_data;
918 +#endif /* HAVE_DNSSD */
919 +
920  
921      if (options & _HTTP_RESOLVE_STDERR)
922        fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
923 @@ -1485,9 +1526,16 @@ _httpResolveURI(
924      if (domain)
925        *domain++ = '\0';
926  
927 +#ifdef HAVE_DNSSD
928      uribuf.buffer   = resolved_uri;
929      uribuf.bufsize  = resolved_size;
930      uribuf.options  = options;
931 +#else
932 +    user_data.uribuf.buffer = resolved_uri;
933 +    user_data.uribuf.bufsize = resolved_size;
934 +    user_data.uribuf.options = options;
935 +#endif
936 +
937      resolved_uri[0] = '\0';
938  
939      DEBUG_printf(("6_httpResolveURI: Resolving hostname=\"%s\", regtype=\"%s\", "
940 @@ -1501,6 +1549,7 @@ _httpResolveURI(
941  
942      uri = NULL;
943  
944 +#ifdef HAVE_DNSSD
945      if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
946      {
947        localref = ref;
948 @@ -1608,6 +1657,36 @@ _httpResolveURI(
949  
950        DNSServiceRefDeallocate(ref);
951      }
952 +#else /* HAVE_AVAHI */
953 +    if ((simple_poll = avahi_simple_poll_new ()) != NULL)
954 +    {
955 +      if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll),
956 +                                     0, avahi_resolve_uri_client_cb,
957 +                                     &simple_poll, &error)) != NULL)
958 +      {
959 +       user_data.poll = simple_poll;
960 +       if (avahi_service_resolver_new (client, AVAHI_IF_UNSPEC,
961 +                                       AVAHI_PROTO_UNSPEC, hostname,
962 +                                       regtype, domain, AVAHI_PROTO_UNSPEC, 0,
963 +                                       avahi_resolve_uri_resolver_cb,
964 +                                       &user_data) != NULL)
965 +       {
966 +         avahi_simple_poll_loop (simple_poll);
967 +
968 +        /*
969 +         * Collect the result.
970 +         */
971 +
972 +         if (resolved_uri[0])
973 +           uri = resolved_uri;
974 +       }
975 +
976 +       avahi_client_free (client);
977 +      }
978 +
979 +      avahi_simple_poll_free (simple_poll);
980 +    }
981 +#endif /* HAVE_DNSSD */
982  
983      if (options & _HTTP_RESOLVE_STDERR)
984      {
985 @@ -1619,13 +1698,13 @@ _httpResolveURI(
986        fputs("STATE: -connecting-to-device,offline-report\n", stderr);
987      }
988  
989 -#else
990 +#else /* HAVE_DNSSD || HAVE_AVAHI */
991     /*
992      * No DNS-SD support...
993      */
994  
995      uri = NULL;
996 -#endif /* HAVE_DNSSD */
997 +#endif /* HAVE_DNSSD || HAVE_AVAHI */
998  
999      if ((options & _HTTP_RESOLVE_STDERR) && !uri)
1000        _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
1001 @@ -1895,6 +1974,116 @@ http_resolve_cb(
1002  #endif /* HAVE_DNSSD */
1003  
1004  
1005 +#ifdef HAVE_AVAHI
1006 +/*
1007 + * 'avahi_resolve_uri_client_cb()' - Avahi client callback for resolving URI.
1008 + */
1009 +
1010 +static void
1011 +avahi_resolve_uri_client_cb (AvahiClient *client,
1012 +                            AvahiClientState state,
1013 +                            void *simple_poll)
1014 +{
1015 +  DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, "
1016 +               "simple_poll=%p)\n", client, state, simple_poll));
1017 +
1018 +  /*
1019 +   * If the connection drops, quit.
1020 +   */
1021 +
1022 +  if (state == AVAHI_CLIENT_FAILURE)
1023 +    avahi_simple_poll_quit (simple_poll);
1024 +}
1025 +
1026 +
1027 +/*
1028 + * 'avahi_resolve_uri_resolver_cb()' - Avahi resolver callback for resolving
1029 + *                                     URI.
1030 + */
1031 +
1032 +static void
1033 +avahi_resolve_uri_resolver_cb (AvahiServiceResolver *resolver,
1034 +                              AvahiIfIndex interface,
1035 +                              AvahiProtocol protocol,
1036 +                              AvahiResolverEvent event,
1037 +                              const char *name,
1038 +                              const char *type,
1039 +                              const char *domain,
1040 +                              const char *host_name,
1041 +                              const AvahiAddress *address,
1042 +                              uint16_t port,
1043 +                              AvahiStringList *txt,
1044 +                              AvahiLookupResultFlags flags,
1045 +                              void *context)
1046 +{
1047 +  const char           *scheme;        /* URI scheme */
1048 +  char                 rp[256];        /* Remote printer */
1049 +  AvahiStringList      *pair;
1050 +  char                 *value;
1051 +  size_t               valueLen = 0;
1052 +  char                 addr[AVAHI_ADDRESS_STR_MAX];
1053 +  struct
1054 +  {
1055 +    AvahiSimplePoll    *poll;
1056 +    _http_uribuf_t     uribuf;
1057 +  }            *poll_uribuf = context;
1058 +
1059 +  DEBUG_printf(("avahi_resolve_uri_resolver_callback(resolver=%p, "
1060 +               "interface=%d, protocol=%d, event=%d, name=\"%s\", "
1061 +               "type=\"%s\", domain=\"%s\", host_name=\"%s\", address=%p, "
1062 +               "port=%d, txt=%p, flags=%d, context=%p)\n",
1063 +               resolver, interface, protocol, event, name, type, domain,
1064 +               host_name, address, port, txt, flags, context));
1065 +
1066 +  if (event != AVAHI_RESOLVER_FOUND)
1067 +  {
1068 +    avahi_service_resolver_free (resolver);
1069 +    avahi_simple_poll_quit (poll_uribuf->poll);
1070 +    return;
1071 +  }
1072 +
1073 + /*
1074 +  * Figure out the scheme from the full name...
1075 +  */
1076 +
1077 +  if (strstr(type, "_ipp."))
1078 +    scheme = "ipp";
1079 +  else if (strstr(type, "_printer."))
1080 +    scheme = "lpd";
1081 +  else if (strstr(type, "_pdl-datastream."))
1082 +    scheme = "socket";
1083 +  else
1084 +    scheme = "riousbprint";
1085 +
1086 + /*
1087 +  * Extract the "remote printer key from the TXT record...
1088 +  */
1089 +
1090 +  if ((pair = avahi_string_list_find (txt, "rp")) != NULL)
1091 +  {
1092 +    avahi_string_list_get_pair (pair, NULL, &value, &valueLen);
1093 +    rp[0] = '/';
1094 +    memcpy (rp + 1, value, valueLen);
1095 +    rp[valueLen + 1] = '\0';
1096 +  }
1097 +  else
1098 +    rp[0] = '\0';
1099 +
1100 + /*
1101 +  * Assemble the final device URI...
1102 +  */
1103 +
1104 +  avahi_address_snprint (addr, AVAHI_ADDRESS_STR_MAX, address);
1105 +  httpAssembleURI(HTTP_URI_CODING_ALL, poll_uribuf->uribuf.buffer,
1106 +                 poll_uribuf->uribuf.bufsize, scheme, NULL,
1107 +                 addr, port, rp);
1108 +  DEBUG_printf(("avahi_resolve_uri_resolver_callback: Resolved URI is \"%s\"\n",
1109 +               poll_uribuf->uribuf.buffer));
1110 +  avahi_simple_poll_quit (poll_uribuf->poll);
1111 +}
1112 +#endif /* HAVE_AVAHI */
1113 +
1114 +
1115  /*
1116   * End of "$Id$".
1117   */
This page took 0.281546 seconds and 3 git commands to generate.