Fri, 18 Dec 2015 18:26:12 -0600
This should do it for XMPP
--- 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;