dnsquery: added option to resolve DNS A records
[siplcs.git] / src / purple / purple-dnsquery.c
blob02d16d0599888b4ca4b4d6fca4d28a047c6446a9
1 /**
2 * @file purple-dnsquery.c
4 * pidgin-sipe
6 * Copyright (C) 2010 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 #ifdef _WIN32
24 #include <ws2tcpip.h>
25 #else
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
28 #endif
30 #include "glib.h"
32 #include "dnsquery.h"
33 #include "dnssrv.h"
35 #include "sipe-backend.h"
37 struct sipe_dns_query {
38 enum {
40 SRV
41 } type;
42 sipe_dns_resolved_cb callback;
43 gpointer extradata;
44 gpointer purple_query_data;
47 static void dns_a_response(GSList *hosts,
48 struct sipe_dns_query *query,
49 const char *error_message)
51 char ipstr[INET6_ADDRSTRLEN];
52 struct sockaddr *addr;
53 const void *addrdata;
54 int port;
56 if (error_message || !g_slist_next(hosts)) {
57 query->callback(query->extradata, NULL, 0);
58 g_slist_free(hosts);
59 return;
62 addr = g_slist_next(hosts)->data;
63 if (addr->sa_family == AF_INET6) {
64 addrdata = &((struct sockaddr_in6 *) addr)->sin6_addr;
65 port = ((struct sockaddr_in6 *) addr)->sin6_port;
66 } else {
67 addrdata = &((struct sockaddr_in *) addr)->sin_addr;
68 port = ((struct sockaddr_in *) addr)->sin_port;
71 inet_ntop(addr->sa_family, addrdata, ipstr, sizeof (ipstr));
73 query->callback(query->extradata, ipstr, port);
75 for (; hosts; hosts = g_slist_delete_link(hosts, hosts)) {
76 // Free the addrlen, no data in this link
77 hosts = g_slist_delete_link(hosts, hosts);
78 // Free the address
79 g_free(hosts->data);
82 g_free(query);
85 struct sipe_dns_query *sipe_backend_dns_query_a(const gchar *hostname,
86 int port,
87 sipe_dns_resolved_cb callback,
88 gpointer data)
90 struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);
91 query->type = A;
92 query->callback = callback;
93 query->extradata = data;
94 query->purple_query_data = purple_dnsquery_a(hostname,
95 port,
96 (PurpleDnsQueryConnectFunction) dns_a_response,
97 query);
99 return query;
103 static void dns_srv_response(PurpleSrvResponse *resp,
104 int results,
105 struct sipe_dns_query *query)
107 if (results)
108 query->callback(query->extradata, resp->hostname, resp->port);
109 else
110 query->callback(query->extradata, NULL, 0);
112 g_free(query);
113 g_free(resp);
116 struct sipe_dns_query *sipe_backend_dns_query_srv(const gchar *protocol,
117 const gchar *transport,
118 const gchar *domain,
119 sipe_dns_resolved_cb callback,
120 gpointer data)
122 struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1);
123 query->type = SRV;
124 query->callback = callback;
125 query->extradata = data;
126 query->purple_query_data = purple_srv_resolve(protocol,
127 transport,
128 domain,
129 (PurpleSrvCallback) dns_srv_response,
130 query);
132 return query;
135 void sipe_backend_dns_query_cancel(struct sipe_dns_query *query)
137 switch (query->type) {
138 case A:
139 purple_dnsquery_destroy(query->purple_query_data);
140 break;
141 case SRV:
142 purple_srv_cancel(query->purple_query_data);
143 break;
146 g_free(query);
150 Local Variables:
151 mode: c
152 c-file-style: "bsd"
153 indent-tabs-mode: t
154 tab-width: 8
155 End: