Home | History | Annotate | Download | only in patches
      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