Mercurial > pidgin
diff libpurple/ft.c @ 29328:1e19c439fa7a
propagate from branch 'im.pidgin.pidgin' (head 07dc6851f4d16e9c89791c488bbc6d3b2bdb8ecf)
to branch 'im.pidgin.pidgin.next.minor' (head 3716aff37a220834473555f2a4143810736e51f8)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Mon, 30 Nov 2009 06:24:32 +0000 |
parents | 52dc24a5069f 18667ce1f55d |
children | 10eaca0bf01a |
line wrap: on
line diff
--- a/libpurple/ft.c Mon Nov 30 05:59:57 2009 +0000 +++ b/libpurple/ft.c Mon Nov 30 06:24:32 2009 +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); } @@ -93,14 +97,21 @@ 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; 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); @@ -116,9 +127,12 @@ purple_xfer_destroy(PurpleXfer *xfer) { PurpleXferUiOps *ui_ops; + PurpleXferPrivData *priv; g_return_if_fail(xfer != NULL); + priv = g_hash_table_lookup(xfers_data, xfer); + /* Close the file browser, if it's open */ purple_request_close_with_handle(xfer); @@ -967,8 +981,6 @@ r = write(xfer->fd, buffer, s); if (r < 0 && errno == EAGAIN) r = 0; - if ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)) - purple_xfer_set_completed(xfer, TRUE); } return r; @@ -999,9 +1011,6 @@ return; } - if ((purple_xfer_get_size(xfer) > 0) && - ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer))) - purple_xfer_set_completed(xfer, TRUE); } else if(r < 0) { purple_xfer_cancel_remote(xfer); g_free(buffer); @@ -1010,6 +1019,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. */ @@ -1021,6 +1031,10 @@ return; } + if (priv->buffer) { + s = s - priv->buffer->len; + } + if (ui_ops && ui_ops->ui_read) { gssize tmp = ui_ops->ui_read(xfer, &buffer, s); if (tmp == 0) { @@ -1033,8 +1047,13 @@ purple_input_remove(xfer->watcher); xfer->watcher = 0; } - - return; + /* + * if we requested 0 bytes it's only normal that en up here + * we shouldn't return as we still have something to + * write in priv->buffer + */ + if (s != 0) + return; } else if (tmp < 0) { purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); purple_xfer_cancel_local(xfer); @@ -1052,29 +1071,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); } } @@ -1094,8 +1124,11 @@ purple_xfer_get_progress(xfer)); } - if (purple_xfer_is_completed(xfer)) + if ((purple_xfer_get_size(xfer) > 0) && + ((purple_xfer_get_bytes_sent(xfer)) >= purple_xfer_get_size(xfer))) { + purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); + } } static void