Mercurial > pidgin
diff libpurple/protocols/bonjour/jabber.c @ 21734:d4c01ceb50a1
Fix #4189 to make the bonjour prpl more standards compliant by sending the stream response in the correct order. Thanks to Sjoerd Simons from Telepathy Salut for noticing.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Mon, 03 Dec 2007 01:18:37 +0000 |
parents | fded60f269bc |
children | b7e914cd1773 |
line wrap: on
line diff
--- a/libpurple/protocols/bonjour/jabber.c Sun Dec 02 22:02:34 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon Dec 03 01:18:37 2007 +0000 @@ -62,6 +62,12 @@ #define DOCTYPE "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" \ "<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"%s\" to=\"%s\">" +enum sent_stream_start_types { + NOT_SENT = 0, + PARTIALLY_SENT = 1, + FULLY_SENT = 2 +}; + static void xep_iq_parse(xmlnode *packet, PurpleConnection *connection, PurpleBuddy *pb); @@ -100,6 +106,8 @@ bconv->rx_handler = 0; bconv->pb = pb; + bonjour_parser_setup(bconv); + return bconv; } @@ -289,7 +297,7 @@ /* If we're not ready to actually send, append it to the buffer */ if (bconv->tx_handler != 0 || bconv->connect_data != NULL - || !bconv->sent_stream_start + || bconv->sent_stream_start != FULLY_SENT || !bconv->recv_stream_start || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { ret = -1; @@ -319,6 +327,7 @@ } if (ret < len) { + /* Don't interfere with the stream starting */ if (bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); @@ -409,20 +418,6 @@ } } -void bonjour_jabber_stream_started(PurpleBuddy *pb) { - BonjourBuddy *bb = pb->proto_data; - BonjourJabberConversation *bconv = bb->conversation; - - /* If the stream has been completely started, we can start doing stuff */ - if (bconv->sent_stream_start && bconv->recv_stream_start && purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { - /* Watch for when we can write the buffered messages */ - bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, - _send_data_write_cb, pb); - /* We can probably write the data right now. */ - _send_data_write_cb(pb, bconv->socket, PURPLE_INPUT_WRITE); - } - -} struct _stream_start_data { char *msg; @@ -478,14 +473,13 @@ /* Stream started; process the send buffer if there is one */ purple_input_remove(bconv->tx_handler); - bconv->tx_handler= 0; - bconv->sent_stream_start = TRUE; + bconv->tx_handler = 0; + bconv->sent_stream_start = FULLY_SENT; bonjour_jabber_stream_started(pb); - } -static gboolean bonjour_jabber_stream_init(PurpleBuddy *pb, int client_socket) +static gboolean bonjour_jabber_send_stream_init(PurpleBuddy *pb, int client_socket) { int ret, len; char *stream_start; @@ -495,6 +489,8 @@ purple_buddy_get_name(pb)); len = strlen(stream_start); + bb->conversation->sent_stream_start = PARTIALLY_SENT; + /* Start the stream */ ret = send(client_socket, stream_start, len, 0); @@ -521,18 +517,55 @@ bb->conversation->tx_handler = purple_input_add(client_socket, PURPLE_INPUT_WRITE, _start_stream, pb); } else - bb->conversation->sent_stream_start = TRUE; + bb->conversation->sent_stream_start = FULLY_SENT; g_free(stream_start); - /* setup the parser fresh for each stream */ - bonjour_parser_setup(bb->conversation); + return TRUE; +} + +static gboolean +_async_bonjour_jabber_close_conversation(gpointer data) { + BonjourJabberConversation *bconv = data; + bonjour_jabber_close_conversation(bconv); + return FALSE; +} + +void bonjour_jabber_stream_started(PurpleBuddy *pb) { + BonjourBuddy *bb = pb->proto_data; + BonjourJabberConversation *bconv = bb->conversation; + + if (bconv->sent_stream_start == NOT_SENT && !bonjour_jabber_send_stream_init(pb, bconv->socket)) { + const char *err = g_strerror(errno); + PurpleConversation *conv; + + purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n", + purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)"); - bb->conversation->socket = client_socket; - bb->conversation->rx_handler = purple_input_add(client_socket, - PURPLE_INPUT_READ, _client_socket_handler, pb); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account); + if (conv != NULL) + purple_conversation_write(conv, NULL, + _("Unable to send the message, the conversation couldn't be started."), + PURPLE_MESSAGE_SYSTEM, time(NULL)); - return TRUE; + close(bconv->socket); + /* This must be asynchronous because it destroys the parser and we + * may be in the middle of parsing. + */ + purple_timeout_add(0, _async_bonjour_jabber_close_conversation, bb->conversation); + bb->conversation = NULL; + return; + } + + /* If the stream has been completely started, we can start doing stuff */ + if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start && purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { + /* Watch for when we can write the buffered messages */ + bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, + _send_data_write_cb, pb); + /* We can probably write the data right now. */ + _send_data_write_cb(pb, bconv->socket, PURPLE_INPUT_WRITE); + } + } static void @@ -576,14 +609,15 @@ bb = pb->proto_data; /* Check if the conversation has been previously started */ + /* This really shouldn't ever happen unless something weird is going on */ if (bb->conversation == NULL) { bb->conversation = bonjour_jabber_conv_new(pb); - if (!bonjour_jabber_stream_init(pb, client_socket)) { - close(client_socket); - return; - } + /* We wait for the stream start before doing anything else */ + bb->conversation->socket = client_socket; + bb->conversation->rx_handler = purple_input_add(client_socket, + PURPLE_INPUT_READ, _client_socket_handler, pb); } else { purple_debug_warning("bonjour", "Ignoring incoming connection because an existing connection exists.\n"); @@ -696,7 +730,7 @@ return; } - if (!bonjour_jabber_stream_init(pb, source)) { + if (!bonjour_jabber_send_stream_init(pb, source)) { const char *err = g_strerror(errno); PurpleConversation *conv; @@ -714,6 +748,11 @@ bb->conversation = NULL; return; } + + /* Start listening for the stream acknowledgement */ + bb->conversation->socket = source; + bb->conversation->rx_handler = purple_input_add(source, + PURPLE_INPUT_READ, _client_socket_handler, pb); } static PurpleBuddy * @@ -843,7 +882,7 @@ /* Close the socket and remove the watcher */ if (bconv->socket >= 0) { /* Send the end of the stream to the other end of the conversation */ - if (bconv->sent_stream_start) + if (bconv->sent_stream_start == FULLY_SENT) send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); /* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */ close(bconv->socket);