avahi-05-resolve-service.diff revision 10786
10786N/A--- /usr/tmp/clean/avahi-0.6.12/avahi-core/resolve-service.c 2006-04-01 01:48:59.000000000 +0100
10786N/A+++ avahi-0.6.12/avahi-core/resolve-service.c 2006-08-28 14:40:21.749772000 +0100
10786N/A@@ -27,6 +27,10 @@
10786N/A #include <stdio.h>
10786N/A #include <stdlib.h>
10786N/A
10786N/A+#ifdef HAVE_BONJOUR
10786N/A+#include <netinet/in.h> /* for ntohs */
10786N/A+#endif
10786N/A+
10786N/A #include <avahi-common/domain.h>
10786N/A #include <avahi-common/timeval.h>
10786N/A #include <avahi-common/malloc.h>
10786N/A@@ -61,9 +65,302 @@
10786N/A
10786N/A AvahiTimeEvent *time_event;
10786N/A
10786N/A+#ifdef HAVE_BONJOUR
10786N/A+ uint16_t port;
10786N/A+ AvahiTimeEvent *defer_time_event;
10786N/A+ char *host;
10786N/A+ AvahiWatch *watch;
10786N/A+ AvahiWatch *watch_a;
10786N/A+ AvahiWatch *watch_a6;
10786N/A+ DNSServiceRef client;
10786N/A+ DNSServiceRef client_a;
10786N/A+ DNSServiceRef client_a6;
10786N/A+#endif
10786N/A+
10786N/A AVAHI_LLIST_FIELDS(AvahiSServiceResolver, resolver);
10786N/A };
10786N/A
10786N/A+
10786N/A+#ifdef HAVE_BONJOUR
10786N/A+static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event ) {
10786N/A+ AvahiLookupResultFlags flags;
10786N/A+
10786N/A+ assert(r);
10786N/A+
10786N/A+ if (r->time_event) {
10786N/A+ avahi_time_event_free(r->time_event);
10786N/A+ r->time_event = NULL;
10786N/A+ }
10786N/A+
10786N/A+ flags = 0;
10786N/A+
10786N/A+ switch (event) {
10786N/A+ case AVAHI_RESOLVER_FAILURE:
10786N/A+
10786N/A+ r->callback(r,
10786N/A+ r->interface,
10786N/A+ r->protocol,
10786N/A+ event,
10786N/A+ r->service_name,
10786N/A+ r->service_type,
10786N/A+ r->domain_name,
10786N/A+ NULL,
10786N/A+ NULL,
10786N/A+ 0,
10786N/A+ NULL,
10786N/A+ flags,
10786N/A+ r->userdata);
10786N/A+ break;
10786N/A+
10786N/A+ case AVAHI_RESOLVER_FOUND: {
10786N/A+ AvahiAddress a;
10786N/A+
10786N/A+ if (r->address_record) {
10786N/A+ switch (r->address_record->key->type) {
10786N/A+ case AVAHI_DNS_TYPE_A:
10786N/A+ a.proto = AVAHI_PROTO_INET;
10786N/A+ a.data.ipv4 = r->address_record->data.a.address;
10786N/A+ break;
10786N/A+
10786N/A+ case AVAHI_DNS_TYPE_AAAA:
10786N/A+ a.proto = AVAHI_PROTO_INET6;
10786N/A+ a.data.ipv6 = r->address_record->data.aaaa.address;
10786N/A+ break;
10786N/A+
10786N/A+ default:
10786N/A+ assert(0);
10786N/A+ }
10786N/A+ }
10786N/A+
10786N/A+ flags = 0;
10786N/A+ if (avahi_domain_equal(r->server->host_name_fqdn, r->host))
10786N/A+ flags |= AVAHI_LOOKUP_RESULT_LOCAL;
10786N/A+ r->callback(r,
10786N/A+ r->interface,
10786N/A+ r->protocol,
10786N/A+ event,
10786N/A+ r->service_name,
10786N/A+ r->service_type,
10786N/A+ r->domain_name,
10786N/A+ r->host,
10786N/A+ r->address_record ? &a : NULL,
10786N/A+ r->port,
10786N/A+ r->txt_record ? r->txt_record->data.txt.string_list : NULL,
10786N/A+ flags,
10786N/A+ r->userdata);
10786N/A+ break;
10786N/A+ }
10786N/A+ }
10786N/A+}
10786N/A+
10786N/A+static void query_record(DNSServiceRef sdRef, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
10786N/A+ const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
10786N/A+{
10786N/A+ AvahiSServiceResolver *r = context;
10786N/A+ const unsigned char *rd = rdata;
10786N/A+ AvahiAddress a;
10786N/A+ int changed = 0;
10786N/A+
10786N/A+ if (r->interface > 0 && ifIndex != r->interface)
10786N/A+ return;
10786N/A+ if (r->interface <= 0)
10786N/A+ r->interface = ifIndex;
10786N/A+
10786N/A+ switch (rrtype) {
10786N/A+ case kDNSServiceType_A:
10786N/A+ if (!r->address_record) {
10786N/A+ if (!(r->address_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, ttl))) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ return;
10786N/A+ }
10786N/A+ if (avahi_rdata_parse(r->address_record, rdata, rdlen) != 0) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ }
10786N/A+ changed = 1;
10786N/A+ if (r->protocol == AVAHI_PROTO_UNSPEC)
10786N/A+ r->protocol = AVAHI_PROTO_INET;
10786N/A+ }
10786N/A+ break;
10786N/A+
10786N/A+ case kDNSServiceType_A6:
10786N/A+ if (!r->address_record) {
10786N/A+ if (!(r->address_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, ttl))) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ return;
10786N/A+ }
10786N/A+ if (avahi_rdata_parse(r->address_record, rdata, rdlen) != 0) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ }
10786N/A+ changed = 1;
10786N/A+ if (r->protocol == AVAHI_PROTO_UNSPEC)
10786N/A+ r->protocol = AVAHI_PROTO_INET6;
10786N/A+ }
10786N/A+ break;
10786N/A+ default:
10786N/A+ abort();
10786N/A+ }
10786N/A+
10786N/A+ if (changed &&
10786N/A+ (r->txt_record || (r->user_flags & AVAHI_LOOKUP_NO_TXT)) &&
10786N/A+ r->address_record || (r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
10786N/A+ finish(r, AVAHI_RESOLVER_FOUND);
10786N/A+ }
10786N/A+}
10786N/A+
10786N/A+static void resolve_socket_event(AvahiWatch *w, int fd, AvahiWatchEvent events, void *userdata) {
10786N/A+ AvahiSServiceResolver *r = userdata;
10786N/A+ DNSServiceErrorType ret;
10786N/A+ DNSServiceRef client;
10786N/A+
10786N/A+ assert(w);
10786N/A+ assert(fd >= 0);
10786N/A+ assert(events & AVAHI_WATCH_IN);
10786N/A+
10786N/A+ if (fd == DNSServiceRefSockFD(r->client))
10786N/A+ client = r->client;
10786N/A+ else if (fd == DNSServiceRefSockFD(r->client_a))
10786N/A+ client = r->client_a;
10786N/A+ else if (fd == DNSServiceRefSockFD(r->client_a6))
10786N/A+ client = r->client_a6;
10786N/A+ else
10786N/A+ assert (0);
10786N/A+
10786N/A+ ret = DNSServiceProcessResult(client);
10786N/A+ if (ret != kDNSServiceErr_NoError) {
10786N/A+ if (client == r->client) {
10786N/A+ if (r->watch) {
10786N/A+ r->server->poll_api->watch_free(r->watch);
10786N/A+ r->watch = NULL;
10786N/A+ }
10786N/A+ DNSServiceRefDeallocate(r->client);
10786N/A+ r->client = NULL;
10786N/A+ } else if (client == r->client_a) {
10786N/A+ if (r->watch_a) {
10786N/A+ r->server->poll_api->watch_free(r->watch_a);
10786N/A+ r->watch_a = NULL;
10786N/A+ }
10786N/A+ DNSServiceRefDeallocate(r->client_a);
10786N/A+ r->client_a = NULL;
10786N/A+ } else if (client == r->client_a6) {
10786N/A+ if (r->watch_a6) {
10786N/A+ r->server->poll_api->watch_free(r->watch_a6);
10786N/A+ r->watch_a6 = NULL;
10786N/A+ }
10786N/A+ DNSServiceRefDeallocate(r->client_a6);
10786N/A+ r->client_a6 = NULL;
10786N/A+ }
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_DISCONNECTED);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ }
10786N/A+}
10786N/A+
10786N/A+static void resolve_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
10786N/A+ const char *fullname, const char *host, uint16_t opaqueport, uint16_t txtlen, const char* txtrecord, void *context) {
10786N/A+ AvahiSServiceResolver *r = context;
10786N/A+ AvahiServer *s = r->server;
10786N/A+ DNSServiceErrorType ret;
10786N/A+ DNSServiceRef new_client;
10786N/A+
10786N/A+ if (r->interface > 0 && ifIndex != r->interface)
10786N/A+ return;
10786N/A+ if (r->interface <= 0)
10786N/A+ r->interface = ifIndex;
10786N/A+
10786N/A+ if (host) {
10786N/A+ if (!(r->host = avahi_strdup(host))) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ }
10786N/A+ }
10786N/A+ if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
10786N/A+ if (!r->txt_record) {
10786N/A+ if (!(r->txt_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, AVAHI_DEFAULT_TTL))) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ return;
10786N/A+ }
10786N/A+ }
10786N/A+ if (avahi_rdata_parse(r->txt_record, txtrecord, txtlen) != 0) {
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ }
10786N/A+ }
10786N/A+ r->port = ntohs(opaqueport);
10786N/A+ if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
10786N/A+ if (r->address_protocol == AVAHI_PROTO_INET || r->address_protocol == AVAHI_PROTO_UNSPEC) {
10786N/A+ if (r->client_a) {
10786N/A+ if (r->watch_a) {
10786N/A+ r->server->poll_api->watch_free(r->watch_a);
10786N/A+ r->watch_a = NULL;
10786N/A+ }
10786N/A+ DNSServiceRefDeallocate(r->client_a);
10786N/A+ r->client_a = NULL;
10786N/A+ }
10786N/A+ ret = DNSServiceQueryRecord(&r->client_a, 0, ifIndex, host, kDNSServiceType_A, kDNSServiceClass_IN, query_record, r);
10786N/A+ if (ret != kDNSServiceErr_NoError || !r->client_a) {
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ return;
10786N/A+ }
10786N/A+ r->watch_a = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a), AVAHI_WATCH_IN, resolve_socket_event, r);
10786N/A+ }
10786N/A+
10786N/A+ if (r->address_protocol == AVAHI_PROTO_INET6 || r->address_protocol == AVAHI_PROTO_UNSPEC) {
10786N/A+ if (r->client_a6) {
10786N/A+ if (r->watch_a6) {
10786N/A+ r->server->poll_api->watch_free(r->watch_a6);
10786N/A+ r->watch_a6 = NULL;
10786N/A+ }
10786N/A+ DNSServiceRefDeallocate(r->client_a6);
10786N/A+ r->client_a6 = NULL;
10786N/A+ }
10786N/A+ ret = DNSServiceQueryRecord(&r->client_a6, 0, ifIndex, host, kDNSServiceType_A6, kDNSServiceClass_IN, query_record, r);
10786N/A+ if (ret != kDNSServiceErr_NoError || !r->client_a6) {
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+ return;
10786N/A+ }
10786N/A+ r->watch_a6 = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a6), AVAHI_WATCH_IN, resolve_socket_event, r);
10786N/A+ }
10786N/A+ } else {
10786N/A+ finish(r, AVAHI_RESOLVER_FOUND);
10786N/A+ }
10786N/A+}
10786N/A+
10786N/A+static void resolve_error_callback(AvahiTimeEvent *e, void *userdata) {
10786N/A+ AvahiSServiceResolver *r = userdata;
10786N/A+
10786N/A+ if (r->defer_time_event) {
10786N/A+ avahi_time_event_free(r->defer_time_event);
10786N/A+ r->defer_time_event = NULL;
10786N/A+ }
10786N/A+ avahi_server_set_errno(r->server, AVAHI_ERR_FAILURE);
10786N/A+ finish(r, AVAHI_RESOLVER_FAILURE);
10786N/A+}
10786N/A+
10786N/A+static void avahi_resolve_service_start(AvahiServer *s, AvahiSServiceResolver *r) {
10786N/A+ DNSServiceErrorType ret;
10786N/A+
10786N/A+ ret = DNSServiceResolve(&r->client,
10786N/A+ 0,
10786N/A+ r->interface == AVAHI_IF_UNSPEC ?
10786N/A+ kDNSServiceInterfaceIndexAny :
10786N/A+ r->interface,
10786N/A+ r->service_name,
10786N/A+ r->service_type,
10786N/A+ r->domain_name,
10786N/A+ resolve_reply,
10786N/A+ r);
10786N/A+ if (ret != kDNSServiceErr_NoError || !r->client) {
10786N/A+ r->defer_time_event = avahi_time_event_new(r->server->time_event_queue, NULL, resolve_error_callback, r);
10786N/A+ } else {
10786N/A+ r->watch = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client), AVAHI_WATCH_IN, resolve_socket_event, r);
10786N/A+ }
10786N/A+}
10786N/A+#else
10786N/A+
10786N/A static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event) {
10786N/A AvahiLookupResultFlags flags;
10786N/A
10786N/A@@ -142,6 +439,7 @@
10786N/A }
10786N/A }
10786N/A }
10786N/A+#endif
10786N/A
10786N/A static void time_event_callback(AvahiTimeEvent *e, void *userdata) {
10786N/A AvahiSServiceResolver *r = userdata;
10786N/A@@ -165,6 +463,7 @@
10786N/A r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);
10786N/A }
10786N/A
10786N/A+#ifndef HAVE_BONJOUR
10786N/A static void record_browser_callback(
10786N/A AvahiSRecordBrowser*rr,
10786N/A AvahiIfIndex interface,
10786N/A@@ -376,6 +675,7 @@
10786N/A break;
10786N/A }
10786N/A }
10786N/A+#endif
10786N/A
10786N/A AvahiSServiceResolver *avahi_s_service_resolver_new(
10786N/A AvahiServer *server,
10786N/A@@ -435,6 +735,17 @@
10786N/A r->time_event = NULL;
10786N/A AVAHI_LLIST_PREPEND(AvahiSServiceResolver, resolver, server->service_resolvers, r);
10786N/A
10786N/A+#ifdef HAVE_BONJOUR
10786N/A+ r->defer_time_event = NULL;
10786N/A+ r->host = NULL;
10786N/A+ r->watch = NULL;
10786N/A+ r->watch_a = NULL;
10786N/A+ r->watch_a6 = NULL;
10786N/A+ r->client = NULL;
10786N/A+ r->client_a = NULL;
10786N/A+ r->client_a6 = NULL;
10786N/A+ avahi_resolve_service_start(server, r);
10786N/A+#else
10786N/A k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
10786N/A r->record_browser_srv = avahi_s_record_browser_new(server, interface, protocol, k, flags & ~(AVAHI_LOOKUP_NO_TXT|AVAHI_LOOKUP_NO_ADDRESS), record_browser_callback, r);
10786N/A avahi_key_unref(k);
10786N/A@@ -454,6 +765,7 @@
10786N/A return NULL;
10786N/A }
10786N/A }
10786N/A+#endif
10786N/A
10786N/A start_timeout(r);
10786N/A
10786N/A@@ -484,6 +796,29 @@
10786N/A if (r->address_record)
10786N/A avahi_record_unref(r->address_record);
10786N/A
10786N/A+#ifdef HAVE_BONJOUR
10786N/A+ if (r->defer_time_event) {
10786N/A+ avahi_time_event_free(r->defer_time_event);
10786N/A+ r->defer_time_event = NULL;
10786N/A+ }
10786N/A+
10786N/A+ if (r->host)
10786N/A+ avahi_free(r->host);
10786N/A+
10786N/A+ if (r->watch)
10786N/A+ r->server->poll_api->watch_free(r->watch);
10786N/A+ if (r->watch_a)
10786N/A+ r->server->poll_api->watch_free(r->watch_a);
10786N/A+ if (r->watch_a6)
10786N/A+ r->server->poll_api->watch_free(r->watch_a6);
10786N/A+
10786N/A+ if (r->client)
10786N/A+ DNSServiceRefDeallocate (r->client);
10786N/A+ if (r->client_a)
10786N/A+ DNSServiceRefDeallocate (r->client_a);
10786N/A+ if (r->client_a6)
10786N/A+ DNSServiceRefDeallocate (r->client_a6);
10786N/A+#endif
10786N/A avahi_free(r->service_name);
10786N/A avahi_free(r->service_type);
10786N/A avahi_free(r->domain_name);