im.pidgin.pidgin: 4c8cd79e13fc8711ae5e749442d990cc52bdb3fe
datallah at pidgin.im
datallah at pidgin.im
Sun Dec 2 20:25:47 EST 2007
-----------------------------------------------------------------
Revision: 4c8cd79e13fc8711ae5e749442d990cc52bdb3fe
Ancestor: b9c97ed0f9ada9069e8bd994b01fdde0b484083c
Author: datallah at pidgin.im
Date: 2007-12-03T01:18:37
Branch: im.pidgin.pidgin
Modified files:
libpurple/protocols/bonjour/jabber.c
libpurple/protocols/bonjour/jabber.h
ChangeLog:
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.
-------------- next part --------------
============================================================
--- libpurple/protocols/bonjour/jabber.c d5513158e2d3c0eef3c29dfebfeebee75f801672
+++ libpurple/protocols/bonjour/jabber.c ca47e72112883c6ae1a7b7210c0e041c426b944c
@@ -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 @@ bonjour_jabber_conv_new(PurpleBuddy *pb)
bconv->rx_handler = 0;
bconv->pb = pb;
+ bonjour_parser_setup(bconv);
+
return bconv;
}
@@ -289,7 +297,7 @@ _send_data(PurpleBuddy *pb, char *messag
/* 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 @@ _send_data(PurpleBuddy *pb, char *messag
}
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,21 +418,7 @@ void bonjour_jabber_stream_ended(PurpleB
}
}
-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 @@ _start_stream(gpointer data, gint source
/* 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 @@ static gboolean bonjour_jabber_stream_in
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 @@ static gboolean bonjour_jabber_stream_in
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;
+}
- bb->conversation->socket = client_socket;
- bb->conversation->rx_handler = purple_input_add(client_socket,
- PURPLE_INPUT_READ, _client_socket_handler, pb);
+static gboolean
+_async_bonjour_jabber_close_conversation(gpointer data) {
+ BonjourJabberConversation *bconv = data;
+ bonjour_jabber_close_conversation(bconv);
+ return FALSE;
+}
- return TRUE;
+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)");
+
+ 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));
+
+ 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 @@ _server_socket_handler(gpointer data, in
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 @@ _connected_to_buddy(gpointer data, gint
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 @@ _connected_to_buddy(gpointer data, gint
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 @@ bonjour_jabber_close_conversation(Bonjou
/* 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);
============================================================
--- libpurple/protocols/bonjour/jabber.h f4ab4e73d3f0ff58e932b1f3be3d618a267abd5c
+++ libpurple/protocols/bonjour/jabber.h caeda2d4032f5b282342b4bb2c6589ba9d52d621
@@ -47,7 +47,7 @@ typedef struct _BonjourJabberConversatio
guint rx_handler;
guint tx_handler;
PurpleCircBuffer *tx_buf;
- gboolean sent_stream_start;
+ int sent_stream_start; /* 0 = Unsent, 1 = Partial, 2 = Complete */
gboolean recv_stream_start;
PurpleProxyConnectData *connect_data;
gpointer stream_data;
More information about the Commits
mailing list