Replace functions which called once with their bodies
[pidgin-git.git] / libpurple / protocols / gg / resolver-purple.c
blob36e45188219031398730d515e4e0706d494931c2
1 /* purple
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
5 * source distribution.
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
30 #include <internal.h>
31 #include <debug.h>
33 #include <libgadu.h>
34 #include "resolver-purple.h"
36 #include <gio/gio.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);
45 typedef struct
47 GCancellable *cancellable;
49 /**
50 * File descriptors:
51 * pipes[0] - for reading
52 * pipes[1] - for writing
54 int pipes[2];
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;
69 GError *error = 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),
76 res, &error);
77 if(addresses == NULL) {
78 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n",
79 error->message);
81 g_error_free(error);
82 } else {
83 purple_debug_misc("gg", "ggp_resolver_purple_cb succeeded: (%p, %p)\n",
84 addresses, cbdata);
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);
97 switch(family) {
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));
105 break;
106 case G_SOCKET_FAMILY_IPV6:
107 purple_debug_misc("gg", "ggp_resolver_purple_cb "
108 "ipv6 (ignore): %s\n", ip_address);
110 break;
111 default:
112 purple_debug_warning("gg", "ggp_resolver_purple_cb "
113 "unexpected sa_family: %d\n",
114 family);
116 break;
119 g_free(ip_address);
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);
129 g_free(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;
140 GResolver *resolver;
142 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n",
143 fd, private_data, hostname);
145 data = g_new0(ggp_resolver_purple_data, 1);
146 *private_data = (void*)data;
147 data->cancellable = NULL;
148 data->pipes[0] = 0;
149 data->pipes[1] = 0;
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);
155 return -1;
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,
165 hostname,
166 data->cancellable,
167 ggp_resolver_purple_cb,
168 (gpointer)data);
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);
175 return -1;
178 return 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);
189 if (!data)
190 return;
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));
199 if (data->pipes[0])
200 close(data->pipes[0]);
201 if (data->pipes[1])
202 close(data->pipes[1]);
204 g_free(data);