[Telepathy-commits] [telepathy-gabble/master] Implement org.laptop.Telepathy.Buddy.RequestRandom()
Guillaume Desmottes
guillaume.desmottes at collabora.co.uk
Fri Sep 26 10:02:01 PDT 2008
20080520144913-7fe3f-cc6962fade582d41f5ae7dd5a48b5eb72c46e5fb.gz
---
src/conn-olpc.c | 190 +++++++++++++++++++++++++++++++
src/conn-olpc.h | 3 +
src/connection.c | 3 +
src/connection.h | 1 +
tests/twisted/olpc/olpc-buddy-search.py | 51 ++++++++-
5 files changed, 247 insertions(+), 1 deletions(-)
diff --git a/src/conn-olpc.c b/src/conn-olpc.c
index cd5b8d6..42a1b3c 100644
--- a/src/conn-olpc.c
+++ b/src/conn-olpc.c
@@ -35,6 +35,7 @@
#include "pubsub.h"
#include "disco.h"
#include "util.h"
+#include "olpc-buddy-view.h"
#define ACTIVITY_PAIR_TYPE \
dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, \
@@ -2951,6 +2952,13 @@ conn_olpc_activity_properties_init (GabbleConnection *conn)
conn->olpc_invited_activities = g_hash_table_new_full (g_direct_hash,
g_direct_equal, NULL, (GDestroyNotify) tp_handle_set_destroy);
+ /* Active buddy views
+ *
+ * view id guint => GabbleOlpcBuddyView
+ */
+ conn->olpc_buddy_views = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_object_unref);
+
conn->olpc_gadget_buddy = NULL;
conn->olpc_gadget_activity = NULL;
@@ -2976,3 +2984,185 @@ olpc_activity_properties_iface_init (gpointer g_iface,
IMPLEMENT(set_properties);
#undef IMPLEMENT
}
+
+static void
+buddy_view_closed_cb (GabbleOlpcBuddyView *view,
+ GabbleConnection *conn)
+{
+ guint id;
+
+ g_object_get (view, "id", &id, NULL);
+ g_hash_table_remove (conn->olpc_buddy_views, GUINT_TO_POINTER (id));
+}
+
+static GabbleOlpcBuddyView *
+create_buddy_view (GabbleConnection *conn)
+{
+ guint id;
+ GabbleOlpcBuddyView *view;
+
+ /* Look for a free ID */
+ for (id = 0; id < G_MAXUINT &&
+ g_hash_table_lookup (conn->olpc_buddy_views, GUINT_TO_POINTER (id))
+ != NULL; id++);
+
+ if (id == G_MAXUINT)
+ {
+ /* All the ID's are allocated */
+ return NULL;
+ }
+
+ view = gabble_olpc_buddy_view_new (conn, id);
+ g_hash_table_insert (conn->olpc_buddy_views, GUINT_TO_POINTER (id), view);
+
+ g_signal_connect (view, "closed", G_CALLBACK (buddy_view_closed_cb), conn);
+
+ return view;
+}
+
+static LmHandlerResult
+buddy_query_result_cb (GabbleConnection *conn,
+ LmMessage *sent_msg,
+ LmMessage *reply_msg,
+ GObject *_view,
+ gpointer user_data)
+{
+ LmMessageNode *query, *buddy;
+ TpHandleSet *buddies;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ (TpBaseConnection*) conn, TP_HANDLE_TYPE_CONTACT);
+ GabbleOlpcBuddyView *view = GABBLE_OLPC_BUDDY_VIEW (_view);
+
+ query = lm_message_node_get_child_with_namespace (reply_msg->node, "query",
+ NS_OLPC_BUDDY);
+ if (query == NULL)
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+
+ buddies = tp_handle_set_new (contact_repo);
+ for (buddy = query->children; buddy != NULL; buddy = buddy->next)
+ {
+ const gchar *jid;
+ LmMessageNode *properties_node;
+ GHashTable *properties;
+ TpHandle handle;
+
+ jid = lm_message_node_get_attribute (buddy, "jid");
+
+ handle = tp_handle_ensure (contact_repo, jid, NULL, NULL);
+ if (handle == 0)
+ {
+ DEBUG ("Invalid jid: %s", jid);
+ tp_handle_set_destroy (buddies);
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+ }
+
+ tp_handle_set_add (buddies, handle);
+ tp_handle_unref (contact_repo, handle);
+
+ properties_node = lm_message_node_get_child_with_namespace (buddy,
+ "properties", NS_OLPC_BUDDY_PROPS);
+ properties = lm_message_node_extract_properties (properties_node,
+ "property");
+
+ gabble_svc_olpc_buddy_info_emit_properties_changed (conn, handle,
+ properties);
+
+ g_hash_table_destroy (properties);
+ }
+
+ /* TODO: remove buddies when needed */
+ gabble_olpc_buddy_view_add_buddies (view, buddies);
+
+ tp_handle_set_destroy (buddies);
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+static void
+olpc_buddy_request_random (GabbleSvcOLPCBuddy *iface,
+ guint max,
+ DBusGMethodInvocation *context)
+{
+ GabbleConnection *conn = GABBLE_CONNECTION (iface);
+ LmMessage *query;
+ gchar *max_str, *id_str;
+ gchar *object_path;
+ guint id;
+ GabbleOlpcBuddyView *view;
+
+ if (!check_gadget_buddy (conn, context))
+ return;
+
+ if (max == 0)
+ {
+ GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "max have to be greater than 0" };
+
+ DEBUG ("%s", error.message);
+ dbus_g_method_return_error (context, &error);
+ return;
+ }
+
+ view = create_buddy_view (conn);
+ if (view == NULL)
+ {
+ GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ "can't create view" };
+
+ DEBUG ("%s", error.message);
+ dbus_g_method_return_error (context, &error);
+ return;
+ }
+
+ g_object_get (view,
+ "id", &id,
+ "object-path", &object_path,
+ NULL);
+
+ max_str = g_strdup_printf ("%u", max);
+ id_str = g_strdup_printf ("%u", id);
+
+ query = lm_message_build_with_sub_type (conn->olpc_gadget_buddy,
+ LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET,
+ '(', "query", "",
+ '@', "xmlns", NS_OLPC_BUDDY,
+ '@', "id", id_str,
+ '(', "random", "",
+ '@', "max", max_str,
+ ')',
+ ')',
+ NULL);
+
+ g_free (max_str);
+ g_free (id_str);
+
+ if (!_gabble_connection_send_with_reply (conn, query,
+ buddy_query_result_cb, G_OBJECT (view), NULL, NULL))
+ {
+ GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+ "Failed to send buddy search query to server" };
+
+ DEBUG ("%s", error.message);
+ dbus_g_method_return_error (context, &error);
+ lm_message_unref (query);
+ g_free (object_path);
+ return;
+ }
+
+ gabble_svc_olpc_buddy_return_from_request_random (context, object_path);
+
+ g_free (object_path);
+ lm_message_unref (query);
+}
+
+void
+olpc_buddy_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GabbleSvcOLPCBuddyClass *klass = g_iface;
+
+#define IMPLEMENT(x) gabble_svc_olpc_buddy_implement_##x (\
+ klass, olpc_buddy_##x)
+ IMPLEMENT(request_random);
+ /* TODO: implement SearchByProperties */
+#undef IMPLEMENT
+}
diff --git a/src/conn-olpc.h b/src/conn-olpc.h
index 4b9e796..b6f114f 100644
--- a/src/conn-olpc.h
+++ b/src/conn-olpc.h
@@ -60,5 +60,8 @@ gboolean conn_olpc_process_activity_uninvite_message (GabbleConnection *conn,
LmHandlerResult conn_olpc_msg_cb (LmMessageHandler *handler,
LmConnection *connection, LmMessage *message, gpointer user_data);
+
+void olpc_buddy_iface_init (gpointer g_iface, gpointer iface_data);
+
#endif /* __CONN_OLPC_H__ */
diff --git a/src/connection.c b/src/connection.c
index e451490..7f2193e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -102,6 +102,8 @@ G_DEFINE_TYPE_WITH_CODE(GabbleConnection,
olpc_buddy_info_iface_init);
G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_ACTIVITY_PROPERTIES,
olpc_activity_properties_iface_init);
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_BUDDY,
+ olpc_buddy_iface_init);
)
/* properties */
@@ -752,6 +754,7 @@ gabble_connection_dispose (GObject *object)
g_hash_table_destroy (self->olpc_activities_info);
g_hash_table_destroy (self->olpc_pep_activities);
g_hash_table_destroy (self->olpc_invited_activities);
+ g_hash_table_destroy (self->olpc_buddy_views);
g_hash_table_destroy (self->avatar_requests);
diff --git a/src/connection.h b/src/connection.h
index acb456b..417a589 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -140,6 +140,7 @@ struct _GabbleConnection {
GHashTable *olpc_activities_info;
GHashTable *olpc_pep_activities;
GHashTable *olpc_invited_activities;
+ GHashTable *olpc_buddy_views;
/* OLPC services */
const gchar *olpc_gadget_buddy;
diff --git a/tests/twisted/olpc/olpc-buddy-search.py b/tests/twisted/olpc/olpc-buddy-search.py
index fe25994..fd47e79 100644
--- a/tests/twisted/olpc/olpc-buddy-search.py
+++ b/tests/twisted/olpc/olpc-buddy-search.py
@@ -57,6 +57,7 @@ def test(q, bus, conn, stream):
stream.send(reply)
buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
+ buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Buddy')
call_async(q, conn, 'RequestHandles', 1, ['bob at localhost'])
@@ -87,7 +88,7 @@ def test(q, bus, conn, stream):
assert buddy['jid'] == 'bob at localhost'
# send reply to the search query
- reply = make_result_iq('stream', event.stanza)
+ reply = make_result_iq(stream, event.stanza)
reply['from'] = 'gadget.localhost'
reply['to'] = 'alice at localhost'
query = xpath.queryForNodes('/iq/query', reply)[0]
@@ -105,5 +106,53 @@ def test(q, bus, conn, stream):
assert props == {'color': '#005FE4,#00A0FF' }
+ # request 3 random buddies
+ call_async(q, buddy_iface, 'RequestRandom', 3)
+
+ event = q.expect('stream-iq', to='gadget.localhost',
+ query_ns=NS_OLPC_BUDDY)
+ random = xpath.queryForNodes('/iq/query/random', event.stanza)
+ assert len(random) == 1
+ assert random[0]['max'] == '3'
+
+ # reply to random query
+ reply = make_result_iq(stream, event.stanza)
+ reply['from'] = 'gadget.localhost'
+ reply['to'] = 'alice at localhost'
+ query = xpath.queryForNodes('/iq/query', reply)[0]
+ buddy = query.addElement((None, "buddy"))
+ buddy['jid'] = 'bob at localhost'
+ properties = buddy.addElement((NS_OLPC_BUDDY_PROPS, "properties"))
+ property = properties.addElement((None, "property"))
+ property['type'] = 'str'
+ property['name'] = 'color'
+ property.addContent('#005FE4,#00A0FF')
+ stream.send(reply)
+
+ event = q.expect('dbus-return', method='RequestRandom')
+ view_path = event.value[0]
+ view = bus.get_object(conn.bus_name, view_path)
+ view_iface = dbus.Interface(view, 'org.laptop.Telepathy.BuddyView')
+
+ event = q.expect('dbus-signal', signal='PropertiesChanged')
+ handle, props = event.args
+ assert conn.InspectHandles(1, [handle])[0] == 'bob at localhost'
+ assert props == {'color': '#005FE4,#00A0FF'}
+
+ event = q.expect('dbus-signal', signal='MembersChanged')
+ msg, added, removed, lp, rp, actor, reason = event.args
+ assert (removed, lp, rp) == ([], [], [])
+ assert len(added) == 1
+ handle = added[0]
+ assert conn.InspectHandles(1, [handle])[0] == 'bob at localhost'
+
+ call_async(q, view_iface, 'Close')
+ event = q.expect('stream-message', to='gadget.localhost')
+ close = xpath.queryForNodes('/message/close', event.stanza)
+ assert len(close) == 1
+ assert close[0]['id'] == '0'
+
+ event = q.expect('dbus-return', method='Close')
+
if __name__ == '__main__':
exec_test(test)
--
1.5.6.5
More information about the Telepathy-commits
mailing list