]> git.meshlink.io Git - catta/blob - avahi-core/resolve-address.c
Make AVAHI_PROTO_xxx well defined constants
[catta] / avahi-core / resolve-address.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <avahi-common/timeval.h>
27 #include <avahi-common/malloc.h>
28 #include <avahi-common/error.h>
29
30 #include "browse.h"
31
32 #define TIMEOUT_MSEC 1000
33
34 struct AvahiSAddressResolver {
35     AvahiServer *server;
36     AvahiAddress address;
37     
38     AvahiSRecordBrowser *record_browser;
39
40     AvahiSAddressResolverCallback callback;
41     void* userdata;
42
43     AvahiRecord *ptr_record;
44     AvahiIfIndex interface;
45     AvahiProtocol protocol;
46
47     AvahiTimeEvent *time_event;
48
49     AVAHI_LLIST_FIELDS(AvahiSAddressResolver, resolver);
50 };
51
52 static void finish(AvahiSAddressResolver *r, AvahiResolverEvent event) {
53     assert(r);
54     
55     if (r->time_event) {
56         avahi_time_event_free(r->time_event);
57         r->time_event = NULL;
58     }
59
60     if (event == AVAHI_RESOLVER_TIMEOUT)
61         r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_TIMEOUT, &r->address, NULL, r->userdata);
62     else {
63
64         assert(event == AVAHI_RESOLVER_FOUND);
65         assert(r->ptr_record);
66
67         r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_FOUND, &r->address, r->ptr_record->data.ptr.name, r->userdata);
68     }
69 }
70
71 static void time_event_callback(AvahiTimeEvent *e, void *userdata) {
72     AvahiSAddressResolver *r = userdata;
73     
74     assert(e);
75     assert(r);
76
77     finish(r, AVAHI_RESOLVER_TIMEOUT);
78 }
79
80 static void start_timeout(AvahiSAddressResolver *r) {
81     struct timeval tv;
82     assert(r);
83
84     if (r->time_event)
85         return;
86
87     avahi_elapse_time(&tv, TIMEOUT_MSEC, 0);
88     r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);
89 }
90
91 static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) {
92     AvahiSAddressResolver *r = userdata;
93
94     assert(rr);
95     assert(record);
96     assert(r);
97
98     assert(record->key->type == AVAHI_DNS_TYPE_PTR);
99
100     if (event == AVAHI_BROWSER_NEW) {
101
102         if (r->interface > 0 && interface != r->interface)
103             return;
104         
105         if (r->protocol != AVAHI_PROTO_UNSPEC && protocol != r->protocol)
106             return;
107         
108         if (r->interface <= 0)
109             r->interface = interface;
110         
111         if (r->protocol == AVAHI_PROTO_UNSPEC)
112             r->protocol = protocol;
113         
114         if (!r->ptr_record) {
115             r->ptr_record = avahi_record_ref(record);
116
117             finish(r, AVAHI_RESOLVER_FOUND);
118         }
119
120     } else {
121         
122         assert(event == AVAHI_BROWSER_REMOVE);
123         
124         if (r->ptr_record && avahi_record_equal_no_ttl(record, r->ptr_record)) {
125             avahi_record_unref(r->ptr_record);
126             r->ptr_record = NULL;
127
128             /** Look for a replacement */
129             avahi_s_record_browser_restart(r->record_browser);
130             start_timeout(r);
131         }
132     }
133 }
134
135 AvahiSAddressResolver *avahi_s_address_resolver_new(AvahiServer *server, AvahiIfIndex interface, AvahiProtocol protocol, const AvahiAddress *address, AvahiSAddressResolverCallback callback, void* userdata) {
136     AvahiSAddressResolver *r;
137     AvahiKey *k;
138     char *n;
139
140     assert(server);
141     assert(address);
142     assert(callback);
143
144     assert(address->proto == AVAHI_PROTO_INET || address->proto == AVAHI_PROTO_INET6);
145
146     if (address->proto == AVAHI_PROTO_INET)
147         n = avahi_reverse_lookup_name_ipv4(&address->data.ipv4);
148     else 
149         n = avahi_reverse_lookup_name_ipv6_arpa(&address->data.ipv6);
150
151     if (!n) {
152         avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
153         return NULL;
154     }
155
156     k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
157     avahi_free(n);
158
159     if (!k) {
160         avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
161         return NULL;
162     }
163
164     if (!(r = avahi_new(AvahiSAddressResolver, 1))) {
165         avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
166         avahi_key_unref(k);
167         return NULL;
168     }
169     
170     r->server = server;
171     r->address = *address;
172     r->callback = callback;
173     r->userdata = userdata;
174     r->ptr_record = NULL;
175     r->interface = interface;
176     r->protocol = protocol;
177
178     r->record_browser = NULL;
179     AVAHI_LLIST_PREPEND(AvahiSAddressResolver, resolver, server->address_resolvers, r);
180
181     r->time_event = NULL;
182     start_timeout(r);
183     
184     r->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
185     avahi_key_unref(k);
186
187     if (!r->record_browser) {
188         avahi_s_address_resolver_free(r);
189         return NULL;
190     }
191     
192     return r;
193 }
194
195 void avahi_s_address_resolver_free(AvahiSAddressResolver *r) {
196     assert(r);
197
198     AVAHI_LLIST_REMOVE(AvahiSAddressResolver, resolver, r->server->address_resolvers, r);
199
200     if (r->record_browser)
201         avahi_s_record_browser_free(r->record_browser);
202
203     if (r->time_event)
204         avahi_time_event_free(r->time_event);
205
206     if (r->ptr_record)
207         avahi_record_unref(r->ptr_record);
208     
209     avahi_free(r);
210 }