pidgin.next.minor: fa4ce539: Kill off the use of fseek for non-seekab...
rekkanoryo at pidgin.im
rekkanoryo at pidgin.im
Mon Oct 12 18:58:25 EDT 2009
-----------------------------------------------------------------
Revision: fa4ce539e5025eb07aad3ca824cd4c512010d8a8
Ancestor: 0afd41e710b9982261d012302ef161daa52ff1eb
Author: foufou33 at gmail.com
Date: 2009-10-12T18:41:51
Branch: im.pidgin.pidgin.next.minor
URL: http://d.pidgin.im/viewmtn/revision/info/fa4ce539e5025eb07aad3ca824cd4c512010d8a8
Modified files:
libpurple/ft.c
ChangeLog:
Kill off the use of fseek for non-seekable streams in file transfers.
Fixes #9841.
-------------- next part --------------
============================================================
--- libpurple/ft.c 4e682737a66d8693c0c23e2ca50a69f935369042
+++ libpurple/ft.c ff89d3c33eebb36898b9595ed4ed2361d72bb650
@@ -57,6 +57,7 @@ typedef struct _PurpleXferPrivData {
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 @@ purple_xfer_priv_data_destroy(gpointer d
{
PurpleXferPrivData *priv = data;
+ if (priv->buffer)
+ g_byte_array_free(priv->buffer, TRUE);
+
g_free(priv);
}
@@ -93,14 +97,21 @@ purple_xfer_new(PurpleAccount *account,
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)
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);
@@ -1010,6 +1024,7 @@ do_transfer(PurpleXfer *xfer)
} 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 +1036,10 @@ do_transfer(PurpleXfer *xfer)
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 +1052,13 @@ do_transfer(PurpleXfer *xfer)
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,30 +1076,41 @@ do_transfer(PurpleXfer *xfer)
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);
+ }
}
if (r > 0) {
More information about the Commits
mailing list