Clear ununused functions from proxy.[ch] including purple_proxy_connect_udp() purple-proxy-to-gio

Sun, 10 Jan 2016 03:23:46 -0600

author
Mike Ruprecht <cmaiku@gmail.com>
date
Sun, 10 Jan 2016 03:23:46 -0600
branch
purple-proxy-to-gio
changeset 37536
7f1d2f3ba6ae
parent 37535
447036b8779a
child 37537
9e1b392c606b

Clear ununused functions from proxy.[ch] including purple_proxy_connect_udp()

Since porting libpurple's proxy API to internally use Gio, a lot of
functions remain unused. purple_proxy_connect_udp() was added for the
QQ prpl (ticket #6589), but no longer appears to be used. This patch
removes all of these functions in favor of the Gio versions.

libpurple/proxy.c file | annotate | diff | comparison | revisions
libpurple/proxy.h file | annotate | diff | comparison | revisions
--- a/libpurple/proxy.c	Tue Jan 12 20:41:07 2016 -0600
+++ b/libpurple/proxy.c	Sun Jan 10 03:23:46 2016 -0600
@@ -99,8 +99,6 @@
 
 static GSList *handles = NULL;
 
-static void try_connect(PurpleProxyConnectData *connect_data);
-
 /*
  * TODO: Eventually (GObjectification) this bad boy will be removed, because it is
  *       a gross fix for a crashy problem.
@@ -639,35 +637,13 @@
 	{
 		purple_debug_error("proxy", "Connection attempt failed: %s\n",
 				error_message);
-		if (connect_data->hosts != NULL)
-			try_connect(connect_data);
-		else
-		{
-			/* Everything failed!  Tell the originator of the request. */
-			connect_data->connect_cb(connect_data->data, -1, error_message);
-			purple_proxy_connect_data_destroy(connect_data);
-		}
+
+		/* Everything failed!  Tell the originator of the request. */
+		connect_data->connect_cb(connect_data->data, -1, error_message);
+		purple_proxy_connect_data_destroy(connect_data);
 	}
 }
 
-/*
- * This calls purple_proxy_connect_data_disconnect(), but it lets you
- * specify the error_message using a printf()-like syntax.
- */
-static void
-purple_proxy_connect_data_disconnect_formatted(PurpleProxyConnectData *connect_data, const char *format, ...)
-{
-	va_list args;
-	gchar *tmp;
-
-	va_start(args, format);
-	tmp = g_strdup_vprintf(format, args);
-	va_end(args);
-
-	purple_proxy_connect_data_disconnect(connect_data, tmp);
-	g_free(tmp);
-}
-
 static void
 purple_proxy_connect_data_connected(PurpleProxyConnectData *connect_data)
 {
@@ -687,1572 +663,6 @@
 	purple_proxy_connect_data_destroy(connect_data);
 }
 
-static void
-socket_ready_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data = data;
-	int error = 0;
-	int ret;
-
-	/* If the socket-connected message had already been triggered when connect_data
- 	 * was destroyed via purple_proxy_connect_cancel(), we may get here with a freed connect_data.
- 	 */
-	if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data))
-		return;
-
-	purple_debug_info("proxy", "Connecting to %s:%d.\n",
-					connect_data->host, connect_data->port);
-
-	/*
-	 * purple_input_get_error after a non-blocking connect returns -1 if something is
-	 * really messed up (bad descriptor, usually). Otherwise, it returns 0 and
-	 * error holds what connect would have returned if it blocked until now.
-	 * Thus, error == 0 is success, error == EINPROGRESS means "try again",
-	 * and anything else is a real error.
-	 *
-	 * (error == EINPROGRESS can happen after a select because the kernel can
-	 * be overly optimistic sometimes. select is just a hint that you might be
-	 * able to do something.)
-	 */
-	ret = purple_input_get_error(connect_data->fd, &error);
-
-	if (ret == 0 && error == EINPROGRESS) {
-		/* No worries - we'll be called again later */
-		/* TODO: Does this ever happen? */
-		purple_debug_info("proxy", "(ret == 0 && error == EINPROGRESS)\n");
-		return;
-	}
-
-	if (ret != 0 || error != 0) {
-		if (ret != 0)
-			error = errno;
-		purple_debug_error("proxy", "Error connecting to %s:%d (%s).\n",
-						connect_data->host, connect_data->port, g_strerror(error));
-
-		purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-		return;
-	}
-
-	purple_proxy_connect_data_connected(connect_data);
-}
-
-static gboolean
-clean_connect(gpointer data)
-{
-	purple_proxy_connect_data_connected(data);
-
-	return FALSE;
-}
-
-static void
-proxy_connect_udp_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
-	purple_debug_info("proxy", "UDP Connecting to %s:%d with no proxy\n",
-			connect_data->host, connect_data->port);
-
-	connect_data->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
-	if (connect_data->fd < 0)
-	{
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to create socket: %s"), g_strerror(errno));
-		return;
-	}
-	_purple_network_set_common_socket_flags(connect_data->fd);
-
-	if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
-	{
-		if ((errno == EINPROGRESS) || (errno == EINTR))
-		{
-			purple_debug_info("proxy", "UDP connection in progress\n");
-			connect_data->inpa = purple_input_add(connect_data->fd,
-					PURPLE_INPUT_WRITE, socket_ready_cb, connect_data);
-		}
-		else
-		{
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-		}
-	}
-	else
-	{
-		/*
-		 * The connection happened IMMEDIATELY... strange, but whatever.
-		 */
-		int error = ETIMEDOUT;
-		int ret;
-
-		purple_debug_info("proxy", "UDP Connected immediately.\n");
-
-		ret = purple_input_get_error(connect_data->fd, &error);
-		if ((ret != 0) || (error != 0))
-		{
-			if (ret != 0)
-				error = errno;
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-			return;
-		}
-
-		/*
-		 * We want to call the "connected" callback eventually, but we
-		 * don't want to call it before we return, just in case.
-		 */
-		purple_timeout_add(10, clean_connect, connect_data);
-	}
-}
-
-static void
-proxy_connect_none(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
-	purple_debug_info("proxy", "Connecting to %s:%d with no proxy\n",
-			connect_data->host, connect_data->port);
-
-	connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
-	if (connect_data->fd < 0)
-	{
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to create socket: %s"), g_strerror(errno));
-		return;
-	}
-	_purple_network_set_common_socket_flags(connect_data->fd);
-
-	if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
-	{
-		if ((errno == EINPROGRESS) || (errno == EINTR))
-		{
-			purple_debug_info("proxy", "Connection in progress\n");
-			connect_data->inpa = purple_input_add(connect_data->fd,
-					PURPLE_INPUT_WRITE, socket_ready_cb, connect_data);
-		}
-		else
-		{
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-		}
-	}
-	else
-	{
-		/*
-		 * The connection happened IMMEDIATELY... strange, but whatever.
-		 */
-		int error = ETIMEDOUT;
-		int ret;
-
-		purple_debug_info("proxy", "Connected immediately.\n");
-
-		ret = purple_input_get_error(connect_data->fd, &error);
-		if ((ret != 0) || (error != 0))
-		{
-			if (ret != 0)
-				error = errno;
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-			return;
-		}
-
-		/*
-		 * We want to call the "connected" callback eventually, but we
-		 * don't want to call it before we return, just in case.
-		 */
-		purple_timeout_add(10, clean_connect, connect_data);
-	}
-}
-
-/*
- * This is a utility function used by the HTTP, SOCKS4 and SOCKS5
- * connect functions.  It writes data from a buffer to a socket.
- * When all the data is written it sets up a watcher to read a
- * response and call a specified function.
- */
-static void
-proxy_do_write(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data;
-	const guchar *request;
-	gsize request_len;
-	int ret;
-
-	connect_data = data;
-	request = connect_data->write_buffer + connect_data->written_len;
-	request_len = connect_data->write_buf_len - connect_data->written_len;
-
-	ret = write(connect_data->fd, request, request_len);
-	if (ret <= 0)
-	{
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-		return;
-	}
-	if ((gsize)ret < request_len) {
-		connect_data->written_len += ret;
-		return;
-	}
-
-	/* We're done writing data!  Wait for a response. */
-	g_free(connect_data->write_buffer);
-	connect_data->write_buffer = NULL;
-	purple_input_remove(connect_data->inpa);
-	connect_data->inpa = purple_input_add(connect_data->fd,
-			PURPLE_INPUT_READ, connect_data->read_cb, connect_data);
-}
-
-/*
- * We're using an HTTP proxy for a non-port 80 tunnel.  Read the
- * response to the CONNECT request.
- */
-static void
-http_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
-	int len, headers_len, status = 0;
-	gboolean error;
-	PurpleProxyConnectData *connect_data = data;
-	char *p;
-	gsize max_read;
-
-	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 8192;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	p = (char *)connect_data->read_buffer + connect_data->read_len;
-	max_read = connect_data->read_buf_len - connect_data->read_len - 1;
-
-	len = read(connect_data->fd, p, max_read);
-
-	if (len == 0) {
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (len < 0) {
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Lost connection with server: %s"), g_strerror(errno));
-		return;
-	}
-
-	connect_data->read_len += len;
-	p[len] = '\0';
-
-	p = g_strstr_len((const gchar *)connect_data->read_buffer,
-			connect_data->read_len, "\r\n\r\n");
-	if (p != NULL) {
-		*p = '\0';
-		headers_len = (p - (char *)connect_data->read_buffer) + 4;
-	} else if((gsize)len == max_read)
-		headers_len = len;
-	else
-		return;
-
-	error = strncmp((const char *)connect_data->read_buffer, "HTTP/", 5) != 0;
-	if (!error) {
-		int major;
-		p = (char *)connect_data->read_buffer + 5;
-		major = strtol(p, &p, 10);
-		error = (major == 0) || (*p != '.');
-		if(!error) {
-			int minor;
-			p++;
-			minor = strtol(p, &p, 10);
-			error = (*p != ' ');
-			if(!error) {
-				p++;
-				status = strtol(p, &p, 10);
-				error = (*p != ' ');
-				(void)minor; /* we don't need its value */
-			}
-		}
-	}
-
-	/* Read the contents */
-	p = g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: ");
-	if (p != NULL) {
-		gchar *tmp;
-		gsize content_len;
-		char tmpc;
-
-		p += strlen("Content-Length: ");
-		tmp = strchr(p, '\r');
-		if(tmp)
-			*tmp = '\0';
-		if (sscanf(p, "%" G_GSIZE_FORMAT, &content_len) != 1) {
-			/* Couldn't read content length */
-			purple_debug_error("proxy", "Couldn't read content length value "
-					"from %s\n", p);
-			if(tmp)
-				*tmp = '\r';
-			purple_proxy_connect_data_disconnect_formatted(connect_data,
-					_("Unable to parse response from HTTP proxy: %s"),
-					connect_data->read_buffer);
-			return;
-		}
-		if(tmp)
-			*tmp = '\r';
-
-		/* Compensate for what has already been read */
-		content_len -= connect_data->read_len - headers_len;
-		/* I'm assuming that we're doing this to prevent the server from
-		   complaining / breaking since we don't read the whole page */
-		while (content_len--) {
-			/* TODO: deal with EAGAIN (and other errors) better */
-			/* TODO: Reading 1 byte at a time is horrible and stupid. */
-			if (read(connect_data->fd, &tmpc, 1) < 0 && errno != EAGAIN)
-				break;
-		}
-	}
-
-	if (error) {
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to parse response from HTTP proxy: %s"),
-				connect_data->read_buffer);
-		return;
-	}
-	else if (status != 200) {
-		purple_debug_error("proxy",
-				"Proxy server replied with:\n%s\n",
-				connect_data->read_buffer);
-
-		if (status == 407 /* Proxy Auth */) {
-			const char *header;
-			gchar *request;
-
-			header = g_strrstr((const gchar *)connect_data->read_buffer,
-					"Proxy-Authenticate: NTLM");
-			if (header != NULL) {
-				const char *header_end = header + strlen("Proxy-Authenticate: NTLM");
-				const char *domain = purple_proxy_info_get_username(connect_data->gpi);
-				char *username = NULL, hostname[256];
-				gchar *response;
-				int ret;
-
-				ret = gethostname(hostname, sizeof(hostname));
-				hostname[sizeof(hostname) - 1] = '\0';
-				if (ret < 0 || hostname[0] == '\0') {
-					purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
-					g_strlcpy(hostname, "localhost", sizeof(hostname));
-				}
-
-				if (domain != NULL)
-					username = (char*) strchr(domain, '\\');
-				if (username == NULL) {
-					purple_proxy_connect_data_disconnect_formatted(connect_data,
-							_("HTTP proxy connection error %d"), status);
-					return;
-				}
-				*username = '\0';
-
-				/* Is there a message? */
-				if (*header_end == ' ') {
-					/* Check for Type-2 */
-					char *tmp = (char*) header;
-					guint8 *nonce;
-
-					header_end++;
-					username++;
-					while(*tmp != '\r' && *tmp != '\0') tmp++;
-					*tmp = '\0';
-					nonce = purple_ntlm_parse_type2(header_end, NULL);
-					response = purple_ntlm_gen_type3(username,
-						(gchar*) purple_proxy_info_get_password(connect_data->gpi),
-						hostname,
-						domain, nonce, NULL);
-					username--;
-				} else /* Empty message */
-					response = purple_ntlm_gen_type1(hostname, domain);
-
-				*username = '\\';
-
-				request = g_strdup_printf(
-					"CONNECT %s:%d HTTP/1.1\r\n"
-					"Host: %s:%d\r\n"
-					"Proxy-Authorization: NTLM %s\r\n"
-					"Proxy-Connection: Keep-Alive\r\n\r\n",
-					connect_data->host, connect_data->port,
-					connect_data->host, connect_data->port,
-					response);
-
-				g_free(response);
-
-			} else if (g_strrstr((const char *)connect_data->read_buffer, "Proxy-Authenticate: Basic") != NULL) {
-				gchar *t1, *t2;
-				const char *username, *password;
-
-				username = purple_proxy_info_get_username(connect_data->gpi);
-				password = purple_proxy_info_get_password(connect_data->gpi);
-
-				t1 = g_strdup_printf("%s:%s",
-									 username ? username : "",
-									 password ? password : "");
-				t2 = purple_base64_encode((guchar *)t1, strlen(t1));
-				g_free(t1);
-
-				request = g_strdup_printf(
-					"CONNECT %s:%d HTTP/1.1\r\n"
-					"Host: %s:%d\r\n"
-					"Proxy-Authorization: Basic %s\r\n",
-					connect_data->host, connect_data->port,
-					connect_data->host, connect_data->port,
-					t2);
-
-				g_free(t2);
-
-			} else {
-				purple_proxy_connect_data_disconnect_formatted(connect_data,
-						_("HTTP proxy connection error %d"), status);
-				return;
-			}
-
-			purple_input_remove(connect_data->inpa);
-			g_free(connect_data->read_buffer);
-			connect_data->read_buffer = NULL;
-
-			connect_data->write_buffer = (guchar *)request;
-			connect_data->write_buf_len = strlen(request);
-			connect_data->written_len = 0;
-
-			connect_data->read_cb = http_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, cond);
-
-			return;
-		}
-
-		if (status == 403) {
-			/* Forbidden */
-			purple_proxy_connect_data_disconnect_formatted(connect_data,
-					_("Access denied: HTTP proxy server forbids port %d tunneling"),
-					connect_data->port);
-		} else {
-			purple_proxy_connect_data_disconnect_formatted(connect_data,
-					_("HTTP proxy connection error %d"), status);
-		}
-	} else {
-		purple_input_remove(connect_data->inpa);
-		connect_data->inpa = 0;
-		g_free(connect_data->read_buffer);
-		connect_data->read_buffer = NULL;
-		purple_debug_info("proxy", "HTTP proxy connection established\n");
-		purple_proxy_connect_data_connected(connect_data);
-		return;
-	}
-}
-
-static void
-http_start_connect_tunneling(PurpleProxyConnectData *connect_data) {
-	GString *request;
-	int ret;
-
-	purple_debug_info("proxy", "Using CONNECT tunneling for %s:%d\n",
-		connect_data->host, connect_data->port);
-
-	request = g_string_sized_new(4096);
-	g_string_append_printf(request,
-			"CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n",
-			connect_data->host, connect_data->port,
-			connect_data->host, connect_data->port);
-
-	if (purple_proxy_info_get_username(connect_data->gpi) != NULL)
-	{
-		char *t1, *t2, *ntlm_type1;
-		char hostname[256];
-
-		ret = gethostname(hostname, sizeof(hostname));
-		hostname[sizeof(hostname) - 1] = '\0';
-		if (ret < 0 || hostname[0] == '\0') {
-			purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
-			g_strlcpy(hostname, "localhost", sizeof(hostname));
-		}
-
-		t1 = g_strdup_printf("%s:%s",
-			purple_proxy_info_get_username(connect_data->gpi),
-			purple_proxy_info_get_password(connect_data->gpi) ?
-				purple_proxy_info_get_password(connect_data->gpi) : "");
-		t2 = purple_base64_encode((const guchar *)t1, strlen(t1));
-		g_free(t1);
-
-		ntlm_type1 = purple_ntlm_gen_type1(hostname, "");
-
-		g_string_append_printf(request,
-			"Proxy-Authorization: Basic %s\r\n"
-			"Proxy-Authorization: NTLM %s\r\n"
-			"Proxy-Connection: Keep-Alive\r\n",
-			t2, ntlm_type1);
-		g_free(ntlm_type1);
-		g_free(t2);
-	}
-
-	g_string_append(request, "\r\n");
-
-	connect_data->write_buf_len = request->len;
-	connect_data->write_buffer = (guchar *)g_string_free(request, FALSE);
-	connect_data->written_len = 0;
-	connect_data->read_cb = http_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);
-}
-
-static void
-http_canwrite(gpointer data, gint source, PurpleInputCondition cond) {
-	PurpleProxyConnectData *connect_data = data;
-	int ret, error = ETIMEDOUT;
-
-	purple_debug_info("proxy", "Connected to %s:%d.\n",
-		connect_data->host, connect_data->port);
-
-	if (connect_data->inpa > 0)	{
-		purple_input_remove(connect_data->inpa);
-		connect_data->inpa = 0;
-	}
-
-	ret = purple_input_get_error(connect_data->fd, &error);
-	if (ret != 0 || error != 0) {
-		if (ret != 0)
-			error = errno;
-		purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-		return;
-	}
-
-	if (connect_data->port == 80) {
-		/*
-		 * If we're trying to connect to something running on
-		 * port 80 then we assume the traffic using this
-		 * connection is going to be HTTP traffic.  If it's
-		 * not then this will fail (uglily).  But it's good
-		 * to avoid using the CONNECT method because it's
-		 * not always allowed.
-		 */
-		purple_debug_info("proxy", "HTTP proxy connection established\n");
-		purple_proxy_connect_data_connected(connect_data);
-	} else {
-		http_start_connect_tunneling(connect_data);
-	}
-
-}
-
-static void
-proxy_connect_http(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
-	purple_debug_info("proxy",
-			   "Connecting to %s:%d via %s:%d using HTTP\n",
-			   connect_data->host, connect_data->port,
-			   (purple_proxy_info_get_host(connect_data->gpi) ? purple_proxy_info_get_host(connect_data->gpi) : "(null)"),
-			   purple_proxy_info_get_port(connect_data->gpi));
-
-	connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
-	if (connect_data->fd < 0)
-	{
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to create socket: %s"), g_strerror(errno));
-		return;
-	}
-	_purple_network_set_common_socket_flags(connect_data->fd);
-
-	if (connect(connect_data->fd, &addr->sa, addrlen) != 0) {
-		if (errno == EINPROGRESS || errno == EINTR) {
-			purple_debug_info("proxy", "HTTP connection in progress\n");
-
-			connect_data->inpa = purple_input_add(connect_data->fd,
-					PURPLE_INPUT_WRITE, http_canwrite, connect_data);
-		} else
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-	} else {
-		purple_debug_info("proxy", "Connected immediately.\n");
-
-		http_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-	}
-}
-
-static void
-s4_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data = data;
-	guchar *buf;
-	int len, max_read;
-
-	/* This is really not going to block under normal circumstances, but to
-	 * be correct, we deal with the unlikely scenario */
-
-	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 12;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	buf = connect_data->read_buffer + connect_data->read_len;
-	max_read = connect_data->read_buf_len - connect_data->read_len;
-
-	len = read(connect_data->fd, buf, max_read);
-
-	if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_data->read_len < 4))
-		return;
-	else if (len + connect_data->read_len >= 4) {
-		if (connect_data->read_buffer[1] == 90) {
-			purple_proxy_connect_data_connected(connect_data);
-			return;
-		}
-	}
-
-	purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-}
-
-static void
-s4_host_resolved(GObject *source_object, GAsyncResult *res, gpointer data)
-{
-	GInetAddress *address = NULL;
-	GError *error = NULL;
-	GList *hosts = NULL, *l = NULL;
-	PurpleProxyConnectData *connect_data = data;
-	unsigned char packet[9];
-
-	if(G_IS_CANCELLABLE(connect_data->cancellable)) {
-		g_object_unref(G_OBJECT(connect_data->cancellable));
-
-		connect_data->cancellable = NULL;
-	}
-
-	hosts = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object),
-			res, &error);
-
-	if (error->message != NULL) {
-		purple_proxy_connect_data_disconnect(connect_data, error->message);
-
-		g_error_free(error);
-
-		return;
-	}
-
-	if (hosts == NULL) {
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Error resolving %s"), connect_data->host);
-		return;
-	}
-
-	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))
-			break;
-
-		address = NULL;
-	}
-
-	if(address != NULL) {
-		packet[0] = 0x04;
-		packet[1] = 0x01;
-		packet[2] = connect_data->port >> 8;
-		packet[3] = connect_data->port & 0xff;
-		memcpy(packet + 4, g_inet_address_to_bytes(address), 4);
-		packet[8] = 0x00;
-
-		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);
-	} else {
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Error resolving %s"), connect_data->host);
-	}
-
-	g_resolver_free_addresses(hosts);
-}
-
-static void
-s4_canwrite(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data = data;
-	int error = ETIMEDOUT;
-	int ret;
-
-	purple_debug_info("socks4 proxy", "Connected.\n");
-
-	if (connect_data->inpa > 0) {
-		purple_input_remove(connect_data->inpa);
-		connect_data->inpa = 0;
-	}
-
-	ret = purple_input_get_error(connect_data->fd, &error);
-	if ((ret != 0) || (error != 0)) {
-		if (ret != 0)
-			error = errno;
-		purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-		return;
-	}
-
-	/*
-	 * The socks4 spec doesn't include support for doing host name lookups by
-	 * the proxy.  Many socks4 servers do this via the "socks4a" extension to
-	 * the protocol.  There doesn't appear to be a way to detect if a server
-	 * supports this, so we require that the user set a global option.
-	 */
-	if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) {
-		unsigned char packet[9];
-		int len;
-
-		purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n");
-
-		packet[0] = 0x04;
-		packet[1] = 0x01;
-		packet[2] = connect_data->port >> 8;
-		packet[3] = connect_data->port & 0xff;
-		packet[4] = 0x00;
-		packet[5] = 0x00;
-		packet[6] = 0x00;
-		packet[7] = 0x01;
-		packet[8] = 0x00;
-
-		len = sizeof(packet) + strlen(connect_data->host) + 1;
-
-		connect_data->write_buffer = g_malloc0(len);
-		memcpy(connect_data->write_buffer, packet, sizeof(packet));
-		memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host));
-		connect_data->write_buf_len = len;
-		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);
-	} else {
-		GResolver *resolver = NULL;
-
-		connect_data->cancellable = g_cancellable_new();
-
-		resolver = g_resolver_get_default();
-
-		g_resolver_lookup_by_name_async(resolver,
-		                                connect_data->host,
-		                                connect_data->cancellable,
-		                                s4_host_resolved,
-		                                connect_data);
-
-		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);
-		}
-	}
-}
-
-static void
-proxy_connect_socks4(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
-	purple_debug_info("proxy",
-			   "Connecting to %s:%d via %s:%d using SOCKS4\n",
-			   connect_data->host, connect_data->port,
-			   purple_proxy_info_get_host(connect_data->gpi),
-			   purple_proxy_info_get_port(connect_data->gpi));
-
-	connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
-	if (connect_data->fd < 0)
-	{
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to create socket: %s"), g_strerror(errno));
-		return;
-	}
-	_purple_network_set_common_socket_flags(connect_data->fd);
-
-	if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
-	{
-		if ((errno == EINPROGRESS) || (errno == EINTR))
-		{
-			purple_debug_info("proxy", "SOCKS4 connection in progress\n");
-			connect_data->inpa = purple_input_add(connect_data->fd,
-					PURPLE_INPUT_WRITE, s4_canwrite, connect_data);
-		}
-		else
-		{
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-		}
-	}
-	else
-	{
-		purple_debug_info("proxy", "Connected immediately.\n");
-
-		s4_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-	}
-}
-
-static gboolean
-s5_ensure_buffer_length(PurpleProxyConnectData *connect_data, guint len)
-{
-	if(connect_data->read_len < len) {
-		if(connect_data->read_buf_len < len) {
-			/* it's not just that we haven't read enough, it's that we haven't tried to read enough yet */
-			purple_debug_info("s5", "reallocing from %" G_GSIZE_FORMAT
-					" to %d\n", connect_data->read_buf_len, len);
-			connect_data->read_buf_len = len;
-			connect_data->read_buffer = g_realloc(connect_data->read_buffer, connect_data->read_buf_len);
-		}
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-s5_canread_again(gpointer data, gint source, PurpleInputCondition cond)
-{
-	guchar *dest, *buf;
-	PurpleProxyConnectData *connect_data = data;
-	int len;
-
-	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 5;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	dest = connect_data->read_buffer + connect_data->read_len;
-	buf = connect_data->read_buffer;
-
-	len = read(connect_data->fd, dest, (connect_data->read_buf_len - connect_data->read_len));
-
-	if (len == 0)
-	{
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (len < 0)
-	{
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Lost connection with server: %s"), g_strerror(errno));
-		return;
-	}
-
-	connect_data->read_len += len;
-
-	if(connect_data->read_len < 4)
-		return;
-
-	if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
-		if ((buf[0] == 0x05) && (buf[1] < 0x09)) {
-			purple_debug_error("socks5 proxy", "%s", socks5errors[buf[1]]);
-			purple_proxy_connect_data_disconnect(connect_data,
-					socks5errors[buf[1]]);
-		} else {
-			purple_debug_error("socks5 proxy", "Bad data.\n");
-			purple_proxy_connect_data_disconnect(connect_data,
-					_("Received invalid data on connection with server"));
-		}
-		return;
-	}
-
-	/* Skip past BND.ADDR */
-	switch(buf[3]) {
-		case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */
-			if(!s5_ensure_buffer_length(connect_data, 4 + 4))
-				return;
-			buf += 4 + 4;
-			break;
-		case 0x03: /* the address field contains a fully-qualified domain name.  The first
-					  octet of the address field contains the number of octets of name that
-					  follow, there is no terminating NUL octet. */
-			if(!s5_ensure_buffer_length(connect_data, 4 + 1))
-				return;
-			buf += 4;
-			if(!s5_ensure_buffer_length(connect_data, 4 + 1 + buf[0]))
-				return;
-			buf += buf[0] + 1;
-			break;
-		case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */
-			if(!s5_ensure_buffer_length(connect_data, 4 + 16))
-				return;
-			buf += 4 + 16;
-			break;
-		default:
-			purple_debug_error("socks5 proxy", "Invalid ATYP received (0x%X)\n", buf[3]);
-			purple_proxy_connect_data_disconnect(connect_data,
-					_("Received invalid data on connection with server"));
-			return;
-	}
-
-	/* Skip past BND.PORT */
-	if(!s5_ensure_buffer_length(connect_data, (buf - connect_data->read_buffer) + 2))
-		return;
-
-	purple_proxy_connect_data_connected(connect_data);
-}
-
-static void
-s5_sendconnect(gpointer data, int source)
-{
-	PurpleProxyConnectData *connect_data = data;
-	size_t hlen = strlen(connect_data->host);
-	connect_data->write_buf_len = 5 + hlen + 2;
-	connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
-	connect_data->written_len = 0;
-
-	connect_data->write_buffer[0] = 0x05;
-	connect_data->write_buffer[1] = 0x01;		/* CONNECT */
-	connect_data->write_buffer[2] = 0x00;		/* reserved */
-	connect_data->write_buffer[3] = 0x03;		/* address type -- host name */
-	connect_data->write_buffer[4] = hlen;
-	memcpy(connect_data->write_buffer + 5, connect_data->host, hlen);
-	connect_data->write_buffer[5 + hlen] = connect_data->port >> 8;
-	connect_data->write_buffer[5 + hlen + 1] = connect_data->port & 0xff;
-
-	connect_data->read_cb = s5_canread_again;
-
-	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);
-}
-
-static void
-s5_readauth(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data = data;
-	int len;
-
-	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 2;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	purple_debug_info("socks5 proxy", "Got auth response.\n");
-
-	len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
-		connect_data->read_buf_len - connect_data->read_len);
-
-	if (len == 0)
-	{
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (len < 0)
-	{
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Lost connection with server: %s"), g_strerror(errno));
-		return;
-	}
-
-	connect_data->read_len += len;
-	if (connect_data->read_len < 2)
-		return;
-
-	purple_input_remove(connect_data->inpa);
-	connect_data->inpa = 0;
-
-	if ((connect_data->read_buffer[0] != 0x01) || (connect_data->read_buffer[1] != 0x00)) {
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Received invalid data on connection with server"));
-		return;
-	}
-
-	g_free(connect_data->read_buffer);
-	connect_data->read_buffer = NULL;
-
-	s5_sendconnect(connect_data, connect_data->fd);
-}
-
-static void
-hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response)
-{
-	PurpleHash *hash;
-	int i;
-	unsigned char Kxoripad[65];
-	unsigned char Kxoropad[65];
-	size_t pwlen;
-
-	hash = purple_md5_hash_new();
-
-	memset(Kxoripad,0,sizeof(Kxoripad));
-	memset(Kxoropad,0,sizeof(Kxoropad));
-
-	pwlen=strlen(passwd);
-	if (pwlen>64) {
-		purple_hash_append(hash, (const guchar *)passwd, strlen(passwd));
-		purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad));
-		pwlen=16;
-	} else {
-		memcpy(Kxoripad, passwd, pwlen);
-	}
-	memcpy(Kxoropad,Kxoripad,pwlen);
-
-	for (i=0;i<64;i++) {
-		Kxoripad[i]^=0x36;
-		Kxoropad[i]^=0x5c;
-	}
-
-	purple_hash_reset(hash);
-	purple_hash_append(hash, Kxoripad, 64);
-	purple_hash_append(hash, challenge, challen);
-	purple_hash_digest(hash, Kxoripad, sizeof(Kxoripad));
-
-	purple_hash_reset(hash);
-	purple_hash_append(hash, Kxoropad, 64);
-	purple_hash_append(hash, Kxoripad, 16);
-	purple_hash_digest(hash, response, 16);
-
-	g_object_unref(hash);
-}
-
-static void
-s5_readchap(gpointer data, gint source, PurpleInputCondition cond);
-
-/*
- * Return how many bytes we processed
- * -1 means we've shouldn't keep reading from the buffer
- */
-static gssize
-s5_parse_chap_msg(PurpleProxyConnectData *connect_data)
-{
-	guchar *buf, *cmdbuf = connect_data->read_buffer;
-	int len, navas, currentav;
-
-	purple_debug_misc("socks5 proxy", "Reading CHAP message: %x\n", *cmdbuf);
-
-	if (*cmdbuf != 0x01) {
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Received invalid data on connection with server"));
-		return -1;
-	}
-	cmdbuf++;
-
-	navas = *cmdbuf;
-
-	purple_debug_misc("socks5 proxy", "Expecting %d attribute(s).\n", navas);
-	if (G_UNLIKELY(navas < 0 || navas > 10000)) { /* XXX: what's the threshold? */
-		purple_proxy_connect_data_disconnect(connect_data,
-			_("Received invalid data on connection with server"));
-		return -1;
-	}
-
-	cmdbuf++;
-
-	for (currentav = 0; currentav < navas; currentav++) {
-
-		len = connect_data->read_len - (cmdbuf - connect_data->read_buffer);
-		/* We don't have enough data to even know how long the next attribute is,
-		 * or we don't have the full length of the next attribute. */
-		if (len < 2 || len < (cmdbuf[1] + 2)) {
-			/* Clear out the attributes that have been read - decrease the attribute count */
-			connect_data->read_buffer[1] = navas - currentav;
-			/* Move the unprocessed data into the first attribute position */
-			memmove((connect_data->read_buffer + 2), cmdbuf, len);
-			/* Decrease the read count accordingly */
-			connect_data->read_len = len + 2;
-
-			purple_debug_info("socks5 proxy", "Need more data to retrieve attribute %d.\n", currentav);
-
-			return -1;
-		}
-
-		buf = cmdbuf + 2;
-
-		if (cmdbuf[1] == 0) {
-			purple_debug_error("socks5 proxy", "Attribute %x Value length of 0; ignoring.\n", cmdbuf[0]);
-			cmdbuf = buf;
-			continue;
-		}
-
-		switch (cmdbuf[0]) {
-			case 0x00:
-				purple_debug_info("socks5 proxy", "Received STATUS of %x\n", buf[0]);
-				/* Did auth work? */
-				if (buf[0] == 0x00) {
-					purple_input_remove(connect_data->inpa);
-					connect_data->inpa = 0;
-					g_free(connect_data->read_buffer);
-					connect_data->read_buffer = NULL;
-					/* Success */
-					s5_sendconnect(connect_data, connect_data->fd);
-				} else {
-					/* Failure */
-					purple_debug_warning("proxy",
-						"socks5 CHAP authentication "
-						"failed.  Disconnecting...");
-					purple_proxy_connect_data_disconnect(connect_data,
-							_("Authentication failed"));
-				}
-				return -1;
-			case 0x01:
-				/* We've already validated that cmdbuf[1] is sane. */
-				purple_debug_info("socks5 proxy", "Received TEXT-MESSAGE of '%.*s'\n", (int) cmdbuf[1], buf);
-				break;
-			case 0x03:
-				purple_debug_info("socks5 proxy", "Received CHALLENGE\n");
-				/* Server wants our credentials */
-
-				connect_data->write_buf_len = 16 + 4;
-				connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
-				connect_data->written_len = 0;
-
-				hmacmd5_chap(buf, cmdbuf[1],
-					purple_proxy_info_get_password(connect_data->gpi),
-					connect_data->write_buffer + 4);
-				/* TODO: What about USER-IDENTITY? */
-				connect_data->write_buffer[0] = 0x01;
-				connect_data->write_buffer[1] = 0x01;
-				connect_data->write_buffer[2] = 0x04;
-				connect_data->write_buffer[3] = 0x10;
-
-				purple_input_remove(connect_data->inpa);
-				g_free(connect_data->read_buffer);
-				connect_data->read_buffer = NULL;
-
-				connect_data->read_cb = s5_readchap;
-
-				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);
-				return -1;
-			case 0x11:
-				purple_debug_info("socks5 proxy", "Received ALGORIGTHMS of %x\n", buf[0]);
-				/* Server wants to select an algorithm */
-				if (buf[0] != 0x85) {
-					/* Only currently support HMAC-MD5 */
-					purple_debug_warning("proxy",
-						"Server tried to select an "
-						"algorithm that we did not advertise "
-						"as supporting.  This is a violation "
-						"of the socks5 CHAP specification.  "
-						"Disconnecting...");
-					purple_proxy_connect_data_disconnect(connect_data,
-							_("Received invalid data on connection with server"));
-					return -1;
-				}
-				break;
-			default:
-				purple_debug_info("socks5 proxy", "Received unused command %x, length=%d\n", cmdbuf[0], cmdbuf[1]);
-		}
-		cmdbuf = buf + cmdbuf[1];
-	}
-
-	return (cmdbuf - connect_data->read_buffer);
-}
-
-static void
-s5_readchap(gpointer data, gint source, PurpleInputCondition cond)
-{
-	gssize msg_ret;
-	PurpleProxyConnectData *connect_data = data;
-	int len;
-
-	purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n");
-
-	if (connect_data->read_buffer == NULL) {
-		/* A big enough butfer to read the message header (2 bytes) and at least one complete attribute and value (1 + 1 + 255). */
-		connect_data->read_buf_len = 259;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	if (connect_data->read_buf_len - connect_data->read_len == 0) {
-		/*If the stuff below is right, this shouldn't be possible. */
-		purple_debug_error("socks5 proxy", "This is about to suck because the read buffer is full (shouldn't happen).\n");
-	}
-
-	len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
-		connect_data->read_buf_len - connect_data->read_len);
-
-	if (len == 0) {
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (len < 0) {
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Lost connection with server: %s"), g_strerror(errno));
-		return;
-	}
-
-	connect_data->read_len += len;
-
-	/* We may have read more than one message into the buffer, we need to make sure to process them all */
-	while (1) {
-
-		/* We need more to be able to read this message */
-		if (connect_data->read_len < 2)
-			return;
-
-		msg_ret = s5_parse_chap_msg(connect_data);
-
-		if (msg_ret < 0)
-			return;
-
-		/* See if we have another message already in the buffer */
-		if ((len = connect_data->read_len - msg_ret) > 0) {
-
-			/* Move on to the next message */
-			memmove(connect_data->read_buffer, connect_data->read_buffer + msg_ret, len);
-			/* Decrease the read count accordingly */
-			connect_data->read_len = len;
-
-			/* Try to read the message that connect_data->read_buffer now points to */
-			continue;
-		}
-
-		break;
-	}
-
-	/* Fell through.  We ran out of CHAP events to process, but haven't
-	 * succeeded or failed authentication - there may be more to come.
-	 * If this is the case, come straight back here. */
-
-	purple_debug_info("socks5 proxy", "Waiting for another message from which to read CHAP info.\n");
-
-	/* We've processed all the available attributes, so get ready for a whole new message */
- 	g_free(connect_data->read_buffer);
-	connect_data->read_buffer = NULL;
-}
-
-static void
-s5_canread(gpointer data, gint source, PurpleInputCondition cond)
-{
-	PurpleProxyConnectData *connect_data = data;
-	int len;
-
-	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 2;
-		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
-		connect_data->read_len = 0;
-	}
-
-	purple_debug_info("socks5 proxy", "Able to read.\n");
-
-	len = read(connect_data->fd, connect_data->read_buffer + connect_data->read_len,
-		connect_data->read_buf_len - connect_data->read_len);
-
-	if (len == 0)
-	{
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Server closed the connection"));
-		return;
-	}
-
-	if (len < 0)
-	{
-		if (errno == EAGAIN)
-			/* No worries */
-			return;
-
-		/* Error! */
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Lost connection with server: %s"), g_strerror(errno));
-		return;
-	}
-
-	connect_data->read_len += len;
-	if (connect_data->read_len < 2)
-		return;
-
-	purple_input_remove(connect_data->inpa);
-	connect_data->inpa = 0;
-
-	if ((connect_data->read_buffer[0] != 0x05) || (connect_data->read_buffer[1] == 0xff)) {
-		purple_proxy_connect_data_disconnect(connect_data,
-				_("Received invalid data on connection with server"));
-		return;
-	}
-
-	if (connect_data->read_buffer[1] == 0x02) {
-		size_t i, j;
-		const char *u, *p;
-
-		u = purple_proxy_info_get_username(connect_data->gpi);
-		p = purple_proxy_info_get_password(connect_data->gpi);
-
-		i = (u == NULL) ? 0 : strlen(u);
-		j = (p == NULL) ? 0 : strlen(p);
-
-		connect_data->write_buf_len = 1 + 1 + i + 1 + j;
-		connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
-		connect_data->written_len = 0;
-
-		connect_data->write_buffer[0] = 0x01;	/* version 1 */
-		connect_data->write_buffer[1] = i;
-		if (u != NULL)
-			memcpy(connect_data->write_buffer + 2, u, i);
-		connect_data->write_buffer[2 + i] = j;
-		if (p != NULL)
-			memcpy(connect_data->write_buffer + 2 + i + 1, p, j);
-
-		g_free(connect_data->read_buffer);
-		connect_data->read_buffer = NULL;
-
-		connect_data->read_cb = s5_readauth;
-
-		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);
-
-		return;
-	} else if (connect_data->read_buffer[1] == 0x03) {
-		size_t userlen;
-		userlen = strlen(purple_proxy_info_get_username(connect_data->gpi));
-
-		connect_data->write_buf_len = 7 + userlen;
-		connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
-		connect_data->written_len = 0;
-
-		connect_data->write_buffer[0] = 0x01;
-		connect_data->write_buffer[1] = 0x02;
-		connect_data->write_buffer[2] = 0x11;
-		connect_data->write_buffer[3] = 0x01;
-		connect_data->write_buffer[4] = 0x85;
-		connect_data->write_buffer[5] = 0x02;
-		connect_data->write_buffer[6] = userlen;
-		memcpy(connect_data->write_buffer + 7,
-			purple_proxy_info_get_username(connect_data->gpi), userlen);
-
-		g_free(connect_data->read_buffer);
-		connect_data->read_buffer = NULL;
-
-		connect_data->read_cb = s5_readchap;
-
-		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);
-
-		return;
-	} else {
-		g_free(connect_data->read_buffer);
-		connect_data->read_buffer = NULL;
-
-		s5_sendconnect(connect_data, connect_data->fd);
-	}
-}
-
-static void
-s5_canwrite(gpointer data, gint source, PurpleInputCondition cond)
-{
-	unsigned char buf[5];
-	int i;
-	PurpleProxyConnectData *connect_data = data;
-	int error = ETIMEDOUT;
-	int ret;
-
-	purple_debug_info("socks5 proxy", "Connected.\n");
-
-	if (connect_data->inpa > 0)
-	{
-		purple_input_remove(connect_data->inpa);
-		connect_data->inpa = 0;
-	}
-
-	ret = purple_input_get_error(connect_data->fd, &error);
-	if ((ret != 0) || (error != 0))
-	{
-		if (ret != 0)
-			error = errno;
-		purple_proxy_connect_data_disconnect(connect_data, g_strerror(error));
-		return;
-	}
-
-	buf[0] = 0x05;		/* SOCKS version 5 */
-
-	if (purple_proxy_info_get_username(connect_data->gpi) != NULL) {
-		buf[1] = 0x03;	/* three methods */
-		buf[2] = 0x00;	/* no authentication */
-		buf[3] = 0x03;	/* CHAP authentication */
-		buf[4] = 0x02;	/* username/password authentication */
-		i = 5;
-	}
-	else {
-		buf[1] = 0x01;
-		buf[2] = 0x00;
-		i = 3;
-	}
-
-	connect_data->write_buf_len = i;
-	connect_data->write_buffer = g_malloc(connect_data->write_buf_len);
-	memcpy(connect_data->write_buffer, buf, i);
-
-	connect_data->read_cb = s5_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);
-}
-
-static void
-proxy_connect_socks5(PurpleProxyConnectData *connect_data, common_sockaddr_t *addr, socklen_t addrlen)
-{
-	purple_debug_info("proxy",
-			   "Connecting to %s:%d via %s:%d using SOCKS5\n",
-			   connect_data->host, connect_data->port,
-			   purple_proxy_info_get_host(connect_data->gpi),
-			   purple_proxy_info_get_port(connect_data->gpi));
-
-	connect_data->fd = socket(addr->sa.sa_family, SOCK_STREAM, 0);
-	if (connect_data->fd < 0)
-	{
-		purple_proxy_connect_data_disconnect_formatted(connect_data,
-				_("Unable to create socket: %s"), g_strerror(errno));
-		return;
-	}
-	_purple_network_set_common_socket_flags(connect_data->fd);
-
-	if (connect(connect_data->fd, &addr->sa, addrlen) != 0)
-	{
-		if ((errno == EINPROGRESS) || (errno == EINTR))
-		{
-			purple_debug_info("proxy", "SOCKS5 connection in progress\n");
-			connect_data->inpa = purple_input_add(connect_data->fd,
-					PURPLE_INPUT_WRITE, s5_canwrite, connect_data);
-		}
-		else
-		{
-			purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno));
-		}
-	}
-	else
-	{
-		purple_debug_info("proxy", "Connected immediately.\n");
-
-		s5_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE);
-	}
-}
-
-/*
- * This function attempts to connect to the next IP address in the list
- * of IP addresses returned to us by purple_dnsquery_a() and attempts
- * to connect to each one.  This is called after the hostname is
- * resolved, and each time a connection attempt fails (assuming there
- * is another IP address to try).
- */
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
-#endif
-
-static void try_connect(PurpleProxyConnectData *connect_data)
-{
-	GInetAddress *address = NULL;
-	GSocketAddress *socket_address = NULL;
-	GError *error = NULL;
-	char *ipaddr;
-
-	common_sockaddr_t addr;
-	socklen_t addrlen = 0;
-
-	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);
-	g_free(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);
-	if(error != NULL) {
-		purple_debug_info("proxy", "failed connnection : %s\n", error->message);
-
-		g_error_free(error);
-
-		return;
-	}
-
-	if (connect_data->socket_type == SOCK_DGRAM) {
-		proxy_connect_udp_none(connect_data, &addr, addrlen);
-
-		return;
-	}
-
-	switch (purple_proxy_info_get_proxy_type(connect_data->gpi)) {
-		case PURPLE_PROXY_NONE:
-			proxy_connect_none(connect_data, &addr, addrlen);
-			break;
-
-		case PURPLE_PROXY_HTTP:
-			proxy_connect_http(connect_data, &addr, addrlen);
-			break;
-
-		case PURPLE_PROXY_SOCKS4:
-			proxy_connect_socks4(connect_data, &addr, addrlen);
-			break;
-
-		case PURPLE_PROXY_SOCKS5:
-		case PURPLE_PROXY_TOR:
-			proxy_connect_socks5(connect_data, &addr, addrlen);
-			break;
-
-		case PURPLE_PROXY_USE_ENVVAR:
-			proxy_connect_http(connect_data, &addr, addrlen);
-			break;
-
-		default:
-			break;
-	}
-
-	g_object_unref(G_OBJECT(socket_address));
-}
-
-static void
-connection_host_resolved(GObject *source, GAsyncResult *res, gpointer data) {
-	PurpleProxyConnectData *connect_data = (PurpleProxyConnectData *)data;
-	GError *error = NULL;
-	GList *addresses = NULL;
-
-	addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(source),
-			res, &error);
-
-	if(G_IS_CANCELLABLE(connect_data->cancellable)) {
-		g_object_unref(G_OBJECT(connect_data->cancellable));
-
-		connect_data->cancellable = NULL;
-	}
-
-	if (error != NULL) {
-		purple_proxy_connect_data_disconnect(connect_data, error->message);
-
-		g_error_free(error);
-
-		g_resolver_free_addresses(addresses);
-
-		return;
-	}
-
-	if (addresses == NULL) {
-		purple_proxy_connect_data_disconnect(connect_data, _("Unable to resolve hostname"));
-
-		return;
-	}
-
-	connect_data->hosts = addresses;
-
-	try_connect(connect_data);
-}
-
 PurpleProxyInfo *
 purple_proxy_get_setup(PurpleAccount *account)
 {
@@ -2444,84 +854,6 @@
 	return connect_data;
 }
 
-PurpleProxyConnectData *
-purple_proxy_connect_udp(void *handle, PurpleAccount *account,
-				   const char *host, int port,
-				   PurpleProxyConnectFunction connect_cb, gpointer data)
-{
-	const char *connecthost = host;
-	int connectport = port;
-	PurpleProxyConnectData *connect_data;
-	GResolver *resolver;
-
-	g_return_val_if_fail(host       != NULL, NULL);
-	g_return_val_if_fail(port       >  0,    NULL);
-	g_return_val_if_fail(connect_cb != NULL, NULL);
-
-	connect_data = g_new0(PurpleProxyConnectData, 1);
-	connect_data->fd = -1;
-	connect_data->socket_type = SOCK_DGRAM;
-	connect_data->handle = handle;
-	connect_data->connect_cb = connect_cb;
-	connect_data->data = data;
-	connect_data->host = g_strdup(host);
-	connect_data->port = port;
-	connect_data->gpi = purple_proxy_get_setup(account);
-	connect_data->account = account;
-
-	if ((purple_proxy_info_get_proxy_type(connect_data->gpi) != PURPLE_PROXY_NONE) &&
-		(purple_proxy_info_get_host(connect_data->gpi) == NULL ||
-		 purple_proxy_info_get_port(connect_data->gpi) <= 0)) {
-
-		purple_notify_error(NULL, NULL, _("Invalid proxy settings"),
-			_("Either the host name or port number specified for "
-			"your given proxy type is invalid."),
-			purple_request_cpar_from_account(account));
-		purple_proxy_connect_data_destroy(connect_data);
-		return NULL;
-	}
-
-	switch (purple_proxy_info_get_proxy_type(connect_data->gpi))
-	{
-		case PURPLE_PROXY_NONE:
-			break;
-
-		case PURPLE_PROXY_HTTP:
-		case PURPLE_PROXY_SOCKS4:
-		case PURPLE_PROXY_SOCKS5:
-		case PURPLE_PROXY_TOR:
-		case PURPLE_PROXY_USE_ENVVAR:
-			purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n",
-			                  purple_proxy_info_get_proxy_type(connect_data->gpi));
-			break;
-
-		default:
-			purple_debug_error("proxy", "Invalid Proxy type (%d) specified.\n",
-			                   purple_proxy_info_get_proxy_type(connect_data->gpi));
-			purple_proxy_connect_data_destroy(connect_data);
-			return NULL;
-	}
-
-	connect_data->cancellable = g_cancellable_new();
-
-	resolver = g_resolver_get_default();
-	g_resolver_lookup_by_name_async(resolver,
-	                                connecthost,
-	                                connect_data->cancellable,
-	                                connection_host_resolved,
-	                                connect_data);
-	g_object_unref(resolver);
-
-	if (connect_data->cancellable == NULL) {
-		purple_proxy_connect_data_destroy(connect_data);
-		return NULL;
-	}
-
-	handles = g_slist_prepend(handles, connect_data);
-
-	return connect_data;
-}
-
 static void
 socks5_proxy_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
 {
--- a/libpurple/proxy.h	Tue Jan 12 20:41:07 2016 -0600
+++ b/libpurple/proxy.h	Sun Jan 10 03:23:46 2016 -0600
@@ -277,36 +277,6 @@
 			PurpleProxyConnectFunction connect_cb, gpointer data);
 
 /**
- * purple_proxy_connect_udp:
- * @handle:     A handle that should be associated with this
- *              connection attempt.  The handle can be used
- *              to cancel the connection attempt using the
- *              purple_proxy_connect_cancel_with_handle()
- *              function.
- * @account:    The account making the connection.
- * @host:       The destination host.
- * @port:       The destination port.
- * @connect_cb: (scope call): The function to call when the connection is
- *              established.  If the connection failed then
- *              fd will be -1 and error message will be set
- *              to something descriptive (hopefully).
- * @data:       User-defined data.
- *
- * Makes a connection to the specified host and port.  Note that this
- * function name can be misleading--although it is called "proxy
- * connect," it is used for establishing any outgoing UDP connection,
- * whether through a proxy or not.
- *
- * Returns: NULL if there was an error, or a reference to an
- *         opaque data structure that can be used to cancel
- *         the pending connection, if needed.
- */
-PurpleProxyConnectData *purple_proxy_connect_udp(void *handle,
-			PurpleAccount *account,
-			const char *host, int port,
-			PurpleProxyConnectFunction connect_cb, gpointer data);
-
-/**
  * purple_proxy_connect_socks5_account:
  * @handle:     A handle that should be associated with this
  *              connection attempt.  The handle can be used

mercurial