diff options
author | Dario Freddi <dario.freddi@collabora.com> | 2012-09-01 03:48:33 +0200 |
---|---|---|
committer | Dario Freddi <dario.freddi@collabora.com> | 2012-09-01 03:48:33 +0200 |
commit | 22134a711ae8a202922607e27c96af847a4bfb34 (patch) | |
tree | 783fa286d47adf365ceb51e6f230a05897b83608 | |
parent | 804144754de76b7a976a52380808399292e08320 (diff) |
Handle partial data bufferingdrf-tubes-ice-udp
-rw-r--r-- | src/tube-stream.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/src/tube-stream.c b/src/tube-stream.c index 1eaf32d15..e47956684 100644 --- a/src/tube-stream.c +++ b/src/tube-stream.c @@ -109,6 +109,13 @@ struct { guint16 size; } TubePacketHeader; +typedef struct { + guint connection_id; + gchar *partial_buffer; + guint partial_buffer_length; + guint total_buffer_length; +} TubePartialData; + /* signals */ enum { @@ -205,6 +212,7 @@ struct _GabbleTubeStreamPrivate GHashTable *buffers_for_connection_id; GHashTable *length_for_buffers; + TubePartialData *tube_partial_data; }; typedef struct @@ -1380,6 +1388,7 @@ gabble_tube_stream_init (GabbleTubeStream *self) g_direct_equal, NULL, NULL); priv->length_for_buffers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); + priv->tube_partial_data = NULL; priv->address_type = TP_SOCKET_ADDRESS_TYPE_UNIX; priv->address = NULL; @@ -2509,6 +2518,47 @@ nice_data_received_cb (NiceAgent *agent, guint16 size; gchar *real_buffer; + if (priv->tube_partial_data != NULL) + { + TubePartialData *partial_data = priv->tube_partial_data; + connection_id = partial_data->connection_id; + size = partial_data->total_buffer_length; + + /* We are still receiving stuff. */ + if (partial_data->total_buffer_length <= partial_data->partial_buffer_length + len) + { + real_buffer = g_malloc (partial_data->total_buffer_length); + + memcpy (real_buffer, partial_data->partial_buffer, + partial_data->partial_buffer_length); + memcpy (real_buffer + partial_data->partial_buffer_length, + buffer, partial_data->total_buffer_length - partial_data->partial_buffer_length); + } + else + { + real_buffer = g_malloc (partial_data->partial_buffer_length + len); + + memcpy (real_buffer, partial_data->partial_buffer, + partial_data->partial_buffer_length); + memcpy (real_buffer + partial_data->partial_buffer_length, + buffer, len); + + g_free (partial_data->partial_buffer); + + partial_data->partial_buffer_length += len; + partial_data->partial_buffer = real_buffer; + + priv->tube_partial_data = partial_data; + + /* Return - there is nothing left to do here */ + return; + } + + current_position += partial_data->total_buffer_length - partial_data->partial_buffer_length; + + goto send_data; + } + connection_id = buffer[current_position]; size = *((guint16 *) &buffer[current_position + 1]); real_buffer = &buffer[current_position + 3]; @@ -2543,11 +2593,25 @@ nice_data_received_cb (NiceAgent *agent, continue; } +send_data: + /* Let's check if we got the full message */ if (current_position > len) { - /* Bad luck - only part of the message came through. Let's try and handle this case. */ + /* Bad luck - only part of the message came through. Let's try and handle this case. + * It is guaranteed if we got here that partial_data is NULL. */ + TubePartialData *partial_data = g_new (TubePartialData, 1); + DEBUG ("Partial data"); + + partial_data->connection_id = connection_id; + partial_data->partial_buffer_length = size - (current_position - len); + partial_data->total_buffer_length = size; + + partial_data->partial_buffer = g_malloc (partial_data->partial_buffer_length); + memcpy (partial_data->partial_buffer, real_buffer, partial_data->partial_buffer_length); + + priv->tube_partial_data = partial_data; return; } @@ -2588,6 +2652,13 @@ nice_data_received_cb (NiceAgent *agent, } g_object_unref (transport); + + if (priv->tube_partial_data != NULL) + { + g_free (real_buffer); + g_free (priv->tube_partial_data->partial_buffer); + g_free (priv->tube_partial_data); + } } } |