AvahiSHostNameResolver *avahi_s_host_name_resolver_prepare(
    AvahiServer *server,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    const char *host_name,
    AvahiProtocol aprotocol,
    AvahiLookupFlags flags,
    AvahiSHostNameResolverCallback callback,
    void* userdata) {

    AvahiSHostNameResolver *r;
    AvahiKey *k;

    assert(server);
    assert(host_name);
    assert(callback);

    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_is_valid_fqdn(host_name), AVAHI_ERR_INVALID_HOST_NAME);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(aprotocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);

    if (!(r = avahi_new(AvahiSHostNameResolver, 1))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        return NULL;
    }

    r->server = server;
    r->host_name = avahi_normalize_name_strdup(host_name);
    r->callback = callback;
    r->userdata = userdata;
    r->address_record = NULL;
    r->interface = interface;
    r->protocol = protocol;
    r->flags = 0;

    r->record_browser_a = r->record_browser_aaaa = NULL;

    r->time_event = NULL;

    AVAHI_LLIST_PREPEND(AvahiSHostNameResolver, resolver, server->host_name_resolvers, r);

    r->record_browser_aaaa = r->record_browser_a = NULL;

    if (aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_UNSPEC) {
        k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
        r->record_browser_a = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);
        avahi_key_unref(k);

        if (!r->record_browser_a)
            goto fail;
    }

    if (aprotocol == AVAHI_PROTO_INET6 || aprotocol == AVAHI_PROTO_UNSPEC) {
        k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA);
        r->record_browser_aaaa = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);
        avahi_key_unref(k);

        if (!r->record_browser_aaaa)
            goto fail;
    }

    assert(r->record_browser_aaaa || r->record_browser_a);

    start_timeout(r);

    return r;

fail:
    avahi_s_host_name_resolver_free(r);
    return NULL;
}
AvahiSHostNameResolver *avahi_s_host_name_resolver_prepare(
    AvahiServer *server,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    const char *host_name,
    AvahiProtocol aprotocol,
    AvahiLookupFlags flags,
    AvahiSHostNameResolverCallback callback,
    void* userdata) {

    AvahiSHostNameResolver *r;
    AvahiKey *k;

    assert(server);
    assert(host_name);
    assert(callback);

    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_is_valid_fqdn(host_name), AVAHI_ERR_INVALID_HOST_NAME);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(aprotocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);

    if (!(r = avahi_new(AvahiSHostNameResolver, 1))) {
        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
        return NULL;
    }

    r->server = server;
    r->host_name = avahi_normalize_name_strdup(host_name);
    r->callback = callback;
    r->userdata = userdata;
    r->address_record = NULL;
    r->interface = interface;
    r->protocol = protocol;
    r->flags = 0;

    r->record_browser_a = r->record_browser_aaaa = NULL;

    r->time_event = NULL;

    AVAHI_LLIST_PREPEND(AvahiSHostNameResolver, resolver, server->host_name_resolvers, r);

    r->record_browser_aaaa = r->record_browser_a = NULL;

    if (aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_UNSPEC) {
        k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
        r->record_browser_a = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);
        avahi_key_unref(k);

        if (!r->record_browser_a)
            goto fail;
    }

    if (aprotocol == AVAHI_PROTO_INET6 || aprotocol == AVAHI_PROTO_UNSPEC) {
        k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA);
        r->record_browser_aaaa = avahi_s_record_browser_prepare(server, interface, protocol, k, flags, record_browser_callback, r);
        avahi_key_unref(k);

        if (!r->record_browser_aaaa)
            goto fail;
    }

    assert(r->record_browser_aaaa || r->record_browser_a);

    start_timeout(r);

    return r;

fail:
    avahi_s_host_name_resolver_free(r);
    return NULL;
}