1 --- /usr/tmp/clean/avahi-0.6.28/avahi-core/resolve-service.c 2010-08-26 01:51:38.991153000 +0100
2 +++ avahi-0.6.28/avahi-core/resolve-service.c 2011-01-20 12:36:38.289095469 +0000
8 +#include <netinet/in.h> /* for ntohs */
11 #include <avahi-common/domain.h>
12 #include <avahi-common/timeval.h>
13 #include <avahi-common/malloc.h>
16 AvahiTimeEvent *time_event;
20 + AvahiTimeEvent *defer_time_event;
23 + AvahiWatch *watch_a;
24 + AvahiWatch *watch_a6;
25 + DNSServiceRef client;
26 + DNSServiceRef client_a;
27 + DNSServiceRef client_a6;
30 AVAHI_LLIST_FIELDS(AvahiSServiceResolver, resolver);
35 +static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event ) {
36 + AvahiLookupResultFlags flags;
40 + if (r->time_event) {
41 + avahi_time_event_free(r->time_event);
42 + r->time_event = NULL;
48 + case AVAHI_RESOLVER_FAILURE:
65 + case AVAHI_RESOLVER_FOUND: {
68 + if (r->address_record) {
69 + switch (r->address_record->key->type) {
70 + case AVAHI_DNS_TYPE_A:
71 + a.proto = AVAHI_PROTO_INET;
72 + a.data.ipv4 = r->address_record->data.a.address;
75 + case AVAHI_DNS_TYPE_AAAA:
76 + a.proto = AVAHI_PROTO_INET6;
77 + a.data.ipv6 = r->address_record->data.aaaa.address;
86 + if (avahi_domain_equal(r->server->host_name_fqdn, r->host))
87 + flags |= AVAHI_LOOKUP_RESULT_LOCAL;
96 + r->address_record ? &a : NULL,
98 + r->txt_record ? r->txt_record->data.txt.string_list : NULL,
106 +static void query_record(DNSServiceRef sdRef, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
107 + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
109 + AvahiSServiceResolver *r = context;
110 + const unsigned char *rd = rdata;
114 + if (r->interface > 0 && ifIndex != r->interface)
116 + if (r->interface <= 0)
117 + r->interface = ifIndex;
120 + case kDNSServiceType_A:
121 + if (!r->address_record) {
122 + if (!(r->address_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, ttl))) {
123 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
124 + finish(r, AVAHI_RESOLVER_FAILURE);
127 + if (avahi_rdata_parse(r->address_record, rdata, rdlen) != 0) {
128 + avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
129 + finish(r, AVAHI_RESOLVER_FAILURE);
132 + if (r->protocol == AVAHI_PROTO_UNSPEC)
133 + r->protocol = AVAHI_PROTO_INET;
137 + case kDNSServiceType_A6:
138 + if (!r->address_record) {
139 + if (!(r->address_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, ttl))) {
140 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
141 + finish(r, AVAHI_RESOLVER_FAILURE);
144 + if (avahi_rdata_parse(r->address_record, rdata, rdlen) != 0) {
145 + avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
146 + finish(r, AVAHI_RESOLVER_FAILURE);
149 + if (r->protocol == AVAHI_PROTO_UNSPEC)
150 + r->protocol = AVAHI_PROTO_INET6;
159 + (r->txt_record || (r->user_flags & AVAHI_LOOKUP_NO_TXT)) &&
160 + r->address_record || (r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
161 + finish(r, AVAHI_RESOLVER_FOUND);
165 +static void resolve_socket_event(AvahiWatch *w, int fd, AvahiWatchEvent events, void *userdata) {
166 + AvahiSServiceResolver *r = userdata;
167 + DNSServiceErrorType ret;
168 + DNSServiceRef client;
172 + assert(events & AVAHI_WATCH_IN);
174 + if (fd == DNSServiceRefSockFD(r->client))
175 + client = r->client;
176 + else if (fd == DNSServiceRefSockFD(r->client_a))
177 + client = r->client_a;
178 + else if (fd == DNSServiceRefSockFD(r->client_a6))
179 + client = r->client_a6;
183 + ret = DNSServiceProcessResult(client);
184 + if (ret != kDNSServiceErr_NoError) {
185 + if (client == r->client) {
187 + r->server->poll_api->watch_free(r->watch);
190 + DNSServiceRefDeallocate(r->client);
192 + } else if (client == r->client_a) {
194 + r->server->poll_api->watch_free(r->watch_a);
197 + DNSServiceRefDeallocate(r->client_a);
198 + r->client_a = NULL;
199 + } else if (client == r->client_a6) {
201 + r->server->poll_api->watch_free(r->watch_a6);
202 + r->watch_a6 = NULL;
204 + DNSServiceRefDeallocate(r->client_a6);
205 + r->client_a6 = NULL;
207 + avahi_server_set_errno(r->server, AVAHI_ERR_DISCONNECTED);
208 + finish(r, AVAHI_RESOLVER_FAILURE);
212 +static void resolve_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode,
213 + const char *fullname, const char *host, uint16_t opaqueport, uint16_t txtlen, const char* txtrecord, void *context) {
214 + AvahiSServiceResolver *r = context;
215 + AvahiServer *s = r->server;
216 + DNSServiceErrorType ret;
217 + DNSServiceRef new_client;
219 + if (r->interface > 0 && ifIndex != r->interface)
221 + if (r->interface <= 0)
222 + r->interface = ifIndex;
225 + if (!(r->host = avahi_strdup(host))) {
226 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
227 + finish(r, AVAHI_RESOLVER_FAILURE);
230 + if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
231 + if (!r->txt_record) {
232 + if (!(r->txt_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, AVAHI_DEFAULT_TTL))) {
233 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY);
234 + finish(r, AVAHI_RESOLVER_FAILURE);
238 + if (avahi_rdata_parse(r->txt_record, txtrecord, txtlen) != 0) {
239 + avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET);
240 + finish(r, AVAHI_RESOLVER_FAILURE);
243 + r->port = ntohs(opaqueport);
244 + if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) {
245 + if (r->address_protocol == AVAHI_PROTO_INET || r->address_protocol == AVAHI_PROTO_UNSPEC) {
248 + r->server->poll_api->watch_free(r->watch_a);
251 + DNSServiceRefDeallocate(r->client_a);
252 + r->client_a = NULL;
254 + ret = DNSServiceQueryRecord(&r->client_a, 0, ifIndex, host, kDNSServiceType_A, kDNSServiceClass_IN, query_record, r);
255 + if (ret != kDNSServiceErr_NoError || !r->client_a) {
256 + finish(r, AVAHI_RESOLVER_FAILURE);
259 + r->watch_a = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a), AVAHI_WATCH_IN, resolve_socket_event, r);
262 + if (r->address_protocol == AVAHI_PROTO_INET6 || r->address_protocol == AVAHI_PROTO_UNSPEC) {
263 + if (r->client_a6) {
265 + r->server->poll_api->watch_free(r->watch_a6);
266 + r->watch_a6 = NULL;
268 + DNSServiceRefDeallocate(r->client_a6);
269 + r->client_a6 = NULL;
271 + ret = DNSServiceQueryRecord(&r->client_a6, 0, ifIndex, host, kDNSServiceType_A6, kDNSServiceClass_IN, query_record, r);
272 + if (ret != kDNSServiceErr_NoError || !r->client_a6) {
273 + finish(r, AVAHI_RESOLVER_FAILURE);
276 + r->watch_a6 = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a6), AVAHI_WATCH_IN, resolve_socket_event, r);
279 + finish(r, AVAHI_RESOLVER_FOUND);
283 +static void resolve_error_callback(AvahiTimeEvent *e, void *userdata) {
284 + AvahiSServiceResolver *r = userdata;
286 + if (r->defer_time_event) {
287 + avahi_time_event_free(r->defer_time_event);
288 + r->defer_time_event = NULL;
290 + avahi_server_set_errno(r->server, AVAHI_ERR_FAILURE);
291 + finish(r, AVAHI_RESOLVER_FAILURE);
294 +static void avahi_resolve_service_start(AvahiServer *s, AvahiSServiceResolver *r) {
295 + DNSServiceErrorType ret;
297 + ret = DNSServiceResolve(&r->client,
299 + r->interface == AVAHI_IF_UNSPEC ?
300 + kDNSServiceInterfaceIndexAny :
307 + if (ret != kDNSServiceErr_NoError || !r->client) {
308 + r->defer_time_event = avahi_time_event_new(r->server->time_event_queue, NULL, resolve_error_callback, r);
310 + r->watch = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client), AVAHI_WATCH_IN, resolve_socket_event, r);
315 static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event) {
316 AvahiLookupResultFlags flags;
324 static void time_event_callback(AvahiTimeEvent *e, void *userdata) {
325 AvahiSServiceResolver *r = userdata;
327 r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);
330 +#ifndef HAVE_BONJOUR
331 static void record_browser_callback(
332 AvahiSRecordBrowser*rr,
333 AvahiIfIndex interface,
340 AvahiSServiceResolver *avahi_s_service_resolver_new(
343 r->time_event = NULL;
344 AVAHI_LLIST_PREPEND(AvahiSServiceResolver, resolver, server->service_resolvers, r);
347 + r->defer_time_event = NULL;
351 + r->watch_a6 = NULL;
353 + r->client_a = NULL;
354 + r->client_a6 = NULL;
355 + avahi_resolve_service_start(server, r);
357 k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
358 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);
369 if (r->address_record)
370 avahi_record_unref(r->address_record);
373 + if (r->defer_time_event) {
374 + avahi_time_event_free(r->defer_time_event);
375 + r->defer_time_event = NULL;
379 + avahi_free(r->host);
382 + r->server->poll_api->watch_free(r->watch);
384 + r->server->poll_api->watch_free(r->watch_a);
386 + r->server->poll_api->watch_free(r->watch_a6);
389 + DNSServiceRefDeallocate (r->client);
391 + DNSServiceRefDeallocate (r->client_a);
393 + DNSServiceRefDeallocate (r->client_a6);
395 avahi_free(r->service_name);
396 avahi_free(r->service_type);
397 avahi_free(r->domain_name);