soc.2012.gg: 2b9913aa: New custom resolver, that uses libpurple...
tomkiewicz at cpw.pidgin.im
tomkiewicz at cpw.pidgin.im
Thu Jun 7 06:51:58 EDT 2012
----------------------------------------------------------------------
Revision: 2b9913aaf462a241a7d454bf9ea96f156daf76da
Parent: 95b990bae7d439afac6bc95905b0026e52b003c2
Author: tomkiewicz at cpw.pidgin.im
Date: 06/07/12 06:47:50
Branch: im.pidgin.soc.2012.gg
URL: http://d.pidgin.im/viewmtn/revision/info/2b9913aaf462a241a7d454bf9ea96f156daf76da
Changelog:
New custom resolver, that uses libpurple for DNS queries. Get rid of old win32 resolver. Refs#343. Fixes #6263
Changes against parent 95b990bae7d439afac6bc95905b0026e52b003c2
dropped libpurple/protocols/gg/win32-resolver.c
dropped libpurple/protocols/gg/win32-resolver.h
added libpurple/protocols/gg/resolver-purple.c
added libpurple/protocols/gg/resolver-purple.h
patched libpurple/eventloop.c
patched libpurple/eventloop.h
patched libpurple/protocols/gg/Makefile.am
patched libpurple/protocols/gg/Makefile.mingw
patched libpurple/protocols/gg/gg.c
patched libpurple/win32/win32dep.c
patched libpurple/win32/win32dep.h
-------------- next part --------------
============================================================
--- libpurple/protocols/gg/Makefile.am 52056a4431bbd8d71e1e3c3b26a4183e10f4886d
+++ libpurple/protocols/gg/Makefile.am 92f14838ba026d32c3b88e65f34e5ddb5fea37ed
@@ -1,7 +1,7 @@ EXTRA_DIST = \
EXTRA_DIST = \
Makefile.mingw \
- win32-resolver.c \
- win32-resolver.h \
+ resolver-purple.c \
+ resolver-purple.h \
lib/common.c \
lib/compat.h \
lib/COPYING \
@@ -81,7 +81,9 @@ GGSOURCES = \
buddylist.h \
buddylist.c \
gg.h \
- gg.c
+ gg.c \
+ resolver-purple.h \
+ resolver-purple.c
AM_CFLAGS = $(st)
============================================================
--- libpurple/protocols/gg/gg.c 5f171159d2f69d8f0607310d2516c47ff357dae1
+++ libpurple/protocols/gg/gg.c ce72c0ebf7addc72304d660d17ce2f0c3c8f481d
@@ -44,11 +44,8 @@
#include "search.h"
#include "buddylist.h"
#include "gg-utils.h"
+#include "resolver-purple.h"
-#ifdef _WIN32
-# include "win32-resolver.h"
-#endif
-
/* Prototypes */
static void ggp_set_status(PurpleAccount *account, PurpleStatus *status);
static int ggp_to_gg_status(PurpleStatus *status, char **msg);
@@ -3005,10 +3002,7 @@ static void init_plugin(PurplePlugin *pl
gg_debug_handler = purple_gg_debug_handler;
-#ifdef _WIN32
- gg_global_set_custom_resolver(ggp_resolver_win32thread_start,
- ggp_resolver_win32thread_cleanup);
-#endif
+ ggp_resolver_purple_setup();
}
PURPLE_INIT_PLUGIN(gg, init_plugin, info);
============================================================
--- libpurple/protocols/gg/Makefile.mingw fb7eb47e39a124fb8c47c34856471d014f66eda2
+++ libpurple/protocols/gg/Makefile.mingw 1064e02bc4246a61fcc307b327440e93603f69f1
@@ -24,14 +24,14 @@ endif
##
## INCLUDE PATHS
##
-INCLUDE_PATHS += -I. \
+INCLUDE_PATHS +=\
+ -I$(PIDGIN_TREE_TOP) \
+ -I$(PURPLE_TOP) \
+ -I$(PURPLE_TOP)/win32 \
-I./lib \
-I$(GTK_TOP)/include \
-I$(GTK_TOP)/include/glib-2.0 \
- -I$(GTK_TOP)/lib/glib-2.0/include \
- -I$(PURPLE_TOP) \
- -I$(PURPLE_TOP)/win32 \
- -I$(PIDGIN_TREE_TOP)
+ -I$(GTK_TOP)/lib/glib-2.0/include
LIB_PATHS += -L$(GTK_TOP)/lib \
-L$(PURPLE_TOP) \
@@ -61,7 +61,7 @@ C_SRC = \
gg.c \
search.c \
gg-utils.c \
- win32-resolver.c
+ resolver-purple.c
OBJECTS = $(C_SRC:%.c=%.o)
============================================================
--- libpurple/win32/win32dep.c d62e125b1de03235763e5f361b9a93c2d504fa6a
+++ libpurple/win32/win32dep.c ac957dfa5f6088924232369334dd02f346bb94a3
@@ -328,6 +328,111 @@ char *wpurple_read_reg_string(HKEY rootk
return result;
}
+int wpurple_input_pipe(int pipefd[2])
+{
+ SOCKET sock_server, sock_client, sock_server_established;
+ struct sockaddr_in saddr_in;
+ struct sockaddr * const saddr_p = (struct sockaddr *)&saddr_in;
+ int saddr_len = sizeof(struct sockaddr_in);
+ u_long arg;
+ fd_set select_set;
+ char succ = 1;
+
+ sock_server = sock_client = sock_server_established = INVALID_SOCKET;
+
+ purple_debug_misc("wpurple", "wpurple_input_pipe(0x%x[%d,%d])\n",
+ (unsigned int)pipefd, pipefd[0], pipefd[1]);
+
+ /* create client and passive server sockets */
+ sock_server = socket(AF_INET, SOCK_STREAM, 0);
+ sock_client = socket(AF_INET, SOCK_STREAM, 0);
+ succ = (sock_server != INVALID_SOCKET || sock_client != INVALID_SOCKET);
+
+ /* set created sockets into nonblocking mode */
+ arg = 1;
+ succ = (succ &&
+ ioctlsocket(sock_server, FIONBIO, &arg) != SOCKET_ERROR);
+ arg = 1;
+ succ = (succ &&
+ ioctlsocket(sock_client, FIONBIO, &arg) != SOCKET_ERROR);
+
+ /* listen on server socket */
+ memset(&saddr_in, 0, saddr_len);
+ saddr_in.sin_family = AF_INET;
+ saddr_in.sin_port = 0;
+ saddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ succ = (succ &&
+ bind(sock_server, saddr_p, saddr_len) != SOCKET_ERROR &&
+ listen(sock_server, 1) != SOCKET_ERROR &&
+ getsockname(sock_server, saddr_p, &saddr_len) != SOCKET_ERROR);
+
+ /* request a connection from client to server socket */
+ succ = (succ &&
+ connect(sock_client, saddr_p, saddr_len) == SOCKET_ERROR &&
+ WSAGetLastError() == WSAEWOULDBLOCK);
+
+ /* ensure, that server socket is readable */
+ if (succ)
+ {
+ FD_ZERO(&select_set);
+ FD_SET(sock_server, &select_set);
+ }
+ succ = (succ &&
+ select(0, &select_set, NULL, NULL, NULL) != SOCKET_ERROR &&
+ FD_ISSET(sock_server, &select_set));
+
+ /* accept (establish) connection from client socket */
+ if (succ)
+ {
+ sock_server_established =
+ accept(sock_server, saddr_p, &saddr_len);
+ succ = (sock_server_established != INVALID_SOCKET);
+ }
+
+ /* ensure, that client socket is writable */
+ if (succ)
+ {
+ FD_ZERO(&select_set);
+ FD_SET(sock_client, &select_set);
+ }
+ succ = (succ &&
+ select(0, NULL, &select_set, NULL, NULL) != SOCKET_ERROR &&
+ FD_ISSET(sock_client, &select_set));
+
+ /* set sockets into blocking mode */
+ arg = 0;
+ succ = (succ &&
+ ioctlsocket(sock_client, FIONBIO, &arg) != SOCKET_ERROR);
+ arg = 0;
+ succ = (succ &&
+ ioctlsocket(sock_server_established, FIONBIO, &arg)
+ != SOCKET_ERROR);
+
+ /* we don't need (passive) server socket anymore */
+ if (sock_server != INVALID_SOCKET)
+ closesocket(sock_server);
+
+ if (succ)
+ {
+ purple_debug_misc("wpurple",
+ "wpurple_input_pipe created pipe [%d,%d]\n",
+ sock_client, sock_server_established);
+ pipefd[0] = sock_client; /* for reading */
+ pipefd[1] = sock_server_established; /* for writing */
+ return 0;
+ }
+ else
+ {
+ purple_debug_error("wpurple", "wpurple_input_pipe failed\n");
+ if (sock_client != INVALID_SOCKET)
+ closesocket(sock_client);
+ if (sock_server_established != INVALID_SOCKET)
+ closesocket(sock_server_established);
+ errno = EMFILE;
+ return -1;
+ }
+}
+
void wpurple_init(void) {
WORD wVersionRequested;
WSADATA wsaData;
============================================================
--- libpurple/win32/win32dep.h 9ba1b08f050adbe2485bca2b040c67c48b9fd982
+++ libpurple/win32/win32dep.h 84d8f2de37a7e519b7923167cb9afff73693126e
@@ -60,6 +60,9 @@ GIOChannel *wpurple_g_io_channel_win32_n
char *wpurple_escape_dirsep(const char *filename); /* needs to be g_free'd */
GIOChannel *wpurple_g_io_channel_win32_new_socket(int socket); /* Until we get the post-2.8 glib win32 giochannel implementation working, use the thread-based one */
+/* Simulate unix pipes by creating a pair of connected sockets */
+int wpurple_input_pipe(int pipefd[2]);
+
/* Determine Purple paths */
gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */
const char *wpurple_install_dir(void);
============================================================
--- libpurple/eventloop.c d98b9ac615593ed9c4394b7a2e30d1192146c21a
+++ libpurple/eventloop.c 1caf2445b114fa66eed2876f6670cf0857dee088
@@ -91,6 +91,16 @@ purple_input_get_error(int fd, int *erro
}
}
+int
+purple_input_pipe(int pipefd[2])
+{
+#ifdef _WIN32
+ return wpurple_input_pipe(pipefd);
+#else
+ return pipe(pipefd);
+#endif
+}
+
void
purple_eventloop_set_ui_ops(PurpleEventLoopUiOps *ops)
{
============================================================
--- libpurple/eventloop.h 0eb5204960bacae171ba2fb9f5d9ce2f06d526f3
+++ libpurple/eventloop.h 77e014b87bce6f6794e0c0bad63a4991b7bc0a2b
@@ -240,7 +240,25 @@ purple_input_get_error(int fd, int *erro
int
purple_input_get_error(int fd, int *error);
+/**
+ * Creates a pipe - an unidirectional data channel that can be used for
+ * interprocess communication.
+ *
+ * File descriptors for both ends of pipe will be written into provided array.
+ * The first one (pipefd[0]) can be used for reading, the second one (pipefd[1])
+ * for writing.
+ *
+ * On Windows it's simulated by creating a pair of connected sockets, on other
+ * systems pipe() is used.
+ *
+ * @param pipefd Array used to return file descriptors for both ends of pipe.
+ *
+ * @return @c 0 on success, @c -1 on error.
+ */
+int
+purple_input_pipe(int pipefd[2]);
+
/*@}*/
============================================================
--- libpurple/protocols/gg/win32-resolver.c 7df67382fa43098342cd3091b7a1e15a4954f509
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * @file win32-resolver.c
- *
- * purple
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include "win32-resolver.h"
-
-#include <errno.h>
-#include <resolver.h>
-#include "debug.h"
-
-#ifndef _WIN32
-#error "win32thread resolver is not supported on current platform"
-#endif
-
-/**
- * Deal with the fact that you can't select() on a win32 file fd.
- * This makes it practically impossible to tie into purple's event loop.
- *
- * -This is thanks to Tor Lillqvist.
- */
-static int ggp_resolver_win32thread_socket_pipe(int *fds)
-{
- SOCKET temp, socket1 = -1, socket2 = -1;
- struct sockaddr_in saddr;
- int len;
- u_long arg;
- fd_set read_set, write_set;
- struct timeval tv;
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_socket_pipe(&%d)\n",
- *fds);
-
- temp = socket(AF_INET, SOCK_STREAM, 0);
-
- if (temp == INVALID_SOCKET) {
- goto out0;
- }
-
- arg = 1;
- if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
- goto out0;
- }
-
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
- saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
- goto out0;
- }
-
- if (listen(temp, 1) == SOCKET_ERROR) {
- goto out0;
- }
-
- len = sizeof(saddr);
- if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
- goto out0;
- }
-
- socket1 = socket(AF_INET, SOCK_STREAM, 0);
-
- if (socket1 == INVALID_SOCKET) {
- goto out0;
- }
-
- arg = 1;
- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
- goto out1;
- }
-
- if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
- WSAGetLastError() != WSAEWOULDBLOCK) {
- goto out1;
- }
-
- FD_ZERO(&read_set);
- FD_SET(temp, &read_set);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
- goto out1;
- }
-
- if (!FD_ISSET(temp, &read_set)) {
- goto out1;
- }
-
- socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
- if (socket2 == INVALID_SOCKET) {
- goto out1;
- }
-
- FD_ZERO(&write_set);
- FD_SET(socket1, &write_set);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
- goto out2;
- }
-
- if (!FD_ISSET(socket1, &write_set)) {
- goto out2;
- }
-
- arg = 0;
- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
- goto out2;
- }
-
- arg = 0;
- if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
- goto out2;
- }
-
- fds[0] = socket1;
- fds[1] = socket2;
-
- closesocket (temp);
-
- return 0;
-
-out2:
- closesocket (socket2);
-out1:
- closesocket (socket1);
-out0:
- closesocket (temp);
- errno = EIO; /* XXX */
-
- return -1;
-}
-
-struct ggp_resolver_win32thread_data {
- char *hostname;
- int fd;
-};
-
-/**
- * Copy-paste from gg_resolver_run().
- */
-static DWORD WINAPI ggp_resolver_win32thread_thread(LPVOID arg)
-{
- struct ggp_resolver_win32thread_data *data = arg;
- struct in_addr addr_ip[2], *addr_list;
- int addr_count;
-
- purple_debug_info("gg", "ggp_resolver_win32thread_thread() host: %s, "
- "fd: %i called\n", data->hostname, data->fd);
-
- if ((addr_ip[0].s_addr = inet_addr(data->hostname)) == INADDR_NONE) {
- if (gg_gethostbyname_real(data->hostname, &addr_list,
- &addr_count, 0) == -1) {
- addr_list = addr_ip;
- /* addr_ip[0] ju? zawiera INADDR_NONE */
- }
- } else {
- addr_list = addr_ip;
- addr_ip[1].s_addr = INADDR_NONE;
- addr_count = 1;
- }
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_thread() "
- "count = %d\n", addr_count);
-
- write(data->fd, addr_list, (addr_count + 1) * sizeof(struct in_addr));
- close(data->fd);
-
- free(data->hostname);
- data->hostname = NULL;
-
- free(data);
-
- if (addr_list != addr_ip)
- free(addr_list);
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_thread() done\n");
-
- return 0;
-}
-
-
-int ggp_resolver_win32thread_start(int *fd, void **private_data,
- const char *hostname)
-{
- struct ggp_resolver_win32thread_data *data = NULL;
- HANDLE h;
- DWORD dwTId;
- int pipes[2], new_errno;
-
- purple_debug_info("gg", "ggp_resolver_win32thread_start(%p, %p, "
- "\"%s\");\n", fd, private_data, hostname);
-
- if (!private_data || !fd || !hostname) {
- purple_debug_error("gg", "ggp_resolver_win32thread_start() "
- "invalid arguments\n");
- errno = EFAULT;
- return -1;
- }
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating "
- "pipes...\n");
-
- if (ggp_resolver_win32thread_socket_pipe(pipes) == -1) {
- purple_debug_error("gg", "ggp_resolver_win32thread_start() "
- "unable to create pipes (errno=%d, %s)\n",
- errno, strerror(errno));
- return -1;
- }
-
- if (!(data = malloc(sizeof(*data)))) {
- purple_debug_error("gg", "ggp_resolver_win32thread_start() out "
- "of memory\n");
- new_errno = errno;
- goto cleanup;
- }
-
- data->hostname = NULL;
-
- if (!(data->hostname = strdup(hostname))) {
- purple_debug_error("gg", "ggp_resolver_win32thread_start() out "
- "of memory\n");
- new_errno = errno;
- goto cleanup;
- }
-
- data->fd = pipes[1];
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating "
- "thread...\n");
-
- h = CreateThread(NULL, 0, ggp_resolver_win32thread_thread, data, 0,
- &dwTId);
-
- if (h == NULL) {
- purple_debug_error("gg", "ggp_resolver_win32thread_start() "
- "unable to create thread\n");
- new_errno = errno;
- goto cleanup;
- }
-
- *private_data = h;
- *fd = pipes[0];
-
- purple_debug_misc("gg", "ggp_resolver_win32thread_start() done\n");
-
- return 0;
-
-cleanup:
- if (data) {
- free(data->hostname);
- free(data);
- }
-
- close(pipes[0]);
- close(pipes[1]);
-
- errno = new_errno;
-
- return -1;
-
-}
-
-void ggp_resolver_win32thread_cleanup(void **private_data, int force)
-{
- struct ggp_resolver_win32thread_data *data;
-
- purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() force: %i "
- "called\n", force);
-
- if (private_data == NULL || *private_data == NULL) {
- purple_debug_error("gg", "ggp_resolver_win32thread_cleanup() "
- "private_data: NULL\n");
- return;
- }
- return; /* XXX */
-
- data = (struct ggp_resolver_win32thread_data*) *private_data;
- purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() data: "
- "%s called\n", data->hostname);
- *private_data = NULL;
-
- if (force) {
- purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() "
- "force called\n");
- //pthread_cancel(data->thread);
- //pthread_join(data->thread, NULL);
- }
-
- free(data->hostname);
- data->hostname = NULL;
-
- if (data->fd != -1) {
- close(data->fd);
- data->fd = -1;
- }
- purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() done\n");
- free(data);
-}
-
-/* vim: set ts=8 sts=0 sw=8 noet: */
============================================================
--- libpurple/protocols/gg/win32-resolver.h 3d15a404efa96c7cc0826559c6bb7519495f46be
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * @file win32-resolver.h
- *
- * purple
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef _PURPLE_GG_WIN32_RESOLVER
-#define _PURPLE_GG_WIN32_RESOLVER
-
-/**
- * Starts hostname resolving in new win32 thread.
- *
- * @param fd Pointer to variable, where pipe descriptor will be saved.
- * @param private_data Pointer to variable, where pointer to private data will
- * be saved.
- * @param hostname Hostname to resolve.
- */
-int ggp_resolver_win32thread_start(int *fd, void **private_data,
- const char *hostname);
-
-/**
- * Cleans up resources after hostname resolving.
- *
- * @param private_data Pointer to variable storing pointer to private data.
- * @param force TRUE, if resources should be cleaned up even, if
- * resolving process didn't finished.
- */
-void ggp_resolver_win32thread_cleanup(void **private_data, int force);
-
-#endif /* _PURPLE_GG_WIN32_RESOLVER */
-
-/* vim: set ts=8 sts=0 sw=8 noet: */
============================================================
--- /dev/null
+++ libpurple/protocols/gg/resolver-purple.c a6386d0d59219b5f96b1af56568d4a0dac6f6083
@@ -0,0 +1,161 @@
+#include <internal.h>
+#include <debug.h>
+#include <dnsquery.h>
+
+#include <libgadu.h>
+#include "resolver-purple.h"
+
+static int ggp_resolver_purple_start(int *fd, void **private_data,
+ const char *hostname);
+
+static void ggp_resolver_purple_cleanup(void **private_data, int force);
+
+static void ggp_resolver_purple_cb(GSList *hosts, gpointer cbdata,
+ const char *error_message);
+
+typedef struct
+{
+ PurpleDnsQueryData *purpleQuery;
+
+ /**
+ * File descriptors:
+ * pipes[0] - for reading
+ * pipes[1] - for writing
+ */
+ int pipes[2];
+} ggp_resolver_purple_data;
+
+
+extern void ggp_resolver_purple_setup(void)
+{
+ purple_debug_info("gg", "setting up custom resolver\n");
+ gg_global_set_custom_resolver(ggp_resolver_purple_start,
+ ggp_resolver_purple_cleanup);
+}
+
+void ggp_resolver_purple_cb(GSList *hosts, gpointer cbdata,
+ const char *error_message)
+{
+ ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata;
+ const int fd = data->pipes[1];
+ int ipv4_count, all_count, write_size;
+ struct in_addr *addresses;
+
+ purple_debug_misc("gg", "ggp_resolver_purple_cb(%x, %x, \"%s\")\n",
+ (unsigned int)hosts, (unsigned int)cbdata, error_message);
+
+ if (error_message)
+ {
+ purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n",
+ error_message);
+ }
+
+ all_count = g_slist_length(hosts);
+ g_assert(all_count % 2 == 0);
+ all_count /= 2;
+ addresses = malloc((all_count + 1) * sizeof(struct in_addr));
+
+ ipv4_count = 0;
+ while (hosts && (hosts = g_slist_delete_link(hosts, hosts)))
+ {
+ const struct sockaddr *addr = hosts->data;
+ char dst[INET6_ADDRSTRLEN];
+
+ if (addr->sa_family == AF_INET6)
+ {
+ inet_ntop(addr->sa_family,
+ &((struct sockaddr_in6 *) addr)->sin6_addr,
+ dst, sizeof(dst));
+ purple_debug_misc("gg", "ggp_resolver_purple_cb "
+ "ipv6 (ignore): %s\n", dst);
+ }
+ else if (addr->sa_family == AF_INET)
+ {
+ const struct in_addr addr_ipv4 =
+ ((struct sockaddr_in *) addr)->sin_addr;
+ inet_ntop(addr->sa_family, &addr_ipv4,
+ dst, sizeof(dst));
+ purple_debug_misc("gg", "ggp_resolver_purple_cb "
+ "ipv4: %s\n", dst);
+
+ g_assert(ipv4_count < all_count);
+ addresses[ipv4_count++] = addr_ipv4;
+ }
+ else
+ {
+ purple_debug_warning("gg", "ggp_resolver_purple_cb "
+ "unexpected sa_family: %d\n", addr->sa_family);
+ }
+
+ g_free(hosts->data);
+ hosts = g_slist_delete_link(hosts, hosts);
+ }
+
+ addresses[ipv4_count].s_addr = INADDR_NONE;
+
+ write_size = (ipv4_count + 1) * sizeof(struct in_addr);
+ if (write(fd, addresses, write_size) != write_size)
+ {
+ purple_debug_error("gg",
+ "ggp_resolver_purple_cb write error\n");
+ }
+ free(addresses);
+}
+
+int ggp_resolver_purple_start(int *fd, void **private_data,
+ const char *hostname)
+{
+ ggp_resolver_purple_data *data;
+ purple_debug_misc("gg", "ggp_resolver_purple_start(%x, %x, \"%s\")\n",
+ (unsigned int)fd, (unsigned int)private_data, hostname);
+
+ data = malloc(sizeof(ggp_resolver_purple_data));
+ *private_data = (void*)data;
+ data->purpleQuery = NULL;
+ data->pipes[0] = 0;
+ data->pipes[1] = 0;
+
+ if (purple_input_pipe(data->pipes) != 0)
+ {
+ purple_debug_error("gg", "ggp_resolver_purple_start: "
+ "unable to create pipe\n");
+ ggp_resolver_purple_cleanup(private_data, 0);
+ return -1;
+ }
+
+ *fd = data->pipes[0];
+
+ /* account and port is unknown in this context */
+ data->purpleQuery = purple_dnsquery_a(NULL, hostname, 80,
+ ggp_resolver_purple_cb, (gpointer)data);
+
+ if (!data->purpleQuery)
+ {
+ purple_debug_error("gg", "ggp_resolver_purple_start: "
+ "unable to call purple_dnsquery_a\n");
+ ggp_resolver_purple_cleanup(private_data, 0);
+ return -1;
+ }
+
+ return 0;
+}
+
+void ggp_resolver_purple_cleanup(void **private_data, int force)
+{
+ ggp_resolver_purple_data *data =
+ (ggp_resolver_purple_data*)(*private_data);
+
+ purple_debug_misc("gg", "ggp_resolver_purple_cleanup(%x, %d)\n",
+ (unsigned int)private_data, force);
+
+ if (!data)
+ return;
+ *private_data = NULL;
+
+ if (data->pipes[0])
+ close(data->pipes[0]);
+ if (data->pipes[1])
+ close(data->pipes[1]);
+
+ free(data);
+}
============================================================
--- /dev/null
+++ libpurple/protocols/gg/resolver-purple.h e281062cd6f356435dac622a2558fc4db80d2b70
@@ -0,0 +1,9 @@
+#ifndef _PURPLE_GG_RESOLVER_PURPLE
+#define _PURPLE_GG_RESOLVER_PURPLE
+
+/**
+ * Registers custom resolver for libgadu, that uses libpurple for DNS queries.
+ */
+void ggp_resolver_purple_setup(void);
+
+#endif /* _PURPLE_GG_RESOLVER_PURPLE */
More information about the Commits
mailing list