cpw.darkrain42.xmpp.disco: e26f09f4: Iteratively expand the disco tree as pro...

paul at darkrain42.org paul at darkrain42.org
Sat Apr 25 16:17:46 EDT 2009


-----------------------------------------------------------------
Revision: e26f09f4fd01e808a847f8f7047f962a6c0a79e3
Ancestor: aef41109df2b8a7dc5971eb9c7e7cf540495e61a
Author: paul at darkrain42.org
Date: 2009-04-14T06:54:44
Branch: im.pidgin.cpw.darkrain42.xmpp.disco
URL: http://d.pidgin.im/viewmtn/revision/info/e26f09f4fd01e808a847f8f7047f962a6c0a79e3

Modified files:
        libpurple/dbus-analyze-functions.py libpurple/disco.c
        libpurple/disco.h libpurple/protocols/jabber/disco.c

ChangeLog: 

Iteratively expand the disco tree as prompted by the UI.

Walking the entire tree automatically = bad.

This doesn't really work yet. The UI needs to be updated to support the little
expandy things like on the buddy list. It doesn't crash, though, and retrieves
the first level.

-------------- next part --------------
============================================================
--- libpurple/dbus-analyze-functions.py	b876a425ce36b6c945aba7b1f87ad3d751beb9f2
+++ libpurple/dbus-analyze-functions.py	fdf45902c72969a8059e8f577e3516b85f7d62cb
@@ -32,8 +32,10 @@ excluded = [\
     "purple_connection_new_unregister",
 
     # Similar to all the above:
+    "purple_disco_list_set_service_close_func",
     "purple_disco_list_set_cancel_func",
     "purple_disco_list_set_protocol_data",
+    "purple_disco_list_set_expand_func",
     "purple_disco_list_set_register_func",
 
     # This is excluded because this script treats PurpleLogReadFlags*
============================================================
--- libpurple/disco.c	701a16b03738bae000344449e2fe345ad629c8f4
+++ libpurple/disco.c	b0294e1f56315592c9751097efcb28cfe269e806
@@ -49,6 +49,10 @@ struct _PurpleDiscoList {
 	struct {
 		PurpleDiscoCancelFunc cancel_cb;
 		PurpleDiscoCloseFunc close_cb; /**< Callback to free the prpl data */
+		PurpleDiscoServiceCloseFunc service_close_cb;
+		PurpleDiscoServiceExpandFunc expand_cb; /**< Expand a service (iteratively
+		                                             look for things that are
+		                                             "sub-elements" in the tree */
 		PurpleDiscoRegisterFunc register_cb;
 	} ops;
 };
@@ -61,8 +65,10 @@ struct _PurpleDiscoService {
 	gchar *name; /**< The name of the service. */
 	gchar *description; /**< The name of the service. */
 
-	PurpleDiscoServiceType type; /**< The type of service. */
+	gpointer proto_data;
+
 	gchar *gateway_type; /**< The type of the gateway service. */
+	PurpleDiscoServiceType type; /**< The type of service. */
 	PurpleDiscoServiceFlags flags;
 };
 
@@ -96,6 +102,9 @@ static void purple_disco_list_service_de
 
 static void purple_disco_list_service_destroy(PurpleDiscoList *list, PurpleDiscoService *r)
 {
+	if (list->ops.service_close_cb)
+		list->ops.service_close_cb(r);
+
 	g_free(r->name);
 	g_free(r->description);
 	g_free(r->gateway_type);
@@ -147,8 +156,9 @@ void purple_disco_list_service_add(Purpl
 		ops->add_service(list, service, parent);
 }
 
-PurpleDiscoService *purple_disco_list_service_new(PurpleDiscoServiceType type, const gchar *name,
-		const gchar *description, PurpleDiscoServiceFlags flags)
+PurpleDiscoService *purple_disco_list_service_new(PurpleDiscoServiceType type,
+		const gchar *name, const gchar *description,
+		PurpleDiscoServiceFlags flags, gpointer proto_data)
 {
 	PurpleDiscoService *s;
 
@@ -160,6 +170,7 @@ PurpleDiscoService *purple_disco_list_se
 	s->type = type;
 	s->description = g_strdup(description);
 	s->flags = flags;
+	s->proto_data = proto_data;
 
 	return s;
 }
@@ -191,6 +202,24 @@ void purple_disco_cancel_get_list(Purple
 	purple_disco_list_set_in_progress(list, FALSE);
 }
 
+void purple_disco_service_expand(PurpleDiscoService *service)
+{
+	PurpleDiscoList *list;
+
+	g_return_if_fail(service != NULL);
+	g_return_if_fail((service->flags & PURPLE_DISCO_BROWSE) == PURPLE_DISCO_BROWSE);
+
+	list = service->list;
+
+	if (list->ops.expand_cb)
+		list->ops.expand_cb(list, service);
+	else
+		purple_debug_warning("disco", "Cannot expand %s for account %s, "
+		                              "protocol did not provide expand op.\n",
+		                     service->name,
+		                     purple_account_get_username(list->account));
+}
+
 void purple_disco_service_register(PurpleDiscoService *service)
 {
 	PurpleDiscoList *list;
@@ -205,6 +234,11 @@ void purple_disco_service_register(Purpl
 
 	if (list->ops.register_cb)
 		list->ops.register_cb(pc, service);
+	else
+		purple_debug_warning("disco", "Cannot register to %s for account %s, "
+		                              "protocol did not provide register op.\n",
+		                     service->name,
+		                     purple_account_get_username(list->account));
 }
 
 const gchar *purple_disco_service_get_name(PurpleDiscoService *service)
@@ -221,6 +255,14 @@ const gchar *purple_disco_service_get_de
 	return service->description;
 }
 
+gpointer
+purple_disco_service_get_protocol_data(PurpleDiscoService *service)
+{
+	g_return_val_if_fail(service != NULL, NULL);
+
+	return service->proto_data;
+}
+
 PurpleDiscoServiceType
 purple_disco_service_get_type(PurpleDiscoService *service)
 {
@@ -315,6 +357,14 @@ gpointer purple_disco_list_get_protocol_
 	return list->proto_data;
 }
 
+void purple_disco_list_set_service_close_func(PurpleDiscoList *list,
+                                              PurpleDiscoServiceCloseFunc cb)
+{
+	g_return_if_fail(list != NULL);
+
+	list->ops.service_close_cb = cb;
+}
+
 void purple_disco_list_set_cancel_func(PurpleDiscoList *list, PurpleDiscoCancelFunc cb)
 {
 	g_return_if_fail(list != NULL);
@@ -322,6 +372,12 @@ void purple_disco_list_set_cancel_func(P
 	list->ops.cancel_cb = cb;
 }
 
+void purple_disco_list_set_expand_func(PurpleDiscoList *list, PurpleDiscoServiceExpandFunc cb)
+{
+	g_return_if_fail(list != NULL);
+	list->ops.expand_cb = cb;
+}
+
 void purple_disco_list_set_register_func(PurpleDiscoList *list, PurpleDiscoRegisterFunc cb)
 {
 	g_return_if_fail(list != NULL);
============================================================
--- libpurple/disco.h	13f58bd606abb6765b67bb53dea4fabc7ebcb289
+++ libpurple/disco.h	7b1a4acc7c9ab2f221d6f63e34c58906433b48e5
@@ -52,7 +52,11 @@ typedef void (*PurpleDiscoCloseFunc)(Pur
  * @param list  The disco list.
  */
 typedef void (*PurpleDiscoCloseFunc)(PurpleDiscoList *list);
+typedef void (*PurpleDiscoServiceCloseFunc)(PurpleDiscoService *service);
 
+typedef void (*PurpleDiscoServiceExpandFunc)(PurpleDiscoList *list,
+                                             PurpleDiscoService *service);
+
 /**
  * A prpl callback called to initiate registration with the specificed
  * service.
@@ -172,7 +176,8 @@ purple_disco_list_service_new(PurpleDisc
 PurpleDiscoService *
 purple_disco_list_service_new(PurpleDiscoServiceType type, const gchar *name,
                               const gchar *description,
-                              PurpleDiscoServiceFlags flags);
+                              PurpleDiscoServiceFlags flags,
+                              gpointer proto_data);
 
 /**
  * Add service to list
@@ -180,6 +185,19 @@ void purple_disco_list_service_add(Purpl
 void purple_disco_list_service_add(PurpleDiscoList *list, PurpleDiscoService *service, PurpleDiscoService *parent);
 
 /**
+ * Expand a (browsable) service. The UI should call this in order to
+ * iteratively browse the children of this service. The service must
+ * have the PURPLE_DISCO_BROWSE flag set.
+ *
+ * You probably don't want to call this if the service already has children.
+ *
+ * @param service  The browsable disco service.
+ *
+ * @since TODO
+ */
+void purple_disco_service_expand(PurpleDiscoService *service);
+
+/**
  * Register service
  * @param service The service that will be registered
  */
@@ -206,6 +224,18 @@ const gchar* purple_disco_service_get_de
 const gchar* purple_disco_service_get_description(PurpleDiscoService *service);
 
 /**
+ * Returns the service's protocol-specific data.
+ *
+ * This should only be called from the associated prpl.
+ *
+ * @param service The disco service.
+ * @return        The protocol data.
+ *
+ * @since TODO
+ */
+gpointer purple_disco_service_get_protocol_data(PurpleDiscoService *service);
+
+/**
  * Return a service's type.
  *
  * @param service The service.
@@ -350,8 +380,14 @@ gpointer purple_disco_list_get_protocol_
  */
 gpointer purple_disco_list_get_protocol_data(PurpleDiscoList *list);
 
-void purple_disco_list_set_cancel_func(PurpleDiscoList *list, PurpleDiscoCancelFunc cb);
-void purple_disco_list_set_register_func(PurpleDiscoList *list, PurpleDiscoRegisterFunc cb);
+void purple_disco_list_set_service_close_func(PurpleDiscoList *list,
+                                              PurpleDiscoServiceCloseFunc cb);
+void purple_disco_list_set_cancel_func(PurpleDiscoList *list,
+                                       PurpleDiscoCancelFunc cb);
+void purple_disco_list_set_expand_func(PurpleDiscoList *list,
+                                       PurpleDiscoServiceExpandFunc cb);
+void purple_disco_list_set_register_func(PurpleDiscoList *list,
+                                         PurpleDiscoRegisterFunc cb);
 
 /**
  * Sets the UI operations structure to be used in all purple service discovery.
============================================================
--- libpurple/protocols/jabber/disco.c	6fc5723e4652b783d543c4836981fdbe86a041fb
+++ libpurple/protocols/jabber/disco.c	176750ba6579722241d2573f331e9c7450495b3e
@@ -54,12 +54,17 @@ struct jabber_disco_list_data {
 }
 
 struct jabber_disco_list_data {
-	JabberStream *js;
+	JabberStream *js; /* TODO: Needed? */
 	PurpleDiscoList *list;
 	char *server;
 	int fetch_count;
 };
 
+struct jabber_disco_service_data {
+	char *jid;
+	char *node;
+};
+
 static void
 jabber_disco_bytestream_server_cb(JabberStream *js, const char *from,
                                   JabberIqType type, const char *id,
@@ -761,6 +766,7 @@ jabber_disco_service_info_cb(JabberStrea
 	PurpleDiscoService *parent, *service;
 	PurpleDiscoServiceType service_type;
 	PurpleDiscoServiceFlags flags;
+	struct jabber_disco_service_data *service_data;
 
 	disco_data = data;
 	list_data = disco_data->list_data;
@@ -773,10 +779,8 @@ jabber_disco_service_info_cb(JabberStrea
 
 	--list_data->fetch_count;
 
-	if (list_data->list == NULL) {
-		if (list_data->fetch_count == 0)
-			jabber_disco_list_data_destroy(list_data);
-
+	if (!purple_disco_list_get_in_progress(list)) {
+		purple_disco_list_unref(list);
 		return;
 	}
 
@@ -818,8 +822,13 @@ jabber_disco_service_info_cb(JabberStrea
 	else
 		aname = g_strdup(from);
 
+	service_data = g_new0(struct jabber_disco_service_data, 1);
+	service_data->jid = g_strdup(from);
+	if (anode)
+		service_data->node = g_strdup(anode);
+
 	service = purple_disco_list_service_new(service_type, aname,
-			xmlnode_get_attrib(identity, "name"), flags);
+			xmlnode_get_attrib(identity, "name"), flags, service_data);
 	g_free(aname);
 
 	if (service_type == PURPLE_DISCO_SERVICE_TYPE_GATEWAY)
@@ -829,24 +838,11 @@ jabber_disco_service_info_cb(JabberStrea
 
 	purple_disco_list_service_add(list, service, parent);
 
-	/* if (flags & PURPLE_DISCO_FLAG_BROWSE) - not all browsable services have this feature */
-	{
-		++list_data->fetch_count;
-		purple_disco_list_ref(list);
-		disco_data = g_new0(struct _disco_data, 1);
-		disco_data->list_data = list_data;
-		disco_data->parent = service;
-
-		jabber_disco_items_do(js, from, node, jabber_disco_service_items_cb,
-		                      disco_data);
-	}
-
 	if (list_data->fetch_count == 0)
 		purple_disco_list_set_in_progress(list, FALSE);
 
 	purple_disco_list_unref(list);
 
-	g_free(aname);
 	g_free(node);
 }
 
@@ -859,16 +855,12 @@ jabber_disco_server_items_cb(JabberStrea
 	xmlnode *query, *child;
 	gboolean has_items = FALSE;
 
-	if (!from || type == JABBER_IQ_ERROR)
-		return;
-
 	list_data = data;
 	--list_data->fetch_count;
 
-	if (list_data->list == NULL) {
-		if (list_data->fetch_count == 0)
-			jabber_disco_list_data_destroy(list_data);
-
+	if (!from || type == JABBER_IQ_ERROR ||
+			!purple_disco_list_get_in_progress(list_data->list)) {
+		purple_disco_list_unref(list_data->list);
 		return;
 	}
 
@@ -968,24 +960,50 @@ static void
 }
 
 static void
+jabber_disco_service_close(PurpleDiscoService *service)
+{
+	struct jabber_disco_service_data *data;
+
+	data = purple_disco_service_get_protocol_data(service);
+	g_free(data->jid);
+	g_free(data->node);
+	g_free(data);
+}
+
+#if 0
+static void
 jabber_disco_cancel(PurpleDiscoList *list)
 {
-	struct jabber_disco_list_data *list_data = purple_disco_list_get_protocol_data(list);
-	purple_disco_list_set_protocol_data(list, NULL, NULL);
+	/* This space intentionally letft blank */
+}
+#endif
 
-	if (list_data->fetch_count == 0) {
-		/* Nothing outstanding, just free it now... */
-		jabber_disco_list_data_destroy(list_data);
-	} else {
-		int i;
-		/* Lose all our references to the PurpleDiscoList */
-		for (i = 0; i < list_data->fetch_count; ++i) {
-			purple_disco_list_unref(list);
-		}
+static void
+jabber_disco_list_expand(PurpleDiscoList *list, PurpleDiscoService *service)
+{
+	PurpleAccount *account;
+	PurpleConnection *pc;
+	JabberStream *js;
+	struct jabber_disco_list_data *list_data;
+	struct jabber_disco_service_data *service_data;
+	struct _disco_data *disco_data;
 
-		/* We'll free list_data when fetch_count is down to 0 */
-		list_data->list = NULL;
-	}
+	account = purple_disco_list_get_account(list);
+	pc = purple_account_get_connection(account);
+	js = purple_connection_get_protocol_data(pc);
+
+	list_data = purple_disco_list_get_protocol_data(list);
+
+	++list_data->fetch_count;
+	purple_disco_list_ref(list);
+	disco_data = g_new0(struct _disco_data, 1);
+	disco_data->list_data = list_data;
+	disco_data->parent = service;
+
+	service_data = purple_disco_service_get_protocol_data(service);
+
+	jabber_disco_items_do(js, service_data->jid, service_data->node,
+	                      jabber_disco_service_items_cb, disco_data);
 }
 
 static void
@@ -1014,8 +1032,13 @@ jabber_disco_get_list(PurpleConnection *
 	disco_list_data = g_new0(struct jabber_disco_list_data, 1);
 	disco_list_data->list = list;
 	disco_list_data->js = js;
-	purple_disco_list_set_protocol_data(list, disco_list_data, disco_proto_data_destroy_cb);
+	purple_disco_list_set_protocol_data(list, disco_list_data,
+	                                    disco_proto_data_destroy_cb);
+	purple_disco_list_set_service_close_func(list, jabber_disco_service_close);
+#if 0
 	purple_disco_list_set_cancel_func(list, jabber_disco_cancel);
+#endif
+	purple_disco_list_set_expand_func(list, jabber_disco_list_expand);
 	purple_disco_list_set_register_func(list, jabber_disco_service_register);
 
 	purple_request_input(gc, _("Server name request"), _("Enter an XMPP Server"),


More information about the Commits mailing list