/pidgin/main: b057fee9d11a: HTTP progress watcher support

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Tue Oct 23 06:49:39 EDT 2012


Changeset: b057fee9d11a2ee93b588a37b4f33ea3ab9f8e98
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-10-23 12:48 +0200
Branch:	 default
URL: http://hg.pidgin.im/pidgin/main/rev/b057fee9d11a

Description:

HTTP progress watcher support

diffstat:

 libpurple/http.c |  60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libpurple/http.h |  27 +++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 0 deletions(-)

diffs (169 lines):

diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -78,6 +78,7 @@ struct _PurpleHttpConnection
 	PurpleConnection *gc;
 	PurpleHttpCallback callback;
 	gpointer user_data;
+	gboolean is_reading;
 
 	PurpleHttpURL *url;
 	PurpleHttpRequest *request;
@@ -103,6 +104,11 @@ struct _PurpleHttpConnection
 	GList *link_global, *link_gc;
 
 	guint timeout_handle;
+
+	PurpleHttpProgressWatcher watcher;
+	gpointer watcher_user_data;
+	guint watcher_interval_threshold;
+	gint64 watcher_last_call;
 };
 
 struct _PurpleHttpResponse
@@ -149,6 +155,7 @@ static time_t purple_http_rfc1123_to_tim
 static PurpleHttpConnection * purple_http_connection_new(
 	PurpleHttpRequest *request, PurpleConnection *gc);
 static void purple_http_connection_terminate(PurpleHttpConnection *hc);
+static void purple_http_conn_notify_progress_watcher(PurpleHttpConnection *hc);
 
 static PurpleHttpResponse * purple_http_response_new(void);
 static void purple_http_response_free(PurpleHttpResponse *response);
@@ -662,6 +669,8 @@ static void _purple_http_recv_body_data(
 		hc->data_length_got += len;
 	}
 
+	purple_http_conn_notify_progress_watcher(hc);
+
 	if (len == 0)
 		return;
 
@@ -1017,12 +1026,14 @@ static void _purple_http_send(gpointer _
 
 	if (writing_headers) {
 		hc->request_header_written += written;
+		purple_http_conn_notify_progress_watcher(hc);
 		if (hc->request_header_written < hc->request_header->len)
 			return;
 		if (hc->request->contents_length > 0)
 			return;
 	} else {
 		hc->request_contents_written += written;
+		purple_http_conn_notify_progress_watcher(hc);
 		if (hc->contents_reader_buffer)
 			g_string_erase(hc->contents_reader_buffer, 0, written);
 		if (hc->request_contents_written < hc->request->contents_length)
@@ -1030,6 +1041,7 @@ static void _purple_http_send(gpointer _
 	}
 
 	/* request is completely written, let's read the response */
+	hc->is_reading = TRUE;
 	purple_input_remove(hs->inpa);
 	hs->inpa = 0;
 	if (hs->is_ssl)
@@ -1192,6 +1204,8 @@ static gboolean _purple_http_reconnect(P
 	hc->in_chunk = FALSE;
 	hc->chunks_done = FALSE;
 
+	purple_http_conn_notify_progress_watcher(hc);
+
 	return TRUE;
 }
 
@@ -1387,6 +1401,52 @@ PurpleConnection * purple_http_conn_get_
 	return http_conn->gc;
 }
 
+void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
+	PurpleHttpProgressWatcher watcher, gpointer user_data,
+	guint interval_threshold)
+{
+	g_return_if_fail(http_conn != NULL);
+
+	http_conn->watcher = watcher;
+	http_conn->watcher_user_data = user_data;
+	http_conn->watcher_interval_threshold = interval_threshold;
+}
+
+static void purple_http_conn_notify_progress_watcher(
+	PurpleHttpConnection *hc)
+{
+	gint64 now;
+	gboolean reading_state;
+	int processed, total;
+
+	g_return_if_fail(hc != NULL);
+
+	if (hc->watcher == NULL)
+		return;
+
+	reading_state = hc->is_reading;
+	if (reading_state) {
+		total = hc->length_expected;
+		processed = hc->length_got;
+	} else {
+		total = hc->request->contents_length;
+		processed = hc->request_contents_written;
+		if (total == 0)
+			total = -1;
+	}
+	if (total != -1 && total < processed) {
+		purple_debug_warning("http", "Processed too much\n");
+		total = processed;
+	}
+
+	now = g_get_monotonic_time();
+	if (hc->watcher_last_call + hc->watcher_interval_threshold
+		> now && processed != total)
+		return;
+	hc->watcher_last_call = now;
+	hc->watcher(hc, reading_state, processed, total, hc->watcher_user_data);
+}
+
 /*** Cookie jar API ***********************************************************/
 
 static PurpleHttpCookie * purple_http_cookie_new(const gchar *value);
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -95,6 +95,19 @@ typedef void (*PurpleHttpContentWriter)(
 	PurpleHttpResponse *response, const gchar *buffer, size_t offset,
 	size_t length, gpointer user_data);
 
+/**
+ * An callback for watching HTTP connection progress.
+ *
+ * @param http_conn     The HTTP Connection.
+ * @param reading_state FALSE, is we are sending the request, TRUE, when reading
+ *                      the response.
+ * @param processed     The amount of data already processed.
+ * @param total         Total amount of data (in current state).
+ * @param user_data     The user data passed with callback function.
+ */
+typedef void (*PurpleHttpProgressWatcher)(PurpleHttpConnection *http_conn,
+	gboolean reading_state, int processed, int total, gpointer user_data);
+
 G_BEGIN_DECLS
 
 /**************************************************************************/
@@ -184,6 +197,20 @@ PurpleHttpCookieJar * purple_http_conn_g
 PurpleConnection * purple_http_conn_get_purple_connection(
 	PurpleHttpConnection *http_conn);
 
+/**
+ * Sets the watcher, called after writing or reading data to/from HTTP stream.
+ * May be used for updating transfer progress gauge.
+ *
+ * @param http_conn          The HTTP connection.
+ * @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.
+ */
+void purple_http_conn_set_progress_watcher(PurpleHttpConnection *http_conn,
+	PurpleHttpProgressWatcher watcher, gpointer user_data,
+	guint interval_threshold);
+
 /*@}*/
 
 



More information about the Commits mailing list