adium: clean up paths in xcconfigs
[siplcs.git] / src / purple / purple-dnsquery.c
blob1e3724a16188dc60a1f5e711880e942c658bc01a
1 /**
2 * @file purple-dnsquery.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <glib.h>
25 #include "version.h"
27 #if PURPLE_VERSION_CHECK(3,0,0)
28 #include "protocols.h"
29 #include <gio/gio.h>
30 #else
32 #ifdef _WIN32
33 /* wrappers for write() & friends for socket handling */
34 #include "win32/win32dep.h"
35 #include <ws2tcpip.h>
36 #else
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #endif
43 #include "dnsquery.h"
44 #include "dnssrv.h"
46 #endif
48 #include "sipe-backend.h"
49 #include "sipe-core.h"
51 #include "purple-private.h"
53 struct sipe_dns_query {
54 struct sipe_backend_private *purple_private;
55 sipe_dns_resolved_cb callback;
56 gpointer extradata;
57 gpointer purple_query_data;
58 gboolean is_valid;
59 #if PURPLE_VERSION_CHECK(3,0,0)
60 guint port;
61 #else
62 enum {
64 SRV
65 } type;
66 #endif
69 static void sipe_dns_query_free(struct sipe_dns_query *query)
71 #if PURPLE_VERSION_CHECK(3,0,0)
72 g_object_unref(query->purple_query_data);
73 #endif
74 g_free(query);
77 #if PURPLE_VERSION_CHECK(3,0,0)
78 static void dns_a_response(GObject *source,
79 GAsyncResult *res,
80 gpointer user_data)
82 struct sipe_dns_query *query = user_data;
83 GList *hosts;
84 GError *error = NULL;
85 gchar *address_str = NULL;
87 if (!query->is_valid) {
88 /* Ignore spurious responses after disconnect */
89 return;
92 query->purple_private->dns_queries =
93 g_slist_remove(query->purple_private->dns_queries,
94 query);
96 hosts = g_resolver_lookup_by_name_finish(G_RESOLVER(source), res,
97 &error);
99 if (!error && g_list_length(hosts) > 0) {
100 address_str = g_inet_address_to_string(hosts->data);
103 query->callback(query->extradata, address_str,
104 address_str ? query->port : 0);
106 g_free(address_str);
107 if (error)
108 g_error_free(error);
109 g_resolver_free_addresses(hosts);
110 sipe_dns_query_free(query);
112 #else
113 static void dns_a_response(GSList *hosts,
114 struct sipe_dns_query *query,
115 const char *error_message)
117 char ipstr[INET6_ADDRSTRLEN];
118 struct sockaddr *addr;
119 const void *addrdata;
120 int port;
122 /* Ignore spurious responses after disconnect */
123 if (query->is_valid) {
124 struct sipe_backend_private *purple_private = query->purple_private;
126 purple_private->dns_queries = g_slist_remove(purple_private->dns_queries,
127 query);
129 if (error_message || !g_slist_next(hosts)) {
130 query->callback(query->extradata, NULL, 0);
131 g_slist_free(hosts);
132 return;
135 addr = g_slist_next(hosts)->data;
136 if (addr->sa_family == AF_INET6) {
137 /* OS provides addr so it must be properly aligned */
138 struct sockaddr_in6 *sin6 = (void *) addr;
139 addrdata = &sin6->sin6_addr;
140 port = sin6->sin6_port;
141 } else {
142 /* OS provides addr so it must be properly aligned */
143 struct sockaddr_in *sin = (void *) addr;
144 addrdata = &sin->sin_addr;
145 port = sin->sin_port;
148 inet_ntop(addr->sa_family, addrdata, ipstr, sizeof (ipstr));
150 query->callback(query->extradata, ipstr, port);
152 g_free(query);
155 for (; hosts; hosts = g_slist_delete_link(hosts, hosts)) {
156 // Free the addrlen, no data in this link
157 hosts = g_slist_delete_link(hosts, hosts);
158 // Free the address
159 g_free(hosts->data);
162 #endif
164 struct sipe_dns_query *sipe_backend_dns_query_a(struct sipe_core_public *sipe_public,
165 const gchar *hostname,
166 guint port,
167 sipe_dns_resolved_cb callback,
168 gpointer data)
170 struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);
171 struct sipe_backend_private *purple_private = sipe_public->backend_private;
172 #if PURPLE_VERSION_CHECK(3,0,0)
173 GResolver *resolver = g_resolver_get_default();
174 #endif
176 query->purple_private = purple_private;
177 query->callback = callback;
178 query->extradata = data;
179 query->is_valid = TRUE;
181 purple_private->dns_queries = g_slist_prepend(purple_private->dns_queries,
182 query);
184 #if PURPLE_VERSION_CHECK(3,0,0)
185 query->port = port;
186 query->purple_query_data = g_cancellable_new();
188 g_resolver_lookup_by_name_async(resolver,
189 hostname,
190 query->purple_query_data,
191 dns_a_response,
192 query);
193 g_object_unref(resolver);
194 #else
195 query->type = A;
196 query->purple_query_data =
197 #if PURPLE_VERSION_CHECK(2,8,0)
198 purple_dnsquery_a_account(
199 purple_private->account,
200 #else
201 purple_dnsquery_a(
202 #endif
203 hostname,
204 port,
205 (PurpleDnsQueryConnectFunction) dns_a_response,
206 query);
207 #endif
209 return query;
212 #if PURPLE_VERSION_CHECK(3,0,0)
213 static void dns_srv_response(GObject *source,
214 GAsyncResult *res,
215 gpointer user_data)
217 struct sipe_dns_query *query = user_data;
218 GError *error = NULL;
219 GList *targets;
221 if (!query->is_valid) {
222 /* Ignore spurious responses after disconnect */
223 return;
226 query->purple_private->dns_queries =
227 g_slist_remove(query->purple_private->dns_queries,
228 query);
230 targets = g_resolver_lookup_service_finish(G_RESOLVER(source), res,
231 &error);
233 if (error || g_list_length(targets) == 0) {
234 query->callback(query->extradata, NULL, 0);
235 } else {
236 query->callback(query->extradata,
237 g_srv_target_get_hostname(targets->data),
238 g_srv_target_get_port(targets->data));
241 if (error)
242 g_error_free(error);
243 g_resolver_free_targets(targets);
244 sipe_dns_query_free(query);
246 #else
247 static void dns_srv_response(PurpleSrvResponse *resp,
248 int results,
249 struct sipe_dns_query *query)
251 /* Ignore spurious responses after disconnect */
252 if (query->is_valid) {
253 struct sipe_backend_private *purple_private = query->purple_private;
255 purple_private->dns_queries = g_slist_remove(purple_private->dns_queries,
256 query);
258 if (results)
259 query->callback(query->extradata, resp->hostname, resp->port);
260 else
261 query->callback(query->extradata, NULL, 0);
263 g_free(query);
266 g_free(resp);
268 #endif
270 struct sipe_dns_query *sipe_backend_dns_query_srv(struct sipe_core_public *sipe_public,
271 const gchar *protocol,
272 const gchar *transport,
273 const gchar *domain,
274 sipe_dns_resolved_cb callback,
275 gpointer data)
277 struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);
278 struct sipe_backend_private *purple_private = sipe_public->backend_private;
279 #if PURPLE_VERSION_CHECK(3,0,0)
280 GResolver *resolver = g_resolver_get_default();
281 #endif
283 query->purple_private = purple_private;
284 query->callback = callback;
285 query->extradata = data;
286 query->is_valid = TRUE;
288 purple_private->dns_queries = g_slist_prepend(purple_private->dns_queries,
289 query);
291 #if PURPLE_VERSION_CHECK(3,0,0)
292 query->purple_query_data = g_cancellable_new();
294 g_resolver_lookup_service_async(resolver,
295 protocol,
296 transport,
297 domain,
298 query->purple_query_data,
299 dns_srv_response,
300 query);
301 g_object_unref(resolver);
302 #else
303 query->type = SRV;
304 query->purple_query_data =
305 #if PURPLE_VERSION_CHECK(2,8,0)
306 purple_srv_resolve_account(
307 purple_private->account,
308 #else
309 purple_srv_resolve(
310 #endif
311 protocol,
312 transport,
313 domain,
314 (PurpleSrvCallback) dns_srv_response,
315 query);
316 #endif
318 return query;
321 static gboolean dns_query_deferred_destroy(gpointer user_data)
324 * All pending events on query have been processed.
325 * Now it is safe to destroy the data structure.
327 SIPE_DEBUG_INFO("dns_query_deferred_destroy: %p", user_data);
328 sipe_dns_query_free(user_data);
329 return(FALSE);
332 void sipe_backend_dns_query_cancel(struct sipe_dns_query *query)
334 SIPE_DEBUG_INFO("sipe_backend_dns_query_cancel: %p", query);
336 if (query->is_valid) {
337 struct sipe_backend_private *purple_private = query->purple_private;
338 purple_private->dns_queries = g_slist_remove(purple_private->dns_queries,
339 query);
341 #if PURPLE_VERSION_CHECK(3,0,0)
342 g_cancellable_cancel(query->purple_query_data);
343 #else
344 switch (query->type) {
345 case A:
346 purple_dnsquery_destroy(query->purple_query_data);
347 break;
348 case SRV:
349 #if PURPLE_VERSION_CHECK(2,8,0)
350 purple_srv_txt_query_destroy(query->purple_query_data);
351 #else
352 purple_srv_cancel(query->purple_query_data);
353 #endif
354 break;
356 #endif
358 /* defer deletion of query data structure to idle callback */
359 query->is_valid = FALSE;
360 g_idle_add(dns_query_deferred_destroy, query);
364 void sipe_purple_dns_query_cancel_all(struct sipe_backend_private *purple_private)
366 GSList *entry;
367 SIPE_DEBUG_INFO_NOFORMAT("sipe_purple_dns_query_cancel_all: entered");
368 while ((entry = purple_private->dns_queries) != NULL)
369 sipe_backend_dns_query_cancel(entry->data);
374 Local Variables:
375 mode: c
376 c-file-style: "bsd"
377 indent-tabs-mode: t
378 tab-width: 8
379 End: