--- a/libpurple/proxy.c Tue Dec 15 22:04:26 2015 -0600
+++ b/libpurple/proxy.c Tue Dec 15 23:59:40 2015 -0600
@@ -29,7 +29,6 @@
#include "ciphers/md5hash.h"
@@ -37,6 +36,8 @@
PurpleProxyType type; /* The proxy type. */
@@ -57,13 +58,14 @@
- PurpleDnsQueryData *query_data;
+ GCancellable *cancellable; - * This contains alternating length/char* values. The char*
- * values need to be freed when removed from the linked list.
+ * This list contains GInetAddress and they should be freed with + * g_resolver_free_addresses when done with.
PurpleProxyConnectData *child;
@@ -580,18 +582,16 @@
handles = g_slist_remove(handles, connect_data);
- if (connect_data->query_data != NULL)
- purple_dnsquery_destroy(connect_data->query_data);
- while (connect_data->hosts != NULL)
- /* Discard the length... */
- connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data);
- /* Free the address... */
- g_free(connect_data->hosts->data);
- connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data);
+ if(G_IS_CANCELLABLE(connect_data->cancellable)) { + g_cancellable_cancel(connect_data->cancellable); + g_object_unref(G_OBJECT(connect_data->cancellable)); + connect_data->cancellable = NULL; + g_resolver_free_addresses(connect_data->hosts); g_free(connect_data->host);
@@ -1313,16 +1313,31 @@
-s4_host_resolved(GSList *hosts, gpointer data, const char *error_message)
+s4_host_resolved(GObject *source_object, GAsyncResult *res, gpointer data) + GResolver *resolver = NULL; + GInetAddress *address = NULL; + GList *hosts = NULL, *l = NULL; PurpleProxyConnectData *connect_data = data;
- common_sockaddr_t *addr;
- connect_data->query_data = NULL;
- if (error_message != NULL) {
- purple_proxy_connect_data_disconnect(connect_data, error_message);
+ if(G_IS_CANCELLABLE(connect_data->cancellable)) { + g_object_unref(G_OBJECT(connect_data->cancellable)); + connect_data->cancellable = NULL; + resolver = g_resolver_get_default(); + hosts = g_resolver_lookup_by_name_finish(resolver, res, &error); + g_object_unref(G_OBJECT(resolver)); + if (error->message != NULL) { + purple_proxy_connect_data_disconnect(connect_data, error->message); @@ -1332,37 +1347,37 @@
- /* Discard the length... */
- hosts = g_slist_delete_link(hosts, hosts);
- hosts = g_slist_delete_link(hosts, hosts);
- packet[2] = connect_data->port >> 8;
- packet[3] = connect_data->port & 0xff;
- memcpy(packet + 4, &addr->in.sin_addr.s_addr, 4);
- /* We could try the other hosts, but hopefully that shouldn't be necessary */
- while (hosts != NULL) {
- /* Discard the length... */
- hosts = g_slist_delete_link(hosts, hosts);
- /* Free the address... */
- hosts = g_slist_delete_link(hosts, hosts);
+ for(l = hosts; l; l = l->next) { + address = G_INET_ADDRESS(l->data); + if(!g_inet_address_get_is_loopback(address) && !g_inet_address_get_is_link_local(address)) - connect_data->write_buffer = g_memdup(packet, sizeof(packet));
- connect_data->write_buf_len = sizeof(packet);
- connect_data->written_len = 0;
- connect_data->read_cb = s4_canread;
- connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data);
- proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
+ packet[2] = connect_data->port >> 8; + packet[3] = connect_data->port & 0xff; + memcpy(packet + 4, g_inet_address_to_bytes(address), 4); + connect_data->write_buffer = g_memdup(packet, sizeof(packet)); + connect_data->write_buf_len = sizeof(packet); + connect_data->written_len = 0; + connect_data->read_cb = s4_canread; + connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); + proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); + purple_proxy_connect_data_disconnect_formatted(connect_data, + _("Error resolving %s"), connect_data->host); + g_resolver_free_addresses(hosts); @@ -1422,11 +1437,21 @@
proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
- connect_data->query_data = purple_dnsquery_a(
- connect_data->account, connect_data->host,
- connect_data->port, s4_host_resolved, connect_data);
- if (connect_data->query_data == NULL) {
+ GResolver *resolver = NULL; + connect_data->cancellable = g_cancellable_new(); + resolver = g_resolver_get_default(); + g_resolver_lookup_by_name_async(resolver, + connect_data->cancellable, + g_object_unref(G_OBJECT(resolver)); + if (connect_data->cancellable == NULL) { purple_debug_error("proxy", "dns query failed unexpectedly.\n");
purple_proxy_connect_data_destroy(connect_data);
@@ -2140,29 +2165,35 @@
static void try_connect(PurpleProxyConnectData *connect_data)
+ GInetAddress *address = NULL; + GSocketAddress *socket_address = NULL; - char ipaddr[INET6_ADDRSTRLEN];
- addrlen = GPOINTER_TO_INT(connect_data->hosts->data);
- connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data);
- addr = connect_data->hosts->data;
- connect_data->hosts = g_slist_remove(connect_data->hosts, connect_data->hosts->data);
- if (addr->sa.sa_family == AF_INET)
- inet_ntop(addr->sa.sa_family, &addr->in.sin_addr,
- ipaddr, sizeof(ipaddr));
- else if (addr->sa.sa_family == AF_INET6)
- inet_ntop(addr->sa.sa_family, &addr->in6.sin6_addr,
- ipaddr, sizeof(ipaddr));
- memcpy(ipaddr, inet_ntoa(addr->in.sin_addr), sizeof(ipaddr));
+ address = G_INET_ADDRESS(connect_data->hosts->data); + ipaddr = g_inet_address_to_string(address); purple_debug_info("proxy", "Attempting connection to %s\n", ipaddr);
+ socket_address = g_inet_socket_address_new(address, connect_data->port); + addrlen = g_socket_address_get_native_size(socket_address); + g_socket_address_to_native(socket_address, addr, addrlen, &error); + purple_debug_info("proxy", "failed connnection : %s\n", error->message); if (connect_data->socket_type == SOCK_DGRAM) {
proxy_connect_udp_none(connect_data, addr, addrlen);
@@ -2192,31 +2223,41 @@
+ g_object_unref(G_OBJECT(socket_address)); -connection_host_resolved(GSList *hosts, gpointer data,
- const char *error_message)
- PurpleProxyConnectData *connect_data;
- connect_data->query_data = NULL;
- if (error_message != NULL)
- purple_proxy_connect_data_disconnect(connect_data, error_message);
+connection_host_resolved(GObject *source, GAsyncResult *res, gpointer data) { + PurpleProxyConnectData *connect_data = (PurpleProxyConnectData *)data; + GList *addresses = NULL; + addresses = g_resolver_lookup_by_name_finish(g_resolver_get_default(), res, &error); + if(G_IS_CANCELLABLE(connect_data->cancellable)) { + g_object_unref(G_OBJECT(connect_data->cancellable)); + connect_data->cancellable = NULL; + purple_proxy_connect_data_disconnect(connect_data, error->message); + g_resolver_free_addresses(addresses);
+ if (addresses == NULL) { purple_proxy_connect_data_disconnect(connect_data, _("Unable to resolve hostname"));
- connect_data->hosts = hosts;
+ connect_data->hosts = addresses; try_connect(connect_data);
@@ -2355,9 +2396,15 @@
- connect_data->query_data = purple_dnsquery_a(account, connecthost,
- connectport, connection_host_resolved, connect_data);
- if (connect_data->query_data == NULL)
+ connect_data->cancellable = g_cancellable_new(); + g_resolver_lookup_by_name_async(g_resolver_get_default(), + connect_data->cancellable, + connection_host_resolved, + if (connect_data->cancellable == NULL) purple_debug_error("proxy", "dns query failed unexpectedly.\n");
purple_proxy_connect_data_destroy(connect_data);
@@ -2426,10 +2473,15 @@
- connect_data->query_data = purple_dnsquery_a(account, connecthost,
- connectport, connection_host_resolved, connect_data);
- if (connect_data->query_data == NULL)
+ connect_data->cancellable = g_cancellable_new(); + g_resolver_lookup_by_name_async(g_resolver_get_default(), + connect_data->cancellable, + connection_host_resolved, + if (connect_data->cancellable == NULL) { purple_proxy_connect_data_destroy(connect_data);