This should do it for XMPP use-gresolver

Fri, 18 Dec 2015 18:26:12 -0600

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 18 Dec 2015 18:26:12 -0600
branch
use-gresolver
changeset 37457
0b957b80c46a
parent 37456
697c2cfa4123
child 37458
2539f27ecd73

This should do it for XMPP

libpurple/protocols/jabber/disco.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/google/jingleinfo.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/jabber.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/jabber.h file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/jabber/disco.c	Fri Dec 18 18:25:55 2015 -0600
+++ b/libpurple/protocols/jabber/disco.c	Fri Dec 18 18:26:12 2015 -0600
@@ -419,77 +419,39 @@
 
 }
 
-/* should probably share this code with google.c, or maybe from 2.7.0
- introduce an abstracted hostname -> IP function in dns.c */
 static void
-jabber_disco_stun_lookup_cb(GSList *hosts, gpointer data,
-	const char *error_message)
-{
+jabber_disco_stun_srv_resolve_cb(GObject *sender, GAsyncResult *result, gpointer data) {
+	GError *error = NULL;
+	GList *services = NULL;
 	JabberStream *js = (JabberStream *) data;
+	gint results = 0;
 
-	if (error_message) {
-		purple_debug_error("jabber", "STUN lookup failed: %s\n",
-			error_message);
-		g_slist_free(hosts);
-		js->stun_query = NULL;
+	services = g_resolver_lookup_service_finish(g_resolver_get_default(), result, &error);
+
+	if(error != NULL) {
+		purple_debug_info("jabber", "Failed to look up a STUN record : %s\n", error->message);
+
+		g_error_free(error);
+
 		return;
 	}
 
-	if (hosts && g_slist_next(hosts)) {
-		common_sockaddr_t addr;
-		char dst[INET6_ADDRSTRLEN];
-		int port;
+	results = g_list_length(services);
 
-		memcpy(&addr, g_slist_next(hosts)->data, sizeof(addr));
+	purple_debug_info("jabber", "got %d SRV responses for STUN.\n", results);
 
-		if (addr.sa.sa_family == AF_INET6) {
-			inet_ntop(addr.sa.sa_family, &addr.in6.sin6_addr,
-				dst, sizeof(dst));
-			port = ntohs(addr.in6.sin6_port);
-		} else {
-			inet_ntop(addr.sa.sa_family, &addr.in.sin_addr,
-				dst, sizeof(dst));
-			port = ntohs(addr.in.sin_port);
-		}
+	if (results > 0) {
+		GSrvTarget *target = (GSrvTarget *)services->data;
+		const gchar *hostname = g_srv_target_get_hostname(target);
 
-		if (js->stun_ip)
-			g_free(js->stun_ip);
-		js->stun_ip = g_strdup(dst);
-		js->stun_port = port;
+		js->stun_ip = g_strdup(hostname);
+		js->stun_port = g_srv_target_get_port(target);
 
-		purple_debug_info("jabber", "set STUN IP/port address: "
-		                  "%s:%d\n", dst, port);
-
-		/* unmark ongoing query */
-		js->stun_query = NULL;
+		purple_debug_info("jabber", "set stun address to %s:%d\n",
+			hostname, js->stun_port);
 	}
 
-	while (hosts != NULL) {
-		hosts = g_slist_delete_link(hosts, hosts);
-		/* Free the address */
-		g_free(hosts->data);
-		hosts = g_slist_delete_link(hosts, hosts);
-	}
-}
-
-
-static void
-jabber_disco_stun_srv_resolve_cb(PurpleSrvResponse *resp, int results, gpointer data)
-{
-	JabberStream *js = (JabberStream *) data;
-
-	purple_debug_info("jabber", "got %d SRV responses for STUN.\n", results);
-	js->srv_query_data = NULL;
-
-	if (results > 0) {
-		PurpleAccount *account;
-		purple_debug_info("jabber", "looking up IP for %s:%d\n",
-			resp[0].hostname, resp[0].port);
-		account = purple_connection_get_account(js->gc);
-		js->stun_query =
-			purple_dnsquery_a(account, resp[0].hostname, resp[0].port,
-				jabber_disco_stun_lookup_cb, js);
-	}
+	g_resolver_free_targets(services);
 }
 
 
@@ -553,11 +515,14 @@
 			}
 		} else if (purple_network_get_stun_ip() == NULL ||
 		    purple_strequal(purple_network_get_stun_ip(), "")) {
-			js->srv_query_data =
-				purple_srv_resolve(
-					purple_connection_get_account(js->gc), "stun", "udp",
-					js->user->domain,
-					jabber_disco_stun_srv_resolve_cb, js);
+
+			g_resolver_lookup_service_async(g_resolver_get_default(),
+			                                "stun",
+			                                "udp",
+			                                js->user->domain,
+			                                NULL,
+			                                jabber_disco_stun_srv_resolve_cb,
+			                                js);
 			/* TODO: add TURN support later... */
 		}
 	}
--- a/libpurple/protocols/jabber/google/jingleinfo.c	Fri Dec 18 18:25:55 2015 -0600
+++ b/libpurple/protocols/jabber/google/jingleinfo.c	Fri Dec 18 18:26:12 2015 -0600
@@ -22,55 +22,36 @@
 #include "debug.h"
 #include "jingleinfo.h"
 
+#include <gio/gio.h>
+
 static void
-jabber_google_stun_lookup_cb(GSList *hosts, gpointer data,
-	const char *error_message)
-{
+jabber_google_stun_lookup_cb(GObject *sender, GAsyncResult *result, gpointer data) {
+	GError *error = NULL;
+	GList *addresses = NULL;
 	JabberStream *js = (JabberStream *) data;
 
-	if (error_message) {
+	addresses = g_resolver_lookup_by_name_finish(g_resolver_get_default(), result, &error);
+
+	if(error) {
 		purple_debug_error("jabber", "Google STUN lookup failed: %s\n",
-			error_message);
-		g_slist_free(hosts);
-		js->stun_query = NULL;
+			error->message);
+
+		g_error_free(error);
+
 		return;
 	}
 
-	if (hosts && g_slist_next(hosts)) {
-		common_sockaddr_t addr;
-		char dst[INET6_ADDRSTRLEN];
-		int port;
-
-		memcpy(&addr, g_slist_next(hosts)->data, sizeof(addr));
+	if(g_list_length(addresses) > 0) {
+		GInetAddress *inet_address = G_INET_ADDRESS(addresses->data);
 
-		if (addr.sa.sa_family == AF_INET6) {
-			inet_ntop(addr.sa.sa_family, &addr.in6.sin6_addr,
-				dst, sizeof(dst));
-			port = ntohs(addr.in6.sin6_port);
-		} else {
-			inet_ntop(addr.sa.sa_family, &addr.in.sin_addr,
-				dst, sizeof(dst));
-			port = ntohs(addr.in.sin_port);
-		}
-
-		if (js->stun_ip)
-			g_free(js->stun_ip);
-		js->stun_ip = g_strdup(dst);
-		js->stun_port = port;
+		g_free(js->stun_ip);
+		js->stun_ip = g_inet_address_to_string(inet_address);
 
 		purple_debug_info("jabber", "set Google STUN IP/port address: "
-		                  "%s:%d\n", dst, port);
-
-		/* unmark ongoing query */
-		js->stun_query = NULL;
+		                  "%s:%d\n", js->stun_ip, js->stun_port);
 	}
 
-	while (hosts != NULL) {
-		hosts = g_slist_delete_link(hosts, hosts);
-		/* Free the address */
-		g_free(hosts->data);
-		hosts = g_slist_delete_link(hosts, hosts);
-	}
+	g_resolver_free_addresses(addresses);
 }
 
 static void
@@ -111,16 +92,13 @@
 			const gchar *udp = purple_xmlnode_get_attrib(server, "udp");
 
 			if (host && udp) {
-				PurpleAccount *account;
-				int port = atoi(udp);
-				/* if there, would already be an ongoing query,
-				 cancel it */
-				if (js->stun_query)
-					purple_dnsquery_destroy(js->stun_query);
+				js->stun_port = atoi(udp);
 
-				account = purple_connection_get_account(js->gc);
-				js->stun_query = purple_dnsquery_a(account, host, port,
-					jabber_google_stun_lookup_cb, js);
+				g_resolver_lookup_by_name_async(g_resolver_get_default(),
+				                                host,
+				                                NULL,
+				                                jabber_google_stun_lookup_cb,
+				                                js);
 			}
 		}
 	}
--- a/libpurple/protocols/jabber/jabber.c	Fri Dec 18 18:25:55 2015 -0600
+++ b/libpurple/protocols/jabber/jabber.c	Fri Dec 18 18:26:12 2015 -0600
@@ -30,7 +30,6 @@
 #include "connection.h"
 #include "conversation.h"
 #include "debug.h"
-#include "dnssrv.h"
 #include "http.h"
 #include "message.h"
 #include "notify.h"
@@ -95,7 +94,6 @@
 static gint plugin_ref = 0;
 
 static void jabber_unregister_account_cb(JabberStream *js);
-static void try_srv_connect(JabberStream *js);
 
 static void jabber_stream_init(JabberStream *js)
 {
@@ -765,28 +763,54 @@
 }
 
 static void
-txt_resolved_cb(GList *responses, gpointer data)
+txt_resolved_cb(GObject *sender, GAsyncResult *result, gpointer data)
 {
+	GError *error = NULL;
+	GList *records = NULL, *l = NULL;
 	JabberStream *js = data;
 	gboolean found = FALSE;
 
-	js->srv_query_data = NULL;
-
-	while (responses) {
-		PurpleTxtResponse *resp = responses->data;
-		gchar **token;
-		token = g_strsplit(purple_txt_response_get_content(resp), "=", 2);
-		if (!strcmp(token[0], "_xmpp-client-xbosh")) {
-			purple_debug_info("jabber","Found alternative connection method using %s at %s.\n", token[0], token[1]);
-			js->bosh = jabber_bosh_connection_new(js, token[1]);
+	records = g_resolver_lookup_service_finish(g_resolver_get_default(), result, &error);
+	if(error) {
+		purple_debug_warning("jabber", "Unable to find alternative XMPP connection "
+				  "methods after failing to connect directly. : %s\n",
+				  error->message);
+
+		purple_connection_error(js->gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				_("Unable to connect"));
+
+		g_error_free(error);
+
+		return;
+	}
+
+	for(l = records; l; l = l->next) {
+		GVariantIter *iter = NULL;
+		gchar *str = NULL;
+
+		g_variant_get((GVariant *)l->data, "(as)", &iter);
+		while(g_variant_iter_loop(iter, "s", &str)) {
+			gchar **token = g_strsplit(str, "=", 2);
+
+			if(!g_ascii_strcasecmp(token[0], "_xmpp-client-xbosh")) {
+				purple_debug_info("jabber","Found alternative connection method using %s at %s.\n", token[0], token[1]);
+
+				js->bosh = jabber_bosh_connection_new(js, token[1]);
+
+				g_strfreev(token);
+
+				break;
+			}
+
 			g_strfreev(token);
-			break;
 		}
-		g_strfreev(token);
-		purple_txt_response_destroy(resp);
-		responses = g_list_delete_link(responses, responses);
+
+		g_variant_iter_free(iter);
 	}
 
+	g_list_free_full(records, (GDestroyNotify)g_variant_unref);
+
 	if (js->bosh)
 		found = TRUE;
 
@@ -798,11 +822,6 @@
 				_("Unable to connect"));
 		return;
 	}
-
-	if (responses) {
-		g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-		g_list_free(responses);
-	}
 }
 
 static void
@@ -812,21 +831,21 @@
 	JabberStream *js = purple_connection_get_protocol_data(gc);
 
 	if (source < 0) {
-		if (js->srv_rec != NULL) {
-			purple_debug_error("jabber", "Unable to connect to server: %s.  Trying next SRV record or connecting directly.\n", error);
-			try_srv_connect(js);
-		} else {
-			purple_debug_info("jabber","Couldn't connect directly to %s.  Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
-			js->srv_query_data = purple_txt_resolve(
-					purple_connection_get_account(gc), "_xmppconnect",
-					js->user->domain, txt_resolved_cb, js);
-		}
+		gchar *name = g_strdup_printf("_xmppconnect.%s", js->user->domain);
+
+		purple_debug_info("jabber", "Couldn't connect directly to %s.  Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
+
+		g_resolver_lookup_records_async(g_resolver_get_default(),
+		                                name,
+		                                G_RESOLVER_RECORD_TXT,
+		                                js->cancellable,
+		                                txt_resolved_cb,
+		                                js);
+		g_free(name);
+
 		return;
 	}
 
-	g_free(js->srv_rec);
-	js->srv_rec = NULL;
-
 	js->fd = source;
 
 	if(js->state == JABBER_STREAM_CONNECTING)
@@ -888,37 +907,43 @@
 	return TRUE;
 }
 
-static void try_srv_connect(JabberStream *js)
+static void
+srv_resolved_cb(GObject *sender, GAsyncResult *result, gpointer data)
 {
-	while (js->srv_rec != NULL && js->srv_rec_idx < js->max_srv_rec_idx) {
-		PurpleSrvResponse *tmp_resp = js->srv_rec + (js->srv_rec_idx++);
-		if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE))
-			return;
-	}
-
-	g_free(js->srv_rec);
-	js->srv_rec = NULL;
-
-	/* Fall back to the defaults (I'm not sure if we should actually do this) */
-	jabber_login_connect(js, js->user->domain, js->user->domain,
-			purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
-			TRUE);
-}
-
-static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data)
-{
+	GError *error = NULL;
+	GList *targets = NULL, *l = NULL;
 	JabberStream *js = data;
-	js->srv_query_data = NULL;
-
-	if(results) {
-		js->srv_rec = resp;
-		js->srv_rec_idx = 0;
-		js->max_srv_rec_idx = results;
-		try_srv_connect(js);
-	} else {
+
+	targets = g_resolver_lookup_service_finish(g_resolver_get_default(), result, &error);
+	if(error) {
+		purple_debug_warning("jabber",
+		                     "SRV lookup failed, proceeding with normal connection : %s",
+		                     error->message);
+
+		g_error_free(error);
+
 		jabber_login_connect(js, js->user->domain, js->user->domain,
 				purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
 				TRUE);
+
+	} else {
+		for(l = targets; l; l = l->next) {
+			GSrvTarget *target = (GSrvTarget *)l->data;
+			const gchar *hostname = g_srv_target_get_hostname(target);
+			guint port = g_srv_target_get_port(target);
+
+			if(jabber_login_connect(js, hostname, hostname, port, FALSE)) {
+				g_resolver_free_targets(targets);
+
+				return;
+			}
+		}
+
+		g_resolver_free_targets(targets);
+
+		jabber_login_connect(js, js->user->domain, js->user->domain,
+				purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
+				TRUE);		
 	}
 }
 
@@ -937,6 +962,9 @@
 	js->fd = -1;
 	js->http_conns = purple_http_connection_set_new();
 
+	/* we might want to expose this at some point */
+	js->cancellable = g_cancellable_new();
+
 	user = g_strdup(purple_account_get_username(account));
 	/* jabber_id_new doesn't accept "user@domain/" as valid */
 	slash = strchr(user, '/');
@@ -1007,7 +1035,6 @@
 	js->sessions = NULL;
 	js->stun_ip = NULL;
 	js->stun_port = 0;
-	js->stun_query = NULL;
 	js->google_relay_token = NULL;
 	js->google_relay_host = NULL;
 
@@ -1075,8 +1102,13 @@
 		jabber_login_connect(js, js->user->domain, connect_server,
 				purple_account_get_int(account, "port", 5222), TRUE);
 	} else {
-		js->srv_query_data = purple_srv_resolve(account, "xmpp-client",
-				"tcp", js->user->domain, srv_resolved_cb, js);
+		g_resolver_lookup_service_async(g_resolver_get_default(),
+		                                "xmpp-client",
+		                                "tcp",
+		                                js->user->domain,
+		                                js->cancellable,
+		                                srv_resolved_cb,
+		                                js);
 	}
 }
 
@@ -1608,9 +1640,6 @@
 	} else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
 		jabber_send_raw(js, "</stream:stream>", -1);
 
-	if (js->srv_query_data)
-		purple_srv_txt_query_destroy(js->srv_query_data);
-
 	if(js->gsc) {
 		purple_ssl_close(js->gsc);
 	} else if (js->fd > 0) {
@@ -1706,17 +1735,10 @@
 	if (js->conn_close_timeout != 0)
 		purple_timeout_remove(js->conn_close_timeout);
 
-	g_free(js->srv_rec);
-	js->srv_rec = NULL;
+	g_cancellable_cancel(js->cancellable);
+	g_object_unref(G_OBJECT(js->cancellable));
 
 	g_free(js->stun_ip);
-	js->stun_ip = NULL;
-
-	/* cancel DNS query for STUN, if one is ongoing */
-	if (js->stun_query) {
-		purple_dnsquery_destroy(js->stun_query);
-		js->stun_query = NULL;
-	}
 
 	/* remove Google relay-related stuff */
 	g_free(js->google_relay_token);
--- a/libpurple/protocols/jabber/jabber.h	Fri Dec 18 18:25:55 2015 -0600
+++ b/libpurple/protocols/jabber/jabber.h	Fri Dec 18 18:26:12 2015 -0600
@@ -56,10 +56,10 @@
 
 #include <libxml/parser.h>
 #include <glib.h>
+#include <gio/gio.h>
+
 #include "circularbuffer.h"
 #include "connection.h"
-#include "dnsquery.h"
-#include "dnssrv.h"
 #include "http.h"
 #include "media.h"
 #include "mediamanager.h"
@@ -119,7 +119,7 @@
 	int fd;
 	guint inpa;
 
-	PurpleSrvTxtQueryData *srv_query_data;
+	GCancellable *cancellable;
 
 	xmlParserCtxt *context;
 	PurpleXmlNode *current;
@@ -276,10 +276,6 @@
 	guint inactivity_timer;
 	guint conn_close_timeout;
 
-	PurpleSrvResponse *srv_rec;
-	guint srv_rec_idx;
-	guint max_srv_rec_idx;
-
 	PurpleJabberBOSHConnection *bosh;
 
 	PurpleHttpConnectionSet *http_conns;
@@ -290,7 +286,6 @@
 	/* maybe this should only be present when USE_VV? */
 	gchar *stun_ip;
 	int stun_port;
-	PurpleDnsQueryData *stun_query;
 
 	/* stuff for Google's relay handling */
 	gchar *google_relay_token;

mercurial