/cpw/tomkiewicz/http: 4d41b1f7b95f: Cancelling all HTTP connecti...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Tue Oct 16 14:49:50 EDT 2012


Changeset: 4d41b1f7b95f7370096165eb7526a1aa494e9b32
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-10-16 20:49 +0200
Branch:	 default
URL: http://hg.pidgin.im/cpw/tomkiewicz/http/rev/4d41b1f7b95f

Description:

Cancelling all HTTP connections on account disconnect or app shutdown

diffstat:

 libpurple/http.c            |  101 +++++++++++++++++++++++++++++++++++++++++--
 libpurple/http.h            |   13 +++--
 libpurple/protocols/gg/gg.c |   30 +++++-------
 3 files changed, 116 insertions(+), 28 deletions(-)

diffs (273 lines):

diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -84,6 +84,8 @@ struct _PurpleHttpConnection
 
 	gboolean is_chunked, in_chunk, chunks_done;
 	int chunk_length, chunk_got;
+
+	GList *link_global, *link_gc;
 };
 
 struct _PurpleHttpResponse
@@ -113,7 +115,7 @@ struct _PurpleHttpHeaders
 };
 
 static PurpleHttpConnection * purple_http_connection_new(
-	PurpleHttpRequest *request);
+	PurpleHttpRequest *request, PurpleConnection *gc);
 static void purple_http_connection_terminate(PurpleHttpConnection *hc);
 
 static PurpleHttpResponse * purple_http_response_new(void);
@@ -127,6 +129,23 @@ static gchar * purple_http_url_print(Pur
 
 static GRegex *purple_http_re_url, *purple_http_re_url_host;
 
+/**
+ * Values: pointers to running PurpleHttpConnection.
+ */
+static GList *purple_http_hc_list;
+
+/**
+ * Keys: pointers to PurpleConnection.
+ * Values: GList of pointers to running PurpleHttpConnection.
+ */
+static GHashTable *purple_http_hc_by_gc;
+
+/**
+ * Keys: pointers to PurpleHttpConnection.
+ * Values: pointers to links in purple_http_hc_list.
+ */
+static GHashTable *purple_http_hc_by_ptr;
+
 /*** Headers collection *******************************************************/
 
 static PurpleHttpHeaders * purple_http_headers_new(void);
@@ -919,8 +938,7 @@ PurpleHttpConnection * purple_http_reque
 
 	g_return_val_if_fail(request != NULL, NULL);
 
-	hc = purple_http_connection_new(request);
-	hc->gc = gc;
+	hc = purple_http_connection_new(request, gc);
 	hc->callback = callback;
 	hc->user_data = user_data;
 
@@ -948,7 +966,8 @@ PurpleHttpConnection * purple_http_reque
 
 static void purple_http_connection_free(PurpleHttpConnection *hc);
 
-static PurpleHttpConnection * purple_http_connection_new(PurpleHttpRequest *request)
+static PurpleHttpConnection * purple_http_connection_new(
+	PurpleHttpRequest *request, PurpleConnection *gc)
 {
 	PurpleHttpConnection *hc = g_new0(PurpleHttpConnection, 1);
 
@@ -956,6 +975,17 @@ static PurpleHttpConnection * purple_htt
 	purple_http_request_ref(request);
 	hc->response = purple_http_response_new();
 
+	hc->link_global = purple_http_hc_list =
+		g_list_prepend(purple_http_hc_list, hc);
+	g_hash_table_insert(purple_http_hc_by_ptr, hc, hc->link_global);
+	if (gc) {
+		GList *gc_list = g_hash_table_lookup(purple_http_hc_by_gc, gc);
+		g_hash_table_steal(purple_http_hc_by_gc, gc);
+		hc->link_gc = gc_list = g_list_prepend(gc_list, hc);
+		g_hash_table_insert(purple_http_hc_by_gc, gc, gc_list);
+		hc->gc = gc;
+	}
+
 	return hc;
 }
 
@@ -968,6 +998,23 @@ static void purple_http_connection_free(
 	if (hc->request_header)
 		g_string_free(hc->request_header, TRUE);
 
+	purple_http_hc_list = g_list_delete_link(purple_http_hc_list,
+		hc->link_global);
+	g_hash_table_remove(purple_http_hc_by_ptr, hc);
+	if (hc->gc) {
+		GList *gc_list, *gc_list_new;
+		gc_list = g_hash_table_lookup(purple_http_hc_by_gc, hc->gc);
+		g_assert(gc_list != NULL);
+
+		gc_list_new = g_list_delete_link(gc_list, hc->link_gc);
+		if (gc_list != gc_list_new) {
+			g_hash_table_steal(purple_http_hc_by_gc, hc->gc);
+			if (gc_list_new)
+				g_hash_table_insert(purple_http_hc_by_gc,
+					hc->gc, gc_list_new);
+		}
+	}
+
 	g_free(hc);
 }
 
@@ -995,7 +1042,24 @@ void purple_http_conn_cancel(PurpleHttpC
 
 void purple_http_conn_cancel_all(PurpleConnection *gc)
 {
-	purple_debug_warning("http", "purple_http_conn_cancel_all: To be implemented\n");
+	GList *gc_list = g_hash_table_lookup(purple_http_hc_by_gc, gc);
+
+	while (gc_list) {
+		PurpleHttpConnection *hc = gc_list->data;
+		gc_list = g_list_next(gc_list);
+		purple_http_conn_cancel(hc);
+	}
+
+	if (NULL != g_hash_table_lookup(purple_http_hc_by_gc, gc))
+		purple_debug_error("http", "Couldn't cancel all connections "
+			"related to gc=%p\n", gc);
+}
+
+gboolean purple_http_conn_is_running(PurpleHttpConnection *http_conn)
+{
+	if (http_conn == NULL)
+		return FALSE;
+	return (NULL != g_hash_table_lookup(purple_http_hc_by_ptr, http_conn));
 }
 
 /*** Request API **************************************************************/
@@ -1435,6 +1499,17 @@ void purple_http_init(void)
 
 		"$", G_REGEX_OPTIMIZE | G_REGEX_CASELESS,
 		G_REGEX_MATCH_NOTEMPTY, NULL);
+
+	purple_http_hc_list = NULL;
+	purple_http_hc_by_ptr = g_hash_table_new(g_direct_hash, g_direct_equal);
+	purple_http_hc_by_gc = g_hash_table_new_full(g_direct_hash,
+		g_direct_equal, NULL, (GDestroyNotify)g_list_free);
+}
+
+static void purple_http_foreach_conn_cancel(gpointer _hc, gpointer user_data)
+{
+	PurpleHttpConnection *hc = _hc;
+	purple_http_conn_cancel(hc);
 }
 
 void purple_http_uninit(void)
@@ -1443,4 +1518,20 @@ void purple_http_uninit(void)
 	purple_http_re_url = NULL;
 	g_regex_unref(purple_http_re_url_host);
 	purple_http_re_url_host = NULL;
+
+	g_list_foreach(purple_http_hc_list, purple_http_foreach_conn_cancel,
+		NULL);
+
+	if (purple_http_hc_list != NULL ||
+		0 != g_hash_table_size(purple_http_hc_by_ptr) ||
+		0 != g_hash_table_size(purple_http_hc_by_gc))
+		purple_debug_warning("http",
+			"Couldn't cleanup all connections.\n");
+
+	g_list_free(purple_http_hc_list);
+	purple_http_hc_list = NULL;
+	g_hash_table_destroy(purple_http_hc_by_gc);
+	purple_http_hc_by_gc = NULL;
+	g_hash_table_destroy(purple_http_hc_by_ptr);
+	purple_http_hc_by_ptr = NULL;
 }
diff --git a/libpurple/http.h b/libpurple/http.h
--- a/libpurple/http.h
+++ b/libpurple/http.h
@@ -143,9 +143,16 @@ PurpleHttpConnection * purple_http_reque
 void purple_http_conn_cancel(PurpleHttpConnection *http_conn);
 
 /**
+ * Cancels all HTTP connections associated with the specified handle.
+ *
+ * @param gc The handle.
+ */
+void purple_http_conn_cancel_all(PurpleConnection *gc);
+
+/**
  * Checks, if provided HTTP request is running.
  *
- * @param http_conn The HTTP connection.
+ * @param http_conn The HTTP connection (may be invalid pointer).
  * @return          TRUE, if provided connection is currently running.
  */
 gboolean purple_http_conn_is_running(PurpleHttpConnection *http_conn);
@@ -156,10 +163,6 @@ PurpleHttpRequest * purple_http_conn_get
 PurpleConnection * purple_http_conn_get_purple_connection(
 	PurpleHttpConnection *http_conn);
 
-const GSList * purple_http_conn_get_all(PurpleConnection *gc);
-
-void purple_http_conn_cancel_all(PurpleConnection *gc);
-
 /*@}*/
 
 
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -58,7 +58,6 @@
 #include <http.h>
 #include <obsolete.h>
 
-/*
 static void ggp_test_http_cb(PurpleHttpConnection *http_conn,
 	PurpleHttpResponse *response, gpointer user_data)
 {
@@ -85,7 +84,6 @@ static void ggp_test_http_cb(PurpleHttpC
 		g_free(data_tail);
 	}
 }
-*/
 
 static void ggp_test_http_cb2(PurpleUtilFetchUrlData *url_data,
 	gpointer user_data, const gchar *url_text, gsize len,
@@ -117,9 +115,6 @@ static void ggp_action_test_http(PurpleP
 	PurpleConnection *gc = (PurpleConnection *)action->context;
 
 	purple_debug_info("http-test", "Testing http...\n");
-//	purple_http_get(gc, "http://www.wasilczyk.pl/x_ip_simple.htm",
-//		ggp_test_http_cb, NULL);
-/*
 	purple_http_get(gc, "http://www.wasilczyk.pl/x_ip_simple.htm",
 		ggp_test_http_cb, NULL);
 	purple_http_get(gc, "http://www.wasilczyk.pl/x_ip_simple.htm",
@@ -130,27 +125,26 @@ static void ggp_action_test_http(PurpleP
 		ggp_test_http_cb, NULL);
 	purple_http_get(gc, "http://www.wasilczyk.pl/x_ip_simple.htm",
 		ggp_test_http_cb, NULL);
-*/
 
-//	purple_http_get(gc, "http://google.com",
-//		ggp_test_http_cb, NULL);
-//	purple_http_get(gc, "http://wp.pl",
-//		ggp_test_http_cb, NULL);
+	purple_http_get(gc, "http://google.com",
+		ggp_test_http_cb, NULL);
+	purple_http_get(gc, "http://wp.pl",
+		ggp_test_http_cb, NULL);
 
-//	purple_http_get(gc, "https://www.google.pl",
-//		ggp_test_http_cb, NULL);
+	purple_http_get(gc, "https://www.google.pl",
+		ggp_test_http_cb, NULL);
 
 //	purple_util_fetch_url("https://www.google.pl",
 	purple_util_fetch_url("http://wp.pl",
 		TRUE, "My Browser", TRUE, -1, ggp_test_http_cb2, NULL);
 
 
-//	request = purple_http_request_new("http://wp.pl");
-//	purple_http_request_set_http11(request, FALSE);
-//	purple_http_request_set_max_redirects(request, 1);
-//	purple_http_request_set_max_len(request, 0);
-//	purple_http_request(gc, request, ggp_test_http_cb, NULL);
-//	purple_http_request_unref(request);
+	request = purple_http_request_new("http://wp.pl");
+	purple_http_request_set_http11(request, FALSE);
+	purple_http_request_set_max_redirects(request, 1);
+	purple_http_request_set_max_len(request, 0);
+	purple_http_request(gc, request, ggp_test_http_cb, NULL);
+	purple_http_request_unref(request);
 
 	purple_debug_info("http-test", "Testing http started.\n");
 }



More information about the Commits mailing list