pidgin: 15e75311: Add support for using multiple "xmpp-cli...

datallah at pidgin.im datallah at pidgin.im
Sun Jul 27 18:40:44 EDT 2008


-----------------------------------------------------------------
Revision: 15e75311f3c17e8f6415b5402bd75382239031d0
Ancestor: 7d23f027f9930d251c8b02cffe010c08b3fc906f
Author: datallah at pidgin.im
Date: 2008-07-27T22:34:32
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/15e75311f3c17e8f6415b5402bd75382239031d0

Modified files:
        libpurple/protocols/jabber/jabber.c
        libpurple/protocols/jabber/jabber.h

ChangeLog: 

Add support for using multiple "xmpp-client" records on a domain, by trying the
records in order until one succeeds (or we exhaust them all).
This currently will also fall back to the server based on the user's jid.
Fixes #6436.

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/jabber.c	f005b3dede749de2f533f11c1c70a8575f2ef47a
+++ libpurple/protocols/jabber/jabber.c	3a2f2be65d204fb20ab6f34b6ef55ea578c61d1f
@@ -63,6 +63,7 @@ static void jabber_unregister_account_cb
 GList *jabber_features = NULL;
 
 static void jabber_unregister_account_cb(JabberStream *js);
+static void try_srv_connect(JabberStream *js);
 
 static void jabber_stream_init(JabberStream *js)
 {
@@ -520,15 +521,23 @@ jabber_login_callback(gpointer data, gin
 	JabberStream *js = gc->proto_data;
 
 	if (source < 0) {
-		gchar *tmp;
-		tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
-				error);
-		purple_connection_error_reason (gc,
-				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-		g_free(tmp);
+		if (js->srv_rec != NULL) {
+			purple_debug_error("jabber", "Unable to connect to server: %s.  Trying next SRV record.\n", error);
+			try_srv_connect(js);
+		} else {
+			gchar *tmp;
+			tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
+					      error);
+			purple_connection_error_reason(gc,
+					PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+			g_free(tmp);
+		}
 		return;
 	}
 
+	g_free(js->srv_rec);
+	js->srv_rec = NULL;
+
 	js->fd = source;
 
 	if(js->state == JABBER_STREAM_CONNECTING)
@@ -563,37 +572,62 @@ static void tls_init(JabberStream *js)
 			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
 }
 
-static void jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port)
+static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port,
+				 gboolean fatal_failure)
 {
 	/* host should be used in preference to domain to
 	 * allow SASL authentication to work with FQDN of the server,
 	 * but we use domain as fallback for when users enter IP address
 	 * in connect server */
+	g_free(js->serverFQDN);
 	if (purple_ip_address_is_valid(host))
 		js->serverFQDN = g_strdup(domain);
 	else
 		js->serverFQDN = g_strdup(host);
 
 	if (purple_proxy_connect(js->gc, js->gc->account, host,
-			port, jabber_login_callback, js->gc) == NULL)
-		purple_connection_error_reason (js->gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Unable to create socket"));
+			port, jabber_login_callback, js->gc) == NULL) {
+		if (fatal_failure) {
+			purple_connection_error_reason (js->gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				_("Unable to create socket"));
+		}
+
+		return FALSE;
+	}
+
+	return TRUE;
 }
 
+static void try_srv_connect(JabberStream *js)
+{
+	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(js->gc->account, "port", 5222), TRUE);
+}
+
 static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data)
 {
-	JabberStream *js;
-
-	js = data;
+	JabberStream *js = data;
 	js->srv_query_data = NULL;
 
 	if(results) {
-		jabber_login_connect(js, resp->hostname, resp->hostname, resp->port);
-		g_free(resp);
+		js->srv_rec = resp;
+		js->srv_rec_idx = 0;
+		js->max_srv_rec_idx = results;
+		try_srv_connect(js);
 	} else {
 		jabber_login_connect(js, js->user->domain, js->user->domain,
-			purple_account_get_int(js->gc->account, "port", 5222));
+			purple_account_get_int(js->gc->account, "port", 5222), TRUE);
 	}
 }
 
@@ -675,7 +709,7 @@ jabber_login(PurpleAccount *account)
 	 * invoke the magic of SRV lookups, to figure out host and port */
 	if(!js->gsc) {
 		if(connect_server[0]) {
-			jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222));
+			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("xmpp-client",
 					"tcp", js->user->domain, srv_resolved_cb, js);
@@ -1156,7 +1190,7 @@ void jabber_register_account(PurpleAccou
 		if (connect_server[0]) {
 			jabber_login_connect(js, js->user->domain, server,
 			                     purple_account_get_int(account,
-			                                          "port", 5222));
+			                                          "port", 5222), TRUE);
 		} else {
 			js->srv_query_data = purple_srv_resolve("xmpp-client",
 			                                      "tcp",
@@ -1327,9 +1361,12 @@ void jabber_close(PurpleConnection *gc)
 
 	if (js->keepalive_timeout != -1)
 		purple_timeout_remove(js->keepalive_timeout);
-	
+
 	g_free(js);
 
+	g_free(js->srv_rec);
+	js->srv_rec = NULL;
+
 	gc->proto_data = NULL;
 }
 
============================================================
--- libpurple/protocols/jabber/jabber.h	9ac68a50935a4f775fff15e205e9dc61dff2843c
+++ libpurple/protocols/jabber/jabber.h	5db2ebb103d8d20a03087bd9cf27aab964a68bb3
@@ -201,6 +201,10 @@ struct _JabberStream
 	
 	/* A purple timeout tag for the keepalive */
 	int keepalive_timeout;
+
+	PurpleSrvResponse *srv_rec;
+	guint srv_rec_idx;
+	guint max_srv_rec_idx;
 };
 
 typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *shortname, const gchar *namespace);


More information about the Commits mailing list