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