1 --- /usr/tmp/clean/avahi-0.6.12/avahi-core/resolve-service.c 2006-04-01 01:48:59.000000000 +0100 2 +++ avahi-0.6.12/avahi-core/resolve-service.c 2006-08-28 14:40:21.749772000 +0100 3 @@ -27,6 +27,10 @@ 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 +#ifdef HAVE_BONJOUR 8 +#include <netinet/in.h> /* for ntohs */ 9 +#endif 10 + 11 #include <avahi-common/domain.h> 12 #include <avahi-common/timeval.h> 13 #include <avahi-common/malloc.h> 14 @@ -61,9 +65,302 @@ 15 16 AvahiTimeEvent *time_event; 17 18 +#ifdef HAVE_BONJOUR 19 + uint16_t port; 20 + AvahiTimeEvent *defer_time_event; 21 + char *host; 22 + AvahiWatch *watch; 23 + AvahiWatch *watch_a; 24 + AvahiWatch *watch_a6; 25 + DNSServiceRef client; 26 + DNSServiceRef client_a; 27 + DNSServiceRef client_a6; 28 +#endif 29 + 30 AVAHI_LLIST_FIELDS(AvahiSServiceResolver, resolver); 31 }; 32 33 + 34 +#ifdef HAVE_BONJOUR 35 +static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event ) { 36 + AvahiLookupResultFlags flags; 37 + 38 + assert(r); 39 + 40 + if (r->time_event) { 41 + avahi_time_event_free(r->time_event); 42 + r->time_event = NULL; 43 + } 44 + 45 + flags = 0; 46 + 47 + switch (event) { 48 + case AVAHI_RESOLVER_FAILURE: 49 + 50 + r->callback(r, 51 + r->interface, 52 + r->protocol, 53 + event, 54 + r->service_name, 55 + r->service_type, 56 + r->domain_name, 57 + NULL, 58 + NULL, 59 + 0, 60 + NULL, 61 + flags, 62 + r->userdata); 63 + break; 64 + 65 + case AVAHI_RESOLVER_FOUND: { 66 + AvahiAddress a; 67 + 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; 73 + break; 74 + 75 + case AVAHI_DNS_TYPE_AAAA: 76 + a.proto = AVAHI_PROTO_INET6; 77 + a.data.ipv6 = r->address_record->data.aaaa.address; 78 + break; 79 + 80 + default: 81 + assert(0); 82 + } 83 + } 84 + 85 + flags = 0; 86 + if (avahi_domain_equal(r->server->host_name_fqdn, r->host)) 87 + flags |= AVAHI_LOOKUP_RESULT_LOCAL; 88 + r->callback(r, 89 + r->interface, 90 + r->protocol, 91 + event, 92 + r->service_name, 93 + r->service_type, 94 + r->domain_name, 95 + r->host, 96 + r->address_record ? &a : NULL, 97 + r->port, 98 + r->txt_record ? r->txt_record->data.txt.string_list : NULL, 99 + flags, 100 + r->userdata); 101 + break; 102 + } 103 + } 104 +} 105 + 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) 108 +{ 109 + AvahiSServiceResolver *r = context; 110 + const unsigned char *rd = rdata; 111 + AvahiAddress a; 112 + int changed = 0; 113 + 114 + if (r->interface > 0 && ifIndex != r->interface) 115 + return; 116 + if (r->interface <= 0) 117 + r->interface = ifIndex; 118 + 119 + switch (rrtype) { 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); 125 + return; 126 + } 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); 130 + } 131 + changed = 1; 132 + if (r->protocol == AVAHI_PROTO_UNSPEC) 133 + r->protocol = AVAHI_PROTO_INET; 134 + } 135 + break; 136 + 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); 142 + return; 143 + } 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); 147 + } 148 + changed = 1; 149 + if (r->protocol == AVAHI_PROTO_UNSPEC) 150 + r->protocol = AVAHI_PROTO_INET6; 151 + } 152 + break; 153 + default: 154 + abort(); 155 + } 156 + 157 + if (changed && 158 + (r->txt_record || (r->user_flags & AVAHI_LOOKUP_NO_TXT)) && 159 + r->address_record || (r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) { 160 + finish(r, AVAHI_RESOLVER_FOUND); 161 + } 162 +} 163 + 164 +static void resolve_socket_event(AvahiWatch *w, int fd, AvahiWatchEvent events, void *userdata) { 165 + AvahiSServiceResolver *r = userdata; 166 + DNSServiceErrorType ret; 167 + DNSServiceRef client; 168 + 169 + assert(w); 170 + assert(fd >= 0); 171 + assert(events & AVAHI_WATCH_IN); 172 + 173 + if (fd == DNSServiceRefSockFD(r->client)) 174 + client = r->client; 175 + else if (fd == DNSServiceRefSockFD(r->client_a)) 176 + client = r->client_a; 177 + else if (fd == DNSServiceRefSockFD(r->client_a6)) 178 + client = r->client_a6; 179 + else 180 + assert (0); 181 + 182 + ret = DNSServiceProcessResult(client); 183 + if (ret != kDNSServiceErr_NoError) { 184 + if (client == r->client) { 185 + if (r->watch) { 186 + r->server->poll_api->watch_free(r->watch); 187 + r->watch = NULL; 188 + } 189 + DNSServiceRefDeallocate(r->client); 190 + r->client = NULL; 191 + } else if (client == r->client_a) { 192 + if (r->watch_a) { 193 + r->server->poll_api->watch_free(r->watch_a); 194 + r->watch_a = NULL; 195 + } 196 + DNSServiceRefDeallocate(r->client_a); 197 + r->client_a = NULL; 198 + } else if (client == r->client_a6) { 199 + if (r->watch_a6) { 200 + r->server->poll_api->watch_free(r->watch_a6); 201 + r->watch_a6 = NULL; 202 + } 203 + DNSServiceRefDeallocate(r->client_a6); 204 + r->client_a6 = NULL; 205 + } 206 + avahi_server_set_errno(r->server, AVAHI_ERR_DISCONNECTED); 207 + finish(r, AVAHI_RESOLVER_FAILURE); 208 + } 209 +} 210 + 211 +static void resolve_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, 212 + const char *fullname, const char *host, uint16_t opaqueport, uint16_t txtlen, const char* txtrecord, void *context) { 213 + AvahiSServiceResolver *r = context; 214 + AvahiServer *s = r->server; 215 + DNSServiceErrorType ret; 216 + DNSServiceRef new_client; 217 + 218 + if (r->interface > 0 && ifIndex != r->interface) 219 + return; 220 + if (r->interface <= 0) 221 + r->interface = ifIndex; 222 + 223 + if (host) { 224 + if (!(r->host = avahi_strdup(host))) { 225 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY); 226 + finish(r, AVAHI_RESOLVER_FAILURE); 227 + } 228 + } 229 + if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) { 230 + if (!r->txt_record) { 231 + if (!(r->txt_record = avahi_record_new_full(r->host, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, AVAHI_DEFAULT_TTL))) { 232 + avahi_server_set_errno(r->server, AVAHI_ERR_NO_MEMORY); 233 + finish(r, AVAHI_RESOLVER_FAILURE); 234 + return; 235 + } 236 + } 237 + if (avahi_rdata_parse(r->txt_record, txtrecord, txtlen) != 0) { 238 + avahi_server_set_errno(r->server, AVAHI_ERR_INVALID_PACKET); 239 + finish(r, AVAHI_RESOLVER_FAILURE); 240 + } 241 + } 242 + r->port = ntohs(opaqueport); 243 + if (!(r->user_flags & AVAHI_LOOKUP_NO_ADDRESS)) { 244 + if (r->address_protocol == AVAHI_PROTO_INET || r->address_protocol == AVAHI_PROTO_UNSPEC) { 245 + if (r->client_a) { 246 + if (r->watch_a) { 247 + r->server->poll_api->watch_free(r->watch_a); 248 + r->watch_a = NULL; 249 + } 250 + DNSServiceRefDeallocate(r->client_a); 251 + r->client_a = NULL; 252 + } 253 + ret = DNSServiceQueryRecord(&r->client_a, 0, ifIndex, host, kDNSServiceType_A, kDNSServiceClass_IN, query_record, r); 254 + if (ret != kDNSServiceErr_NoError || !r->client_a) { 255 + finish(r, AVAHI_RESOLVER_FAILURE); 256 + return; 257 + } 258 + r->watch_a = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a), AVAHI_WATCH_IN, resolve_socket_event, r); 259 + } 260 + 261 + if (r->address_protocol == AVAHI_PROTO_INET6 || r->address_protocol == AVAHI_PROTO_UNSPEC) { 262 + if (r->client_a6) { 263 + if (r->watch_a6) { 264 + r->server->poll_api->watch_free(r->watch_a6); 265 + r->watch_a6 = NULL; 266 + } 267 + DNSServiceRefDeallocate(r->client_a6); 268 + r->client_a6 = NULL; 269 + } 270 + ret = DNSServiceQueryRecord(&r->client_a6, 0, ifIndex, host, kDNSServiceType_A6, kDNSServiceClass_IN, query_record, r); 271 + if (ret != kDNSServiceErr_NoError || !r->client_a6) { 272 + finish(r, AVAHI_RESOLVER_FAILURE); 273 + return; 274 + } 275 + r->watch_a6 = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client_a6), AVAHI_WATCH_IN, resolve_socket_event, r); 276 + } 277 + } else { 278 + finish(r, AVAHI_RESOLVER_FOUND); 279 + } 280 +} 281 + 282 +static void resolve_error_callback(AvahiTimeEvent *e, void *userdata) { 283 + AvahiSServiceResolver *r = userdata; 284 + 285 + if (r->defer_time_event) { 286 + avahi_time_event_free(r->defer_time_event); 287 + r->defer_time_event = NULL; 288 + } 289 + avahi_server_set_errno(r->server, AVAHI_ERR_FAILURE); 290 + finish(r, AVAHI_RESOLVER_FAILURE); 291 +} 292 + 293 +static void avahi_resolve_service_start(AvahiServer *s, AvahiSServiceResolver *r) { 294 + DNSServiceErrorType ret; 295 + 296 + ret = DNSServiceResolve(&r->client, 297 + 0, 298 + r->interface == AVAHI_IF_UNSPEC ? 299 + kDNSServiceInterfaceIndexAny : 300 + r->interface, 301 + r->service_name, 302 + r->service_type, 303 + r->domain_name, 304 + resolve_reply, 305 + r); 306 + if (ret != kDNSServiceErr_NoError || !r->client) { 307 + r->defer_time_event = avahi_time_event_new(r->server->time_event_queue, NULL, resolve_error_callback, r); 308 + } else { 309 + r->watch = s->poll_api->watch_new(s->poll_api, DNSServiceRefSockFD(r->client), AVAHI_WATCH_IN, resolve_socket_event, r); 310 + } 311 +} 312 +#else 313 + 314 static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event) { 315 AvahiLookupResultFlags flags; 316 317 @@ -142,6 +439,7 @@ 318 } 319 } 320 } 321 +#endif 322 323 static void time_event_callback(AvahiTimeEvent *e, void *userdata) { 324 AvahiSServiceResolver *r = userdata; 325 @@ -165,6 +463,7 @@ 326 r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r); 327 } 328 329 +#ifndef HAVE_BONJOUR 330 static void record_browser_callback( 331 AvahiSRecordBrowser*rr, 332 AvahiIfIndex interface, 333 @@ -376,6 +675,7 @@ 334 break; 335 } 336 } 337 +#endif 338 339 AvahiSServiceResolver *avahi_s_service_resolver_new( 340 AvahiServer *server, 341 @@ -435,6 +735,17 @@ 342 r->time_event = NULL; 343 AVAHI_LLIST_PREPEND(AvahiSServiceResolver, resolver, server->service_resolvers, r); 344 345 +#ifdef HAVE_BONJOUR 346 + r->defer_time_event = NULL; 347 + r->host = NULL; 348 + r->watch = NULL; 349 + r->watch_a = NULL; 350 + r->watch_a6 = NULL; 351 + r->client = NULL; 352 + r->client_a = NULL; 353 + r->client_a6 = NULL; 354 + avahi_resolve_service_start(server, r); 355 +#else 356 k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV); 357 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); 358 avahi_key_unref(k); 359 @@ -454,6 +765,7 @@ 360 return NULL; 361 } 362 } 363 +#endif 364 365 start_timeout(r); 366 367 @@ -484,6 +796,29 @@ 368 if (r->address_record) 369 avahi_record_unref(r->address_record); 370 371 +#ifdef HAVE_BONJOUR 372 + if (r->defer_time_event) { 373 + avahi_time_event_free(r->defer_time_event); 374 + r->defer_time_event = NULL; 375 + } 376 + 377 + if (r->host) 378 + avahi_free(r->host); 379 + 380 + if (r->watch) 381 + r->server->poll_api->watch_free(r->watch); 382 + if (r->watch_a) 383 + r->server->poll_api->watch_free(r->watch_a); 384 + if (r->watch_a6) 385 + r->server->poll_api->watch_free(r->watch_a6); 386 + 387 + if (r->client) 388 + DNSServiceRefDeallocate (r->client); 389 + if (r->client_a) 390 + DNSServiceRefDeallocate (r->client_a); 391 + if (r->client_a6) 392 + DNSServiceRefDeallocate (r->client_a6); 393 +#endif 394 avahi_free(r->service_name); 395 avahi_free(r->service_type); 396 avahi_free(r->domain_name); 397