[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