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);
 		}
 	}