# HG changeset patch # User Daniel Atallah # Date 1217203020 0 # Node ID d48d333e6ef5b0ebebba1ee06a49f3a4cd2ad1e0 # Parent 10382f1e1353b0a59f459bd3d8e544c0d8ff5e87# Parent 429cd88862fdcf69f43c85cec980537550702d74 merge of 'e9179f6992531a71364a9bb343ed1c64938f6fc9' and 'fe5690f538eb9373e340948a63c43511ec3ba199' diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/jabber/disco.c Sun Jul 27 23:57:00 2008 +0000 @@ -73,6 +73,15 @@ "jid='%s' host='%s' port='%d' zeroconf='%s'\n", from ? from : "", sh->host ? sh->host : "", sh->port, sh->zeroconf ? sh->zeroconf : ""); + + /* TODO: When we support zeroconf proxies, fix this to handle them */ + if (!(sh->jid && sh->host && sh->port > 0)) { + g_free(sh->jid); + g_free(sh->host); + g_free(sh->zeroconf); + g_free(sh); + js->bs_proxies = g_list_remove(js->bs_proxies, sh); + } } @@ -329,6 +338,7 @@ static void jabber_disco_finish_server_info_result_cb(JabberStream *js) { + const char *ft_proxies; jabber_vcard_fetch_mine(js); @@ -339,11 +349,44 @@ /* Send initial presence; this will trigger receipt of presence for contacts on the roster */ jabber_presence_send(js->gc->account, NULL); - + if (js->server_caps & JABBER_CAP_ADHOC) { /* The server supports ad-hoc commands, so let's request the list */ jabber_adhoc_server_get_list(js); } + + /* If there are manually specified bytestream proxies, query them */ + ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL); + if (ft_proxies) { + JabberIq *iq; + JabberBytestreamsStreamhost *sh; + int i; + char *tmp; + gchar **ft_proxy_list = g_strsplit(ft_proxies, ",", 0); + + for(i = 0; ft_proxy_list[i]; i++) { + g_strstrip(ft_proxy_list[i]); + if(!(*ft_proxy_list[i])) + continue; + + /* We used to allow specifying a port directly here; get rid of it */ + if((tmp = strchr(ft_proxy_list[i], ':'))) + *tmp = '\0'; + + sh = g_new0(JabberBytestreamsStreamhost, 1); + sh->jid = g_strdup(ft_proxy_list[i]); + js->bs_proxies = g_list_prepend(js->bs_proxies, sh); + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, + "http://jabber.org/protocol/bytestreams"); + xmlnode_set_attrib(iq->node, "to", sh->jid); + jabber_iq_set_callback(iq, jabber_disco_bytestream_server_cb, sh); + jabber_iq_send(iq); + } + + g_strfreev(ft_proxy_list); + } + } static void diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Jul 27 23:57:00 2008 +0000 @@ -63,6 +63,7 @@ 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 @@ 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 @@ 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 @@ * 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 @@ 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,7 +1361,10 @@ if (js->keepalive_timeout != -1) purple_timeout_remove(js->keepalive_timeout); - + + g_free(js->srv_rec); + js->srv_rec = NULL; + g_free(js); gc->proto_data = NULL; diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.h Sun Jul 27 23:57:00 2008 +0000 @@ -201,6 +201,10 @@ /* 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); diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Sun Jul 27 23:57:00 2008 +0000 @@ -236,7 +236,7 @@ option = purple_account_option_string_new(_("File transfer proxies"), "ft_proxies", /* TODO: Is this an acceptable default? */ - "proxy.jabber.org:7777"); + "proxy.jabber.org"); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/jabber/si.c Sun Jul 27 23:57:00 2008 +0000 @@ -721,7 +721,6 @@ JabberSIXfer *jsx; JabberIq *iq; xmlnode *query, *streamhost; - const char *ft_proxies; char port[6]; GList *tmp; JabberBytestreamsStreamhost *sh, *sh2; @@ -785,52 +784,6 @@ jabber_si_xfer_bytestreams_send_connected_cb, xfer); } - /* insert proxies here */ - ft_proxies = purple_account_get_string(xfer->account, "ft_proxies", NULL); - if (ft_proxies) { - int i, portnum; - char *tmp; - gchar **ft_proxy_list = g_strsplit(ft_proxies, ",", 0); - - g_list_foreach(jsx->streamhosts, jabber_si_free_streamhost, NULL); - g_list_free(jsx->streamhosts); - jsx->streamhosts = NULL; - - for(i = 0; ft_proxy_list[i]; i++) { - g_strstrip(ft_proxy_list[i]); - if(!(*ft_proxy_list[i])) - continue; - - if((tmp = strchr(ft_proxy_list[i], ':'))) { - portnum = atoi(tmp + 1); - *tmp = '\0'; - } else - portnum = 7777; - - g_snprintf(port, sizeof(port), "%hu", portnum); - - purple_debug_info("jabber", "jabber_si_xfer_bytestreams_listen_cb() will be looking at jsx %p: jsx->streamhosts %p and ft_proxy_list[%i] %p\n", - jsx, jsx->streamhosts, i, ft_proxy_list[i]); - if(g_list_find_custom(jsx->streamhosts, ft_proxy_list[i], jabber_si_compare_jid) != NULL) - continue; - - streamhost_count++; - streamhost = xmlnode_new_child(query, "streamhost"); - xmlnode_set_attrib(streamhost, "jid", ft_proxy_list[i]); - xmlnode_set_attrib(streamhost, "host", ft_proxy_list[i]); - xmlnode_set_attrib(streamhost, "port", port); - - sh = g_new0(JabberBytestreamsStreamhost, 1); - sh->jid = g_strdup(ft_proxy_list[i]); - sh->host = g_strdup(ft_proxy_list[i]); - sh->port = portnum; - - jsx->streamhosts = g_list_prepend(jsx->streamhosts, sh); - } - - g_strfreev(ft_proxy_list); - } - for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) { sh = tmp->data; diff -r 429cd88862fd -r d48d333e6ef5 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Jul 25 18:50:54 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sun Jul 27 23:57:00 2008 +0000 @@ -1512,6 +1512,7 @@ /* Suspended account */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended.")); break; + case 0x02: case 0x14: /* service temporarily unavailable */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable."));