3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * Rewritten from scratch during Google Summer of Code 2012
8 * by Tomek Wasilczyk (http://www.wasilczyk.pl).
10 * Previously implemented by:
11 * - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001);
12 * - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005;
13 * - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011).
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
34 #include "resolver-purple.h"
38 static int ggp_resolver_purple_start(int *fd
, void **private_data
,
39 const char *hostname
);
41 static void ggp_resolver_purple_cleanup(void **private_data
, int force
);
43 static void ggp_resolver_purple_cb(GObject
*sender
, GAsyncResult
*res
, gpointer data
);
47 GCancellable
*cancellable
;
51 * pipes[0] - for reading
52 * pipes[1] - for writing
55 } ggp_resolver_purple_data
;
58 extern void ggp_resolver_purple_setup(void)
60 if (gg_global_set_custom_resolver(ggp_resolver_purple_start
,
61 ggp_resolver_purple_cleanup
) != 0)
63 purple_debug_error("gg", "failed to set custom resolver\n");
67 void ggp_resolver_purple_cb(GObject
*sender
, GAsyncResult
*res
, gpointer cbdata
) {
68 GList
*addresses
= NULL
, *in_addrs
= NULL
, *l
= NULL
;
70 gsize native_size
= 0; /* this is kind of dirty, but it'll be initialized before we use it */
72 ggp_resolver_purple_data
*data
= (ggp_resolver_purple_data
*)cbdata
;
73 const int fd
= data
->pipes
[1];
75 addresses
= g_resolver_lookup_by_name_finish(G_RESOLVER(sender
),
77 if(addresses
== NULL
) {
78 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n",
83 purple_debug_misc("gg", "ggp_resolver_purple_cb succeeded: (%p, %p)\n",
87 g_object_unref(G_OBJECT(data
->cancellable
));
88 data
->cancellable
= NULL
;
90 for(l
= addresses
; l
; l
= l
->next
) {
91 GInetAddress
*inet_address
= G_INET_ADDRESS(l
->data
);
92 GSocketFamily family
= G_SOCKET_FAMILY_INVALID
;
93 gchar
*ip_address
= g_inet_address_to_string(inet_address
);
95 family
= g_inet_address_get_family(inet_address
);
98 case G_SOCKET_FAMILY_IPV4
:
99 purple_debug_misc("gg", "ggp_resolver_purple_cb "
100 "ipv4: %s\n", ip_address
);
102 native_size
= g_inet_address_get_native_size(inet_address
);
103 in_addrs
= g_list_append(in_addrs
, g_memdup(g_inet_address_to_bytes(inet_address
), native_size
));
106 case G_SOCKET_FAMILY_IPV6
:
107 purple_debug_misc("gg", "ggp_resolver_purple_cb "
108 "ipv6 (ignore): %s\n", ip_address
);
112 purple_debug_warning("gg", "ggp_resolver_purple_cb "
113 "unexpected sa_family: %d\n",
122 for(l
= in_addrs
; l
; l
= l
->next
) {
123 gint write_size
= native_size
;
124 if(write(fd
, l
->data
, write_size
) != write_size
) {
125 purple_debug_error("gg",
126 "ggp_resolver_purple_cb write error on %p\n", l
->data
);
132 g_list_free(in_addrs
);
133 g_resolver_free_addresses(addresses
);
136 int ggp_resolver_purple_start(int *fd
, void **private_data
,
137 const char *hostname
)
139 ggp_resolver_purple_data
*data
;
142 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n",
143 fd
, private_data
, hostname
);
145 data
= malloc(sizeof(ggp_resolver_purple_data
));
146 *private_data
= (void*)data
;
147 data
->cancellable
= NULL
;
151 if (purple_input_pipe(data
->pipes
) != 0) {
152 purple_debug_error("gg", "ggp_resolver_purple_start: "
153 "unable to create pipe\n");
154 ggp_resolver_purple_cleanup(private_data
, 0);
158 *fd
= data
->pipes
[0];
160 /* account and port is unknown in this context */
161 data
->cancellable
= g_cancellable_new();
163 resolver
= g_resolver_get_default();
164 g_resolver_lookup_by_name_async(resolver
,
167 ggp_resolver_purple_cb
,
169 g_object_unref(resolver
);
171 if (!data
->cancellable
) {
172 purple_debug_error("gg", "ggp_resolver_purple_start: "
173 "unable to call purple_dnsquery_a\n");
174 ggp_resolver_purple_cleanup(private_data
, 0);
181 void ggp_resolver_purple_cleanup(void **private_data
, int force
)
183 ggp_resolver_purple_data
*data
=
184 (ggp_resolver_purple_data
*)(*private_data
);
186 purple_debug_misc("gg", "ggp_resolver_purple_cleanup(%p, %d)\n",
187 private_data
, force
);
191 *private_data
= NULL
;
193 if (G_IS_CANCELLABLE(data
->cancellable
)) {
194 g_cancellable_cancel(data
->cancellable
);
196 g_object_unref(G_OBJECT(data
->cancellable
));
200 close(data
->pipes
[0]);
202 close(data
->pipes
[1]);