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