Mercurial > pidgin
diff libpurple/ft.c @ 29392:f549ad844d54
propagate from branch 'im.pidgin.pidgin.next.minor' (head 42544ec892337510146c931806a95dbf69c2fe30)
to branch 'im.pidgin.pidgin' (head 32a27a2c6eebcccdecd7d7cd420b3789c69cbb09)
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 18 Feb 2010 09:22:01 +0000 |
parents | 422889fb57e0 |
children | 1326fd4dfdc9 1e8dc177415e |
line wrap: on
line diff
--- a/libpurple/ft.c Thu Feb 18 09:20:29 2010 +0000 +++ b/libpurple/ft.c Thu Feb 18 09:22:01 2010 +0000 @@ -57,6 +57,7 @@ PURPLE_XFER_READY_UI = 0x1, PURPLE_XFER_READY_PRPL = 0x2, } ready; + GByteArray *buffer; } PurpleXferPrivData; static int purple_xfer_choose_file(PurpleXfer *xfer); @@ -66,6 +67,9 @@ { PurpleXferPrivData *priv = data; + if (priv->buffer) + g_byte_array_free(priv->buffer, TRUE); + g_free(priv); } @@ -117,7 +121,7 @@ xfer->type = type; xfer->account = account; xfer->who = g_strdup(who); - xfer->ui_ops = purple_xfers_get_ui_ops(); + xfer->ui_ops = ui_ops = purple_xfers_get_ui_ops(); xfer->message = NULL; xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE; xfer->fd = -1; @@ -125,6 +129,13 @@ priv = g_new0(PurpleXferPrivData, 1); priv->ready = PURPLE_XFER_READY_NONE; + if (ui_ops && ui_ops->data_not_sent) { + /* If the ui will handle unsent data no need for buffer */ + priv->buffer = NULL; + } else { + priv->buffer = g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE); + } + g_hash_table_insert(xfers_data, xfer, priv); ui_ops = purple_xfer_get_ui_ops(xfer); @@ -1076,6 +1087,7 @@ } else if (xfer->type == PURPLE_XFER_SEND) { size_t result; size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); + PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); /* this is so the prpl can keep the connection open if it needs to for some odd reason. */ @@ -1090,8 +1102,6 @@ if (ui_ops && ui_ops->ui_read) { gssize tmp = ui_ops->ui_read(xfer, &buffer, s); if (tmp == 0) { - PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); - /* * The UI claimed it was ready, but didn't have any data for * us... It will call purple_xfer_ui_ready when ready, which @@ -1105,7 +1115,13 @@ /* Need to indicate the prpl is still ready... */ priv->ready |= PURPLE_XFER_READY_PRPL; - g_return_if_reached(); + /* + * if we requested 0 bytes it's only normal that end up here + * we shouldn't return as we still have something to + * write in priv->buffer + */ + if (s != 0) + g_return_if_reached(); } else if (tmp < 0) { purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); purple_xfer_cancel_local(xfer); @@ -1123,29 +1139,40 @@ return; } } - - /* Write as much as we're allowed to. */ + + if (priv->buffer) { + priv->buffer = g_byte_array_append(priv->buffer, buffer, result); + g_free(buffer); + buffer = priv->buffer->data; + result = priv->buffer->len; + } + r = purple_xfer_write(xfer, buffer, result); if (r == -1) { purple_xfer_cancel_remote(xfer); g_free(buffer); return; - } else if (r < result) { - if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) { - /* We have to seek back in the file now. */ - fseek(xfer->dest_fp, r - s, SEEK_CUR); - } - else { - ui_ops->data_not_sent(xfer, buffer + r, result - r); - } - } else { + } else if (r == result) { /* * We managed to write the entire buffer. This means our * network is fast and our buffer is too small, so make it * bigger. */ purple_xfer_increase_buffer_size(xfer); + } else { + if (ui_ops && ui_ops->data_not_sent) + ui_ops->data_not_sent(xfer, buffer + r, result -r); + } + + if (priv->buffer) { + /* + * Remove what we wrote + * If we wrote the whole buffer the byte array will be empty + * Otherwise we'll kee what wasn't sent for next time. + */ + buffer = NULL; + priv->buffer = g_byte_array_remove_range(priv->buffer, 0, r); } }