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