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