From 1e332ae86d9e28321347c8da1fead2c50b2a2ca3 Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Tue, 28 Aug 2012 22:25:25 +0300 Subject: [PATCH] telepathy: fix read of large messages in transport If a message is larger than the currently allocated buffer, then the input routine in the core will NOT consume any data. Thus we're setting up the next read for 0 bytes which incorrectly lead to a server disconnected situation. If the next read would be for 0 bytes we increase the buffer before kicking off the next read. The code now completes a complete login scenario with the OCS server. --- src/telepathy/telepathy-transport.c | 61 +++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/telepathy/telepathy-transport.c b/src/telepathy/telepathy-transport.c index e59e9c86..08a23d4a 100644 --- a/src/telepathy/telepathy-transport.c +++ b/src/telepathy/telepathy-transport.c @@ -64,36 +64,45 @@ static void read_completed(GObject *stream, struct sipe_transport_telepathy *transport = data; struct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION; - if (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) { - conn->buffer_length += BUFFER_SIZE_INCREMENT; - conn->buffer = g_realloc(conn->buffer, conn->buffer_length); - SIPE_DEBUG_INFO("read_completed: new buffer length %" G_GSIZE_FORMAT, - conn->buffer_length); - } + SIPE_DEBUG_INFO_NOFORMAT("read_completed: entry"); + + do { + if (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) { + conn->buffer_length += BUFFER_SIZE_INCREMENT; + conn->buffer = g_realloc(conn->buffer, conn->buffer_length); + SIPE_DEBUG_INFO("read_completed: new buffer length %" G_GSIZE_FORMAT, + conn->buffer_length); + } - /* callback result is valid */ - if (result) { - GError *error = NULL; - gssize len = g_input_stream_read_finish(G_INPUT_STREAM(stream), - result, - &error); + /* callback result is valid */ + if (result) { + GError *error = NULL; + gssize len = g_input_stream_read_finish(G_INPUT_STREAM(stream), + result, + &error); + + if (len < 0) { + SIPE_DEBUG_ERROR("read error: %s", error->message); + transport->error(conn, error->message); + g_error_free(error); + return; + } else if (len == 0) { + SIPE_DEBUG_ERROR_NOFORMAT("Server has disconnected"); + transport->error(conn, _("Server has disconnected")); + return; + } - if (len < 0) { - SIPE_DEBUG_ERROR("read error: %s", error->message); - transport->error(conn, error->message); - g_error_free(error); - return; - } else if (len == 0) { - SIPE_DEBUG_ERROR_NOFORMAT("Server has disconnected"); - transport->error(conn, _("Server has disconnected")); - return; + /* Forward data to core */ + conn->buffer_used += len; + conn->buffer[conn->buffer_used] = '\0'; + transport->input(conn); + + /* we processed the result */ + result = NULL; } - /* Forward data to core */ - conn->buffer_used += len; - conn->buffer[conn->buffer_used] = '\0'; - transport->input(conn); - } + /* buffer too short? */ + } while (conn->buffer_length - conn->buffer_used - 1 == 0); /* setup next read */ g_input_stream_read_async(G_INPUT_STREAM(stream), -- 2.11.4.GIT