Mercurial > pidgin
diff libpurple/protocols/jabber/jabber.c @ 25125:907ca9a36fe0
explicit merge of '714a7c7f903d11c96ffade34966121da549d998f'
and 'd2c40fe4e2181eda5c1c631c7805f17e6b5d22c3'
to branch 'org.darkrain42.pidgin.xmpp'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 20 Nov 2008 21:13:56 +0000 |
parents | a03a953ba63d ba362a67278c |
children | 9ab681f23007 |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c Mon Aug 18 17:08:01 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Thu Nov 20 21:13:56 2008 +0000 @@ -68,6 +68,7 @@ GHashTable *jabber_contact_info = NULL; static void jabber_unregister_account_cb(JabberStream *js); +static void try_srv_connect(JabberStream *js); static void jabber_stream_init(JabberStream *js) { @@ -278,9 +279,42 @@ purple_circ_buffer_mark_read(js->write_buffer, ret); } +static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len) +{ + int ret; + gboolean success = TRUE; + + if (len == -1) + len = strlen(data); + + if (js->writeh == 0) + ret = jabber_do_send(js, data, len); + else { + ret = -1; + errno = EAGAIN; + } + + if (ret < 0 && errno != EAGAIN) { + purple_connection_error_reason (js->gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Write error")); + success = FALSE; + } else if (ret < len) { + if (ret < 0) + ret = 0; + if (js->writeh == 0) + js->writeh = purple_input_add( + js->gsc ? js->gsc->fd : js->fd, + PURPLE_INPUT_WRITE, jabber_send_cb, js); + purple_circ_buffer_append(js->write_buffer, + data + ret, len - ret); + } + + return success; +} + void jabber_send_raw(JabberStream *js, const char *data, int len) { - int ret; /* because printing a tab to debug every minute gets old */ if(strcmp(data, "\t")) @@ -289,55 +323,33 @@ /* If we've got a security layer, we need to encode the data, * splitting it on the maximum buffer length negotiated */ - + purple_signal_emit(my_protocol, "jabber-sending-text", js->gc, &data); if (data == NULL) return; - + #ifdef HAVE_CYRUS_SASL if (js->sasl_maxbuf>0) { - int pos; + int pos = 0; if (!js->gsc && js->fd<0) return; - pos = 0; + if (len == -1) len = strlen(data); + while (pos < len) { int towrite; const char *out; unsigned olen; - if ((len - pos) < js->sasl_maxbuf) - towrite = len - pos; - else - towrite = js->sasl_maxbuf; + towrite = MIN((len - pos), js->sasl_maxbuf); sasl_encode(js->sasl, &data[pos], towrite, &out, &olen); pos += towrite; - if (js->writeh == 0) - ret = jabber_do_send(js, out, olen); - else { - ret = -1; - errno = EAGAIN; - } - - if (ret < 0 && errno != EAGAIN) - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Write error")); - else if (ret < olen) { - if (ret < 0) - ret = 0; - if (js->writeh == 0) - js->writeh = purple_input_add( - js->gsc ? js->gsc->fd : js->fd, - PURPLE_INPUT_WRITE, - jabber_send_cb, js); - purple_circ_buffer_append(js->write_buffer, - out + ret, olen - ret); - } + if (!do_jabber_send_raw(js, out, olen)) + break; } return; } @@ -354,29 +366,8 @@ _("Someone tried to send non-XML in a Jabber world.")); } } else { - if (js->writeh == 0) - ret = jabber_do_send(js, data, len); - else { - ret = -1; - errno = EAGAIN; - } - - if (ret < 0 && errno != EAGAIN) - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Write error")); - else if (ret < len) { - if (ret < 0) - ret = 0; - if (js->writeh == 0) - js->writeh = purple_input_add( - js->gsc ? js->gsc->fd : js->fd, - PURPLE_INPUT_WRITE, jabber_send_cb, js); - purple_circ_buffer_append(js->write_buffer, - data + ret, len - ret); - } + do_jabber_send_raw(js, data, len); } - return; } int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len) @@ -402,9 +393,9 @@ g_free(txt); } -static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer timeout) +static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) { - purple_timeout_remove(GPOINTER_TO_INT(timeout)); + purple_timeout_remove(js->keepalive_timeout); js->keepalive_timeout = -1; } @@ -428,7 +419,7 @@ xmlnode_set_namespace(ping, "urn:xmpp:ping"); js->keepalive_timeout = purple_timeout_add_seconds(120, (GSourceFunc)(jabber_pong_timeout), gc); - jabber_iq_set_callback(iq, jabber_pong_cb, GINT_TO_POINTER(js->keepalive_timeout)); + jabber_iq_set_callback(iq, jabber_pong_cb, NULL); jabber_iq_send(iq); } } @@ -457,12 +448,17 @@ jabber_stream_init(js); } - if(errno == EAGAIN) + if(len < 0 && errno == EAGAIN) return; - else + else { + if (len == 0) + purple_debug_info("jabber", "Server closed the connection.\n"); + else + purple_debug_info("jabber", "Disconnected: %s\n", g_strerror(errno)); purple_connection_error_reason (js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Read Error")); + } } static void @@ -497,9 +493,13 @@ jabber_parser_process(js, buf, len); if(js->reinit) jabber_stream_init(js); - } else if(errno == EAGAIN) { + } else if(len < 0 && errno == EAGAIN) { return; } else { + if (len == 0) + purple_debug_info("jabber", "Server closed the connection.\n"); + else + purple_debug_info("jabber", "Disconnected: %s\n", g_strerror(errno)); purple_connection_error_reason (js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Read Error")); @@ -578,11 +578,19 @@ JabberStream *js = gc->proto_data; if (source < 0) { - purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); - purple_txt_resolve("_xmppconnect", js->user->domain, txt_resolved_cb, gc); + 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 { + purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); + purple_txt_resolve("_xmppconnect", js->user->domain, txt_resolved_cb, gc); + } return; } + g_free(js->srv_rec); + js->srv_rec = NULL; + js->fd = source; if(js->state == JABBER_STREAM_CONNECTING) @@ -617,37 +625,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); } } @@ -729,7 +762,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); @@ -1210,7 +1243,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", @@ -1381,7 +1414,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;