+
+static void
+http_resolve_cb(
+ AvahiServiceResolver *resolver, /* I - Resolver (unused) */
+ AvahiIfIndex interface, /* I - Interface index (unused) */
+ AvahiProtocol protocol, /* I - Network protocol (unused) */
+ AvahiResolverEvent event, /* I - Event (found, etc.) */
+ const char *name, /* I - Service name */
+ const char *type, /* I - Registration type */
+ const char *domain, /* I - Domain (unused) */
+ const char *hostTarget, /* I - Hostname */
+ const AvahiAddress *address, /* I - Address (unused) */
+ uint16_t port, /* I - Port number */
+ AvahiStringList *txt, /* I - TXT record */
+ AvahiLookupResultFlags flags, /* I - Lookup flags (unused) */
+ void *context) /* I - Pointer to URI buffer */
+{
+ _http_uribuf_t *uribuf = (_http_uribuf_t *)context;
+ /* URI buffer */
+ const char *scheme, /* URI scheme */
+ *hostptr, /* Pointer into hostTarget */
+ *reskey, /* "rp" or "rfo" */
+ *resdefault; /* Default path */
+ char resource[257], /* Remote path */
+ fqdn[256]; /* FQDN of the .local name */
+ AvahiStringList *pair; /* Current TXT record key/value pair */
+ char *value; /* Value for "rp" key */
+ size_t valueLen = 0; /* Length of "rp" key */
+
+
+ DEBUG_printf(("4http_resolve_cb(resolver=%p, "
+ "interface=%d, protocol=%d, event=%d, name=\"%s\", "
+ "type=\"%s\", domain=\"%s\", hostTarget=\"%s\", address=%p, "
+ "port=%d, txt=%p, flags=%d, context=%p)",
+ resolver, interface, protocol, event, name, type, domain,
+ hostTarget, address, port, txt, flags, context));
+
+ if (event != AVAHI_RESOLVER_FOUND)
+ {
+ avahi_service_resolver_free(resolver);
+ avahi_simple_poll_quit(uribuf->poll);
+ return;
+ }
+
+ /*
+ * If we have a UUID, compare it...
+ */
+
+ if (uribuf->uuid && (pair = avahi_string_list_find(txt, "UUID")) != NULL)
+ {
+ char uuid[256]; /* UUID value */
+
+ avahi_string_list_get_pair(pair, NULL, &value, &valueLen);
+
+ memcpy(uuid, value, valueLen);
+ uuid[valueLen] = '\0';
+
+ if (_cups_strcasecmp(uuid, uribuf->uuid))
+ {
+ if (uribuf->options & _HTTP_RESOLVE_STDERR)
+ fprintf(stderr, "DEBUG: Found UUID %s, looking for %s.", uuid,
+ uribuf->uuid);
+
+ DEBUG_printf(("5http_resolve_cb: Found UUID %s, looking for %s.", uuid,
+ uribuf->uuid));
+ return;
+ }
+ }
+
+ /*
+ * Figure out the scheme from the full name...
+ */
+
+ if (strstr(type, "_ipp."))
+ scheme = "ipp";
+ else if (strstr(type, "_printer."))
+ scheme = "lpd";
+ else if (strstr(type, "_pdl-datastream."))
+ scheme = "socket";
+ else
+ scheme = "riousbprint";
+
+ if (!strncmp(type, "_ipps.", 6) || !strncmp(type, "_ipp-tls.", 9))
+ scheme = "ipps";
+ else if (!strncmp(type, "_ipp.", 5) || !strncmp(type, "_fax-ipp.", 9))
+ scheme = "ipp";
+ else if (!strncmp(type, "_http.", 6))
+ scheme = "http";
+ else if (!strncmp(type, "_https.", 7))
+ scheme = "https";
+ else if (!strncmp(type, "_printer.", 9))
+ scheme = "lpd";
+ else if (!strncmp(type, "_pdl-datastream.", 16))
+ scheme = "socket";
+ else
+ {
+ avahi_service_resolver_free(resolver);
+ avahi_simple_poll_quit(uribuf->poll);
+ return;
+ }
+
+ /*
+ * Extract the remote resource key from the TXT record...
+ */
+
+ if ((uribuf->options & _HTTP_RESOLVE_FAXOUT) &&
+ (!strcmp(scheme, "ipp") || !strcmp(scheme, "ipps")) &&
+ !avahi_string_list_find(txt, "printer-type"))
+ {
+ reskey = "rfo";
+ resdefault = "/ipp/faxout";
+ }
+ else
+ {
+ reskey = "rp";
+ resdefault = "/";
+ }
+
+ if ((pair = avahi_string_list_find(txt, reskey)) != NULL)
+ {
+ avahi_string_list_get_pair(pair, NULL, &value, &valueLen);
+
+ if (value[0] == '/')
+ {
+ /*
+ * Value (incorrectly) has a leading slash already...
+ */
+
+ memcpy(resource, value, valueLen);
+ resource[valueLen] = '\0';
+ }
+ else
+ {
+ /*
+ * Convert to resource by concatenating with a leading "/"...
+ */
+
+ resource[0] = '/';
+ memcpy(resource + 1, value, valueLen);
+ resource[valueLen + 1] = '\0';
+ }
+ }
+ else
+ {
+ /*
+ * Use the default value...
+ */
+
+ strlcpy(resource, resdefault, sizeof(resource));
+ }
+
+ /*
+ * Lookup the FQDN if needed...
+ */
+
+ if ((uribuf->options & _HTTP_RESOLVE_FQDN) &&
+ (hostptr = hostTarget + strlen(hostTarget) - 6) > hostTarget &&
+ !_cups_strcasecmp(hostptr, ".local"))
+ {
+ /*
+ * OK, we got a .local name but the caller needs a real domain. Start by
+ * getting the IP address of the .local name and then do reverse-lookups...
+ */
+
+ http_addrlist_t *addrlist, /* List of addresses */
+ *addr; /* Current address */
+
+ DEBUG_printf(("5http_resolve_cb: Looking up \"%s\".", hostTarget));
+
+ snprintf(fqdn, sizeof(fqdn), "%d", ntohs(port));
+ if ((addrlist = httpAddrGetList(hostTarget, AF_UNSPEC, fqdn)) != NULL)
+ {
+ for (addr = addrlist; addr; addr = addr->next)
+ {
+ int error = getnameinfo(&(addr->addr.addr), (socklen_t)httpAddrLength(&(addr->addr)), fqdn, sizeof(fqdn), NULL, 0, NI_NAMEREQD);
+
+ if (!error)
+ {
+ DEBUG_printf(("5http_resolve_cb: Found \"%s\".", fqdn));
+
+ if ((hostptr = fqdn + strlen(fqdn) - 6) <= fqdn ||
+ _cups_strcasecmp(hostptr, ".local"))
+ {
+ hostTarget = fqdn;
+ break;
+ }
+ }
+#ifdef DEBUG
+ else
+ DEBUG_printf(("5http_resolve_cb: \"%s\" did not resolve: %d",
+ httpAddrString(&(addr->addr), fqdn, sizeof(fqdn)),
+ error));
+#endif /* DEBUG */
+ }
+
+ httpAddrFreeList(addrlist);
+ }
+ }
+
+ /*
+ * Assemble the final device URI using the resolved hostname...
+ */
+
+ httpAssembleURI(HTTP_URI_CODING_ALL, uribuf->buffer, (int)uribuf->bufsize, scheme,
+ NULL, hostTarget, port, resource);
+ DEBUG_printf(("5http_resolve_cb: Resolved URI is \"%s\".", uribuf->buffer));
+
+ avahi_simple_poll_quit(uribuf->poll);
+}
+#endif /* HAVE_DNSSD */