/pidgin/main: 8df870b218ca: HTTP: chop off another HTTP implemen...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Mon Aug 5 09:47:45 EDT 2013


Changeset: 8df870b218ca1128c099f15494ba56d57ef473a1
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2013-08-05 15:47 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/8df870b218ca

Description:

HTTP: chop off another HTTP implementation (for xmpp oob file transfers)

diffstat:

 libpurple/ft.c                   |   47 ++++++-
 libpurple/ft.h                   |   12 ++
 libpurple/http.c                 |    9 +-
 libpurple/http.h                 |    4 +-
 libpurple/protocols/jabber/oob.c |  215 +++++++++++++++-----------------------
 5 files changed, 148 insertions(+), 139 deletions(-)

diffs (truncated from 417 to 300 lines):

diff --git a/libpurple/ft.c b/libpurple/ft.c
--- a/libpurple/ft.c
+++ b/libpurple/ft.c
@@ -1144,6 +1144,43 @@ purple_xfer_write(PurpleXfer *xfer, cons
 	return r;
 }
 
+gboolean
+purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size)
+{
+	PurpleXferUiOps *ui_ops;
+	gsize wc;
+	gboolean fs_known;
+
+	g_return_val_if_fail(xfer != NULL, FALSE);
+	g_return_val_if_fail(buffer != NULL, FALSE);
+
+	ui_ops = purple_xfer_get_ui_ops(xfer);
+	fs_known = (purple_xfer_get_size(xfer) > 0);
+
+	if (fs_known && size > purple_xfer_get_bytes_remaining(xfer)) {
+		purple_debug_warning("filetransfer",
+			"Got too much data (truncating).\n");
+		size = purple_xfer_get_bytes_remaining(xfer);
+	}
+
+	if (ui_ops && ui_ops->ui_write)
+		wc = ui_ops->ui_write(xfer, buffer, size);
+	else
+		wc = fwrite(buffer, 1, size, xfer->dest_fp);
+
+	if (wc != size) {
+		purple_debug_error("filetransfer",
+			"Unable to write whole buffer.\n");
+		purple_xfer_cancel_local(xfer);
+		return FALSE;
+	}
+
+	purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) +
+		size);
+
+	return TRUE;
+}
+
 static void
 do_transfer(PurpleXfer *xfer)
 {
@@ -1156,15 +1193,7 @@ do_transfer(PurpleXfer *xfer)
 	if (xfer->type == PURPLE_XFER_RECEIVE) {
 		r = purple_xfer_read(xfer, &buffer);
 		if (r > 0) {
-			size_t wc;
-			if (ui_ops && ui_ops->ui_write)
-				wc = ui_ops->ui_write(xfer, buffer, r);
-			else
-				wc = fwrite(buffer, 1, r, xfer->dest_fp);
-
-			if (wc != r) {
-				purple_debug_error("filetransfer", "Unable to write whole buffer.\n");
-				purple_xfer_cancel_local(xfer);
+			if (!purple_xfer_write_file(xfer, buffer, r)) {
 				g_free(buffer);
 				return;
 			}
diff --git a/libpurple/ft.h b/libpurple/ft.h
--- a/libpurple/ft.h
+++ b/libpurple/ft.h
@@ -629,6 +629,18 @@ gssize purple_xfer_read(PurpleXfer *xfer
 gssize purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size);
 
 /**
+ * Writes chunk of received file.
+ *
+ * @param xfer   The file transfer.
+ * @param buffer The buffer to read the data from.
+ * @param size   The number of bytes to write.
+ *
+ * @return TRUE on success, FALSE otherwise.
+ */
+gboolean
+purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size);
+
+/**
  * Starts a file transfer.
  *
  * Either @a fd must be specified <i>or</i> @a ip and @a port on a
diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -40,6 +40,8 @@
 #define PURPLE_HTTP_REQUEST_DEFAULT_TIMEOUT 30
 #define PURPLE_HTTP_REQUEST_DEFAULT_MAX_LENGTH 1048576
 
+#define PURPLE_HTTP_PROGRESS_WATCHER_DEFAULT_INTERVAL 250000
+
 typedef struct _PurpleHttpSocket PurpleHttpSocket;
 
 typedef struct _PurpleHttpHeaders PurpleHttpHeaders;
@@ -1722,10 +1724,15 @@ PurpleConnection * purple_http_conn_get_
 
 void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
 	PurpleHttpProgressWatcher watcher, gpointer user_data,
-	guint interval_threshold)
+	gint interval_threshold)
 {
 	g_return_if_fail(http_conn != NULL);
 
+	if (interval_threshold < 0) {
+		interval_threshold =
+			PURPLE_HTTP_PROGRESS_WATCHER_DEFAULT_INTERVAL;
+	}
+
 	http_conn->watcher = watcher;
 	http_conn->watcher_user_data = user_data;
 	http_conn->watcher_interval_threshold = interval_threshold;
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -235,11 +235,11 @@ PurpleConnection * purple_http_conn_get_
  * @param watcher            The watcher.
  * @param user_data          The user data to pass to the callback function.
  * @param interval_threshold Minimum interval (in microseconds) of calls to
- *                           watcher.
+ *                           watcher, or -1 for default.
  */
 void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
 	PurpleHttpProgressWatcher watcher, gpointer user_data,
-	guint interval_threshold);
+	gint interval_threshold);
 
 /*@}*/
 
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -31,44 +31,28 @@
 #include "oob.h"
 
 typedef struct _JabberOOBXfer {
-	char *address;
-	int port;
-	char *page;
-
-	GString *headers;
-
-	char *iq_id;
-
 	JabberStream *js;
-
-	gchar *write_buffer;
-	gsize written_len;
-	guint writeh;
-
+	gchar *iq_id;
+	gchar *url;
+	PurpleHttpConnection *hc;
 } JabberOOBXfer;
 
 static void jabber_oob_xfer_init(PurpleXfer *xfer)
 {
-	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
-	purple_xfer_start(xfer, -1, jox->address, jox->port);
+	purple_xfer_start(xfer, -1, NULL, 0);
 }
 
 static void jabber_oob_xfer_free(PurpleXfer *xfer)
 {
 	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
+
+	purple_xfer_set_protocol_data(xfer, NULL);
 	jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers,
 			xfer);
 
-	g_string_free(jox->headers, TRUE);
-	g_free(jox->address);
-	g_free(jox->page);
 	g_free(jox->iq_id);
-	g_free(jox->write_buffer);
-	if(jox->writeh)
-		purple_input_remove(jox->writeh);
+	g_free(jox->url);
 	g_free(jox);
-
-	purple_xfer_set_protocol_data(xfer, NULL);
 }
 
 static void jabber_oob_xfer_end(PurpleXfer *xfer)
@@ -85,82 +69,67 @@ static void jabber_oob_xfer_end(PurpleXf
 	jabber_oob_xfer_free(xfer);
 }
 
-static void jabber_oob_xfer_request_send(gpointer data, gint source, PurpleInputCondition cond) {
-	PurpleXfer *xfer = data;
-	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
-	int len, total_len = strlen(jox->write_buffer);
+static void
+jabber_oob_xfer_got(PurpleHttpConnection *hc, PurpleHttpResponse *response,
+	gpointer _xfer)
+{
+	PurpleXfer *xfer = _xfer;
+	JabberOOBXfer *jox;
 
-	len = purple_xfer_write(xfer, (guchar*) jox->write_buffer + jox->written_len,
-		total_len - jox->written_len);
+	if (purple_xfer_is_cancelled(xfer))
+		return;
 
-	if(len < 0 && errno == EAGAIN)
+	jox = purple_xfer_get_protocol_data(xfer);
+	jox->hc = NULL;
+
+	if (!purple_http_response_is_successfull(response) ||
+		purple_xfer_get_bytes_remaining(xfer) > 0)
+	{
+		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
+		purple_xfer_end(xfer);
+	} else {
+		purple_xfer_set_completed(xfer, TRUE);
+		purple_xfer_end(xfer);
+	}
+}
+
+static void
+jabber_oob_xfer_progress_watcher(PurpleHttpConnection *hc,
+	gboolean reading_state, int processed, int total, gpointer _xfer)
+{
+	PurpleXfer *xfer = _xfer;
+
+	if (!reading_state)
 		return;
-	else if(len < 0) {
-		purple_debug_error("jabber", "Write error on oob xfer!\n");
-		purple_input_remove(jox->writeh);
-		purple_xfer_cancel_local(xfer);
-	}
-	jox->written_len += len;
 
-	if(jox->written_len == total_len) {
-		purple_input_remove(jox->writeh);
-		g_free(jox->write_buffer);
-		jox->write_buffer = NULL;
-	}
+	purple_xfer_set_size(xfer, total);
+	purple_xfer_update_progress(xfer);
+}
+
+static gboolean
+jabber_oob_xfer_writer(PurpleHttpConnection *http_conn,
+	PurpleHttpResponse *response, const gchar *buffer, size_t offset,
+	size_t length, gpointer _xfer)
+{
+	PurpleXfer *xfer = _xfer;
+
+	return purple_xfer_write_file(xfer, (const guchar*)buffer, length);
 }
 
 static void jabber_oob_xfer_start(PurpleXfer *xfer)
 {
+	PurpleHttpRequest *req;
 	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 
-	if(jox->write_buffer == NULL) {
-		jox->write_buffer = g_strdup_printf(
-			"GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n",
-			jox->page, jox->address);
-		jox->written_len = 0;
-	}
+	req = purple_http_request_new(jox->url);
+	purple_http_request_set_max_len(req, -1);
+	purple_http_request_set_response_writer(req, jabber_oob_xfer_writer,
+		xfer);
+	jox->hc = purple_http_request(jox->js->gc, req, jabber_oob_xfer_got,
+		xfer);
 
-	jox->writeh = purple_input_add(purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE,
-		jabber_oob_xfer_request_send, xfer);
-
-	jabber_oob_xfer_request_send(xfer, purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE);
-}
-
-static gssize jabber_oob_xfer_read(guchar **buffer, PurpleXfer *xfer) {
-	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
-	char test[2048];
-	char *tmp, *lenstr;
-	int len;
-
-	if((len = read(purple_xfer_get_fd(xfer), test, sizeof(test))) > 0) {
-		jox->headers = g_string_append_len(jox->headers, test, len);
-		if((tmp = strstr(jox->headers->str, "\r\n\r\n"))) {
-			*tmp = '\0';
-			lenstr = strstr(jox->headers->str, "Content-Length: ");
-			if(lenstr) {
-				goffset size;
-				if (sscanf(lenstr, "Content-Length: %" G_GOFFSET_FORMAT, &size) == 1)
-					purple_xfer_set_size(xfer, size);
-				else {
-					purple_debug_error("jabber", "Unable to parse Content-Length!\n");
-					purple_xfer_cancel_local(xfer);
-					return 0;
-				}



More information about the Commits mailing list