libpurple/protocols/gg/resolver-purple.c

branch
use-gresolver
changeset 37454
eac2789dd461
parent 35676
d9fdd45925ec
child 37517
a67be31f9c7e
equal deleted inserted replaced
37453:387f778190f1 37454:eac2789dd461
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
28 */ 28 */
29 29
30 #include <internal.h> 30 #include <internal.h>
31 #include <debug.h> 31 #include <debug.h>
32 #include <dnsquery.h>
33 32
34 #include <libgadu.h> 33 #include <libgadu.h>
35 #include "resolver-purple.h" 34 #include "resolver-purple.h"
36 35
36 #include <gio/gio.h>
37
37 static int ggp_resolver_purple_start(int *fd, void **private_data, 38 static int ggp_resolver_purple_start(int *fd, void **private_data,
38 const char *hostname); 39 const char *hostname);
39 40
40 static void ggp_resolver_purple_cleanup(void **private_data, int force); 41 static void ggp_resolver_purple_cleanup(void **private_data, int force);
41 42
42 static void ggp_resolver_purple_cb(GSList *hosts, gpointer cbdata, 43 static void ggp_resolver_purple_cb(GObject *sender, GAsyncResult *res, gpointer data);
43 const char *error_message);
44 44
45 typedef struct 45 typedef struct
46 { 46 {
47 PurpleDnsQueryData *purpleQuery; 47 GCancellable *cancellable;
48 48
49 /** 49 /**
50 * File descriptors: 50 * File descriptors:
51 * pipes[0] - for reading 51 * pipes[0] - for reading
52 * pipes[1] - for writing 52 * pipes[1] - for writing
62 { 62 {
63 purple_debug_error("gg", "failed to set custom resolver\n"); 63 purple_debug_error("gg", "failed to set custom resolver\n");
64 } 64 }
65 } 65 }
66 66
67 void ggp_resolver_purple_cb(GSList *hosts, gpointer cbdata, 67 void ggp_resolver_purple_cb(GObject *sender, GAsyncResult *res, gpointer cbdata) {
68 const char *error_message) 68 GList *addresses = NULL, *in_addrs = NULL, *l = NULL;
69 { 69 GError *error = NULL;
70 gsize native_size = 0; /* this is kind of dirty, but it'll be initialized before we use it */
71
70 ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata; 72 ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata;
71 const int fd = data->pipes[1]; 73 const int fd = data->pipes[1];
72 int ipv4_count, all_count, write_size; 74
73 struct in_addr *addresses; 75 addresses = g_resolver_lookup_by_name_finish(g_resolver_get_default(), res, &error);
74 76 if(addresses == NULL) {
75 purple_debug_misc("gg", "ggp_resolver_purple_cb(%p, %p, \"%s\")\n",
76 hosts, cbdata, error_message);
77
78 data->purpleQuery = NULL;
79
80 if (error_message) {
81 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n", 77 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n",
82 error_message); 78 error->message);
83 } 79
84 80 g_error_free(error);
85 all_count = g_slist_length(hosts); 81 } else {
86 g_assert(all_count % 2 == 0); 82 purple_debug_misc("gg", "ggp_resolver_purple_cb succeeded: (%p, %p)\n",
87 all_count /= 2; 83 addresses, cbdata);
88 addresses = malloc((all_count + 1) * sizeof(struct in_addr)); 84 }
89 85
90 ipv4_count = 0; 86 g_object_unref(G_OBJECT(data->cancellable));
91 while (hosts && (hosts = g_slist_delete_link(hosts, hosts))) { 87 data->cancellable = NULL;
92 common_sockaddr_t addr; 88
93 char dst[INET6_ADDRSTRLEN]; 89 for(l = addresses; l; l = l->next) {
94 90 GInetAddress *inet_address = G_INET_ADDRESS(l->data);
95 memcpy(&addr, hosts->data, sizeof(addr)); 91 GSocketFamily family = G_SOCKET_FAMILY_INVALID;
96 92 gchar *ip_address = g_inet_address_to_string(inet_address);
97 if (addr.sa.sa_family == AF_INET6) { 93
98 inet_ntop(addr.sa.sa_family, &addr.in6.sin6_addr, 94 family = g_inet_address_get_family(inet_address);
99 dst, sizeof(dst)); 95
100 purple_debug_misc("gg", "ggp_resolver_purple_cb " 96 switch(family) {
101 "ipv6 (ignore): %s\n", dst); 97 case G_SOCKET_FAMILY_IPV4:
102 } else if (addr.sa.sa_family == AF_INET) { 98 purple_debug_misc("gg", "ggp_resolver_purple_cb "
103 inet_ntop(addr.sa.sa_family, &addr.in.sin_addr, 99 "ipv4: %s\n", ip_address);
104 dst, sizeof(dst)); 100
105 purple_debug_misc("gg", "ggp_resolver_purple_cb " 101 native_size = g_inet_address_get_native_size(inet_address);
106 "ipv4: %s\n", dst); 102 in_addrs = g_list_append(in_addrs, g_memdup(g_inet_address_to_bytes(inet_address), native_size));
107 103
108 g_assert(ipv4_count < all_count); 104 break;
109 addresses[ipv4_count++] = addr.in.sin_addr; 105 case G_SOCKET_FAMILY_IPV6:
110 } else { 106 purple_debug_misc("gg", "ggp_resolver_purple_cb "
111 purple_debug_warning("gg", "ggp_resolver_purple_cb " 107 "ipv6 (ignore): %s\n", ip_address);
112 "unexpected sa_family: %d\n", 108
113 addr.sa.sa_family); 109 break;
110 default:
111 purple_debug_warning("gg", "ggp_resolver_purple_cb "
112 "unexpected sa_family: %d\n",
113 family);
114
115 break;
114 } 116 }
115 117
116 g_free(hosts->data); 118 g_free(ip_address);
117 hosts = g_slist_delete_link(hosts, hosts); 119 }
118 } 120
119 121 for(l = in_addrs; l; l = l->next) {
120 addresses[ipv4_count].s_addr = INADDR_NONE; 122 gint write_size = native_size;
121 123 if(write(fd, l->data, write_size) != write_size) {
122 write_size = (ipv4_count + 1) * sizeof(struct in_addr); 124 purple_debug_error("gg",
123 if (write(fd, addresses, write_size) != write_size) { 125 "ggp_resolver_purple_cb write error on %p\n", l->data);
124 purple_debug_error("gg", 126 }
125 "ggp_resolver_purple_cb write error\n"); 127
126 } 128 g_free(l->data);
127 free(addresses); 129 }
130
131 g_list_free(in_addrs);
132 g_resolver_free_addresses(addresses);
128 } 133 }
129 134
130 int ggp_resolver_purple_start(int *fd, void **private_data, 135 int ggp_resolver_purple_start(int *fd, void **private_data,
131 const char *hostname) 136 const char *hostname)
132 { 137 {
134 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n", 139 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n",
135 fd, private_data, hostname); 140 fd, private_data, hostname);
136 141
137 data = malloc(sizeof(ggp_resolver_purple_data)); 142 data = malloc(sizeof(ggp_resolver_purple_data));
138 *private_data = (void*)data; 143 *private_data = (void*)data;
139 data->purpleQuery = NULL; 144 data->cancellable = NULL;
140 data->pipes[0] = 0; 145 data->pipes[0] = 0;
141 data->pipes[1] = 0; 146 data->pipes[1] = 0;
142 147
143 if (purple_input_pipe(data->pipes) != 0) { 148 if (purple_input_pipe(data->pipes) != 0) {
144 purple_debug_error("gg", "ggp_resolver_purple_start: " 149 purple_debug_error("gg", "ggp_resolver_purple_start: "
148 } 153 }
149 154
150 *fd = data->pipes[0]; 155 *fd = data->pipes[0];
151 156
152 /* account and port is unknown in this context */ 157 /* account and port is unknown in this context */
153 data->purpleQuery = purple_dnsquery_a(NULL, hostname, 80, 158 data->cancellable = g_cancellable_new();
154 ggp_resolver_purple_cb, (gpointer)data); 159
155 160 g_resolver_lookup_by_name_async(g_resolver_get_default(),
156 if (!data->purpleQuery) { 161 hostname,
162 data->cancellable,
163 ggp_resolver_purple_cb,
164 (gpointer)data);
165
166 if (!data->cancellable) {
157 purple_debug_error("gg", "ggp_resolver_purple_start: " 167 purple_debug_error("gg", "ggp_resolver_purple_start: "
158 "unable to call purple_dnsquery_a\n"); 168 "unable to call purple_dnsquery_a\n");
159 ggp_resolver_purple_cleanup(private_data, 0); 169 ggp_resolver_purple_cleanup(private_data, 0);
160 return -1; 170 return -1;
161 } 171 }
173 183
174 if (!data) 184 if (!data)
175 return; 185 return;
176 *private_data = NULL; 186 *private_data = NULL;
177 187
178 if (data->purpleQuery) 188 if (G_IS_CANCELLABLE(data->cancellable)) {
179 purple_dnsquery_destroy(data->purpleQuery); 189 g_cancellable_cancel(data->cancellable);
190
191 g_object_unref(G_OBJECT(data->cancellable));
192 }
193
180 if (data->pipes[0]) 194 if (data->pipes[0])
181 close(data->pipes[0]); 195 close(data->pipes[0]);
182 if (data->pipes[1]) 196 if (data->pipes[1])
183 close(data->pipes[1]); 197 close(data->pipes[1]);
184 198

mercurial