/pidgin/main: 918507303f45: HTTP API: PurpleHttpContentReader su...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Mon Oct 22 19:13:13 EDT 2012


Changeset: 918507303f45a62c581916cbbd0b01ffc5e1b56a
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-10-23 01:13 +0200
Branch:	 default
URL: http://hg.pidgin.im/pidgin/main/rev/918507303f45

Description:

HTTP API: PurpleHttpContentReader support

diffstat:

 libpurple/http.c |  80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 libpurple/http.h |  12 ++++----
 2 files changed, 85 insertions(+), 7 deletions(-)

diffs (185 lines):

diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -33,6 +33,7 @@
 
 #define PURPLE_HTTP_URL_CREDENTIALS_CHARS "a-z0-9.,~_/*!&%?=+\\^-"
 #define PURPLE_HTTP_MAX_RECV_BUFFER_LEN 10240
+#define PURPLE_HTTP_MAX_READ_BUFFER_LEN 10240
 
 #define PURPLE_HTTP_REQUEST_DEFAULT_MAX_REDIRECTS 20
 #define PURPLE_HTTP_REQUEST_DEFAULT_TIMEOUT 30
@@ -63,6 +64,8 @@ struct _PurpleHttpRequest
 
 	gchar *contents;
 	int contents_length;
+	PurpleHttpContentReader contents_reader;
+	gpointer contents_reader_data;
 
 	int timeout;
 	int max_redirects;
@@ -86,6 +89,9 @@ struct _PurpleHttpConnection
 	gboolean main_header_got, headers_got;
 	GString *response_buffer;
 
+	GString *contents_reader_buffer;
+	gboolean contents_reader_requested;
+
 	int redirects_count;
 	int data_length_got;
 
@@ -916,6 +922,33 @@ static void _purple_http_recv_ssl(gpoint
 	_purple_http_recv(_hc, -1, cond);
 }
 
+static void _purple_http_send_got_data(PurpleHttpConnection *hc,
+	gboolean success, gboolean eof, size_t stored)
+{
+	int estimated_length;
+
+	g_return_if_fail(hc != NULL);
+
+	if (!success) {
+		_purple_http_error(hc, _("Error requesting data to write"));
+		return;
+	}
+
+	hc->contents_reader_requested = FALSE;
+	g_string_set_size(hc->contents_reader_buffer, stored);
+	if (!eof)
+		return;
+
+	estimated_length = hc->request_contents_written + stored;
+
+	if (hc->request->contents_length != -1 &&
+		hc->request->contents_length != estimated_length) {
+		purple_debug_warning("http",
+			"Invalid amount of data has been written\n");
+	}
+	hc->request->contents_length = estimated_length;
+}
+
 static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond)
 {
 	PurpleHttpConnection *hc = _hc;
@@ -924,6 +957,11 @@ static void _purple_http_send(gpointer _
 	const gchar *write_from;
 	gboolean writing_headers;
 
+	/* Waiting for data. This could be written more efficiently, by removing
+	 * (and later, adding) hs->inpa. */
+	if (hc->contents_reader_requested)
+		return;
+
 	_purple_http_gen_headers(hc);
 
 	writing_headers =
@@ -933,8 +971,26 @@ static void _purple_http_send(gpointer _
 			hc->request_header_written;
 		write_len = hc->request_header->len -
 			hc->request_header_written;
+	} else if (hc->request->contents_reader) {
+		if (hc->contents_reader_requested)
+			return; /* waiting for data */
+		if (!hc->contents_reader_buffer)
+			hc->contents_reader_buffer = g_string_new("");
+		if (hc->contents_reader_buffer->len == 0) {
+			hc->contents_reader_requested = TRUE;
+			g_string_set_size(hc->contents_reader_buffer,
+				PURPLE_HTTP_MAX_READ_BUFFER_LEN);
+			hc->request->contents_reader(hc,
+				hc->contents_reader_buffer->str,
+				hc->request_contents_written,
+				PURPLE_HTTP_MAX_READ_BUFFER_LEN,
+				hc->request->contents_reader_data,
+				_purple_http_send_got_data);
+			return;
+		}
+		write_from = hc->contents_reader_buffer->str;
+		write_len = hc->contents_reader_buffer->len;
 	} else {
-		/* TODO: write_from - other write methods */
 		write_from = hc->request->contents +
 			hc->request_contents_written;
 		write_len = hc->request->contents_length -
@@ -967,6 +1023,8 @@ static void _purple_http_send(gpointer _
 			return;
 	} else {
 		hc->request_contents_written += written;
+		if (hc->contents_reader_buffer)
+			g_string_erase(hc->contents_reader_buffer, 0, written);
 		if (hc->request_contents_written < hc->request->contents_length)
 			return;
 	}
@@ -1234,6 +1292,9 @@ static void purple_http_connection_free(
 	purple_http_request_unref(hc->request);
 	purple_http_response_free(hc->response);
 
+	if (hc->contents_reader_buffer)
+		g_string_free(hc->contents_reader_buffer, TRUE);
+
 	if (hc->request_header)
 		g_string_free(hc->request_header, TRUE);
 
@@ -1628,6 +1689,9 @@ void purple_http_request_set_contents(Pu
 	g_return_if_fail(request != NULL);
 	g_return_if_fail(length >= -1);
 
+	request->contents_reader = NULL;
+	request->contents_reader_data = NULL;
+
 	g_free(request->contents);
 	if (contents == NULL || length == 0) {
 		request->contents = NULL;
@@ -1641,6 +1705,20 @@ void purple_http_request_set_contents(Pu
 	request->contents_length = length;
 }
 
+void purple_http_request_set_contents_reader(PurpleHttpRequest *request,
+	PurpleHttpContentReader reader, int contents_length, gpointer user_data)
+{
+	g_return_if_fail(request != NULL);
+	g_return_if_fail(reader != NULL);
+	g_return_if_fail(contents_length >= -1);
+
+	g_free(request->contents);
+	request->contents = NULL;
+	request->contents_length = contents_length;
+	request->contents_reader = reader;
+	request->contents_reader_data = user_data;
+}
+
 void purple_http_request_set_timeout(PurpleHttpRequest *request, int timeout)
 {
 	g_return_if_fail(request != NULL);
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -63,7 +63,7 @@ typedef void (*PurpleHttpCallback)(Purpl
  * An callback called after storing data requested by PurpleHttpContentReader.
  */
 typedef void (*PurpleHttpContentReaderCb)(PurpleHttpConnection *http_conn,
-	gboolean success, size_t stored);
+	gboolean success, gboolean eof, size_t stored);
 
 /**
  * An callback for getting large request contents (ie. from file stored on
@@ -325,13 +325,13 @@ void purple_http_request_set_contents(Pu
  * Sets contents reader for HTTP request, used mainly for possible large
  * uploads.
  *
- * @param request   The request.
- * @param reader    The reader callback.
- * @param user_data The user data to pass to the callback function.
+ * @param request       The request.
+ * @param reader        The reader callback.
+ * @param contents_size The size of all contents.
+ * @param user_data     The user data to pass to the callback function.
  */
-/* TODO */
 void purple_http_request_set_contents_reader(PurpleHttpRequest *request,
-	PurpleHttpContentReader reader, gpointer user_data);
+	PurpleHttpContentReader reader, int contents_length, gpointer user_data);
 
 /**
  * Set contents writer for HTTP response.



More information about the Commits mailing list