[Telepathy-commits] [telepathy-salut/master] Salut Tubes Manager

Alban Crequy alban.crequy at collabora.co.uk
Tue Nov 25 03:59:09 PST 2008


20080422115634-a41c0-5076aef578391df8aa0052f3712b867344283399.gz
---
 src/Makefile.am           |    2 +
 src/salut-connection.c    |   17 +--
 src/salut-tubes-manager.c |  447 +++++++++++++++++++++++++++++++++++++++++++++
 src/salut-tubes-manager.h |   75 ++++++++
 4 files changed, 529 insertions(+), 12 deletions(-)
 create mode 100644 src/salut-tubes-manager.c
 create mode 100644 src/salut-tubes-manager.h

diff --git a/src/Makefile.am b/src/Makefile.am
index c195636..b294c8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,6 +27,8 @@ CORE_SOURCES =                                          \
     salut-muc-manager.h                                 \
     salut-muc-channel.c                                 \
     salut-muc-channel.h                                 \
+    salut-tubes-manager.c                               \
+    salut-tubes-manager.h                               \
     salut-contact.h                                     \
     salut-contact.c                                     \
     salut-self.h                                        \
diff --git a/src/salut-connection.c b/src/salut-connection.c
index 71e40c1..c946d2a 100644
--- a/src/salut-connection.c
+++ b/src/salut-connection.c
@@ -44,9 +44,7 @@
 #include "salut-self.h"
 #include "salut-xmpp-connection-manager.h"
 #include "salut-bytestream-manager.h"
-/*
 #include "salut-tubes-manager.h"
-*/
 
 #include "salut-presence.h"
 
@@ -172,8 +170,7 @@ struct _SalutConnectionPrivate
   SalutMucManager *muc_manager;
 
   /* Tubes channel manager */
-  /* XXX disabled while private tubes aren't implemented */
-  /* SalutTubesManager *tubes_manager; */
+  SalutTubesManager *tubes_manager;
 
   /* Bytestream manager */
   SalutBytestreamManager *bytestream_manager;
@@ -2608,7 +2605,7 @@ static GPtrArray*
 salut_connection_create_channel_factories(TpBaseConnection *base) {
   SalutConnection *self = SALUT_CONNECTION(base);
   SalutConnectionPrivate *priv = SALUT_CONNECTION_GET_PRIVATE(self);
-  GPtrArray *factories = g_ptr_array_sized_new(3);
+  GPtrArray *factories = g_ptr_array_sized_new(4);
 
   /* Create the contact manager */
   priv->contact_manager = salut_contact_manager_new (self);
@@ -2635,16 +2632,12 @@ salut_connection_create_channel_factories(TpBaseConnection *base) {
   priv->muc_manager = salut_muc_manager_new (self,
       priv->xmpp_connection_manager);
 
-  /*
   priv->tubes_manager = salut_tubes_manager_new (self, priv->contact_manager);
-  */
 
-  g_ptr_array_add(factories, priv->contact_manager);
-  g_ptr_array_add(factories, priv->im_manager);
-  g_ptr_array_add(factories, priv->muc_manager);
-  /*
+  g_ptr_array_add (factories, priv->contact_manager);
+  g_ptr_array_add (factories, priv->im_manager);
+  g_ptr_array_add (factories, priv->muc_manager);
   g_ptr_array_add (factories, priv->tubes_manager);
-  */
 
   return factories;
 }
diff --git a/src/salut-tubes-manager.c b/src/salut-tubes-manager.c
new file mode 100644
index 0000000..0ba83d1
--- /dev/null
+++ b/src/salut-tubes-manager.c
@@ -0,0 +1,447 @@
+/*
+ * salut-tubes-manager.c - Source for SalutTubesManager
+ * Copyright (C) 2006-2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "salut-tubes-manager.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#define DEBUG_FLAG DEBUG_TUBES
+
+#include "debug.h"
+#include "extensions/extensions.h"
+#include "salut-connection.h"
+#include "salut-tubes-channel.h"
+#include "salut-muc-manager.h"
+#include "salut-muc-channel.h"
+#include <gibber/gibber-namespaces.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/channel-factory-iface.h>
+
+static SalutTubesChannel *new_tubes_channel (SalutTubesManager *fac,
+    TpHandle handle);
+
+static void tubes_channel_closed_cb (SalutTubesChannel *chan,
+    gpointer user_data);
+
+static void salut_tubes_manager_iface_init (gpointer g_iface,
+    gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (SalutTubesManager,
+    salut_tubes_manager,
+    G_TYPE_OBJECT,
+    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
+        salut_tubes_manager_iface_init));
+
+/* properties */
+enum
+{
+  PROP_CONNECTION = 1,
+  LAST_PROPERTY
+};
+
+typedef struct _SalutTubesManagerPrivate \
+          SalutTubesManagerPrivate;
+struct _SalutTubesManagerPrivate
+{
+  SalutConnection *conn;
+
+  GHashTable *channels;
+
+  gboolean dispose_has_run;
+};
+
+#define SALUT_TUBES_MANAGER_GET_PRIVATE(obj) \
+    ((SalutTubesManagerPrivate *) obj->priv)
+
+static void
+salut_tubes_manager_init (SalutTubesManager *self)
+{
+  SalutTubesManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+      SALUT_TYPE_TUBES_MANAGER, SalutTubesManagerPrivate);
+
+  self->priv = priv;
+
+  priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, g_object_unref);
+
+  priv->conn = NULL;
+  priv->dispose_has_run = FALSE;
+}
+
+static GObject *
+salut_tubes_manager_constructor (GType type,
+                                  guint n_props,
+                                  GObjectConstructParam *props)
+{
+  GObject *obj;
+  SalutTubesManager *self;
+  SalutTubesManagerPrivate *priv;
+
+  obj = G_OBJECT_CLASS (salut_tubes_manager_parent_class)->
+           constructor (type, n_props, props);
+
+  self = SALUT_TUBES_MANAGER (obj);
+  priv = SALUT_TUBES_MANAGER_GET_PRIVATE (self);
+
+  return obj;
+}
+
+static void
+salut_tubes_manager_dispose (GObject *object)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (object);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+
+  if (priv->dispose_has_run)
+    return;
+
+  DEBUG ("dispose called");
+  priv->dispose_has_run = TRUE;
+
+  tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
+  g_assert (priv->channels == NULL);
+
+  if (G_OBJECT_CLASS (salut_tubes_manager_parent_class)->dispose)
+    G_OBJECT_CLASS (salut_tubes_manager_parent_class)->dispose (
+        object);
+}
+
+static void
+salut_tubes_manager_get_property (GObject *object,
+                                   guint property_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (object);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        g_value_set_object (value, priv->conn);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+salut_tubes_manager_set_property (GObject *object,
+                                   guint property_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (object);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        priv->conn = g_value_get_object (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+salut_tubes_manager_class_init (
+    SalutTubesManagerClass *salut_tubes_manager_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (
+      salut_tubes_manager_class);
+  GParamSpec *param_spec;
+
+  g_type_class_add_private (salut_tubes_manager_class,
+      sizeof (SalutTubesManagerPrivate));
+
+  object_class->constructor = salut_tubes_manager_constructor;
+  object_class->dispose = salut_tubes_manager_dispose;
+
+  object_class->get_property = salut_tubes_manager_get_property;
+  object_class->set_property = salut_tubes_manager_set_property;
+
+  param_spec = g_param_spec_object (
+      "connection",
+      "SalutConnection object",
+      "Salut connection object that owns this Tubes channel factory object.",
+      SALUT_TYPE_CONNECTION,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NAME |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+}
+
+
+/**
+ * tubes_channel_closed_cb:
+ *
+ * Signal callback for when an Tubes channel is closed. Removes the references
+ * that TubesManager holds to them.
+ */
+static void
+tubes_channel_closed_cb (SalutTubesChannel *chan,
+                         gpointer user_data)
+{
+  SalutTubesManager *conn = SALUT_TUBES_MANAGER (user_data);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (conn);
+  TpHandle contact_handle;
+
+  if (priv->channels == NULL)
+    return;
+
+  g_object_get (chan, "handle", &contact_handle, NULL);
+
+  DEBUG ("removing tubes channel with handle %d", contact_handle);
+
+  g_hash_table_remove (priv->channels, GUINT_TO_POINTER (contact_handle));
+}
+
+/**
+ * new_tubes_channel
+ *
+ * Creates the SalutTubes object associated with the given parameters
+ */
+static SalutTubesChannel *
+new_tubes_channel (SalutTubesManager *fac,
+                   TpHandle handle)
+{
+  SalutTubesManagerPrivate *priv;
+  TpBaseConnection *conn;
+  SalutTubesChannel *chan;
+  char *object_path;
+
+  g_assert (SALUT_IS_TUBES_MANAGER (fac));
+
+  priv = SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+  conn = (TpBaseConnection *) priv->conn;
+
+  object_path = g_strdup_printf ("%s/TubesChannel%u", conn->object_path,
+      handle);
+
+  chan = g_object_new (SALUT_TYPE_TUBES_CHANNEL,
+                       "connection", priv->conn,
+                       "object-path", object_path,
+                       "handle", handle,
+                       "handle-type", TP_HANDLE_TYPE_CONTACT,
+                       NULL);
+
+  DEBUG ("object path %s", object_path);
+
+  g_signal_connect (chan, "closed", G_CALLBACK (tubes_channel_closed_cb), fac);
+
+  g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);
+
+  g_free (object_path);
+
+  return chan;
+}
+
+static void
+salut_tubes_manager_iface_close_all (TpChannelFactoryIface *iface)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (iface);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+  GHashTable *tmp;
+
+  DEBUG ("closing 1-1 tubes channels");
+
+  if (priv->channels == NULL)
+    return;
+
+  tmp = priv->channels;
+  priv->channels = NULL;
+  g_hash_table_destroy (tmp);
+}
+
+static void
+salut_tubes_manager_iface_connecting (TpChannelFactoryIface *iface)
+{
+  /* nothing to do */
+}
+
+static void
+salut_tubes_manager_iface_connected (TpChannelFactoryIface *iface)
+{
+  /* nothing to do */
+}
+
+static void
+salut_tubes_manager_iface_disconnected (TpChannelFactoryIface *iface)
+{
+  /* nothing to do */
+}
+
+struct _ForeachData
+{
+  TpChannelFunc foreach;
+  gpointer user_data;
+};
+
+static void
+_foreach_slave (gpointer key,
+                gpointer value,
+                gpointer user_data)
+{
+  struct _ForeachData *data = (struct _ForeachData *) user_data;
+  TpChannelIface *chan = TP_CHANNEL_IFACE (value);
+
+  data->foreach (chan, data->user_data);
+}
+
+static void
+salut_tubes_manager_iface_foreach (TpChannelFactoryIface *iface,
+                                    TpChannelFunc foreach,
+                                    gpointer user_data)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (iface);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+  struct _ForeachData data;
+
+  data.user_data = user_data;
+  data.foreach = foreach;
+
+  g_hash_table_foreach (priv->channels, _foreach_slave, &data);
+}
+
+static TpChannelFactoryRequestStatus
+salut_tubes_manager_iface_request (TpChannelFactoryIface *iface,
+                                    const gchar *chan_type,
+                                    TpHandleType handle_type,
+                                    guint handle,
+                                    gpointer request,
+                                    TpChannelIface **ret,
+                                    GError **error)
+{
+  SalutTubesManager *fac = SALUT_TUBES_MANAGER (iface);
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
+  TpHandleRepoIface *contacts_repo = tp_base_connection_get_handles (
+      (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+  SalutTubesChannel *chan;
+  TpChannelFactoryRequestStatus status;
+
+  if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TUBES))
+    return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
+
+  if (handle_type != TP_HANDLE_TYPE_CONTACT)
+    return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
+
+  if (!tp_handle_is_valid (contacts_repo, handle, NULL))
+    return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
+
+  /* Don't support opening a channel to our self handle */
+  if (handle == ((TpBaseConnection*) priv->conn)->self_handle)
+    {
+     g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+         "Can't open a channel to your self handle");
+     return TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR;
+    }
+
+  chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));
+
+  status = TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
+  if (chan == NULL)
+    {
+      status = TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
+      chan = new_tubes_channel (fac, handle);
+      tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *)chan,
+          request);
+    }
+
+  g_assert (chan);
+  *ret = TP_CHANNEL_IFACE (chan);
+  return status;
+}
+
+void
+salut_tubes_manager_handle_tube_request (
+    SalutTubesManager *self,
+    GibberBytestreamIface *bytestream,
+    TpHandle handle,
+    const gchar *stream_id,
+    GibberXmppStanza *msg)
+{
+  SalutTubesManagerPrivate *priv =
+    SALUT_TUBES_MANAGER_GET_PRIVATE (self);
+  TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+              (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+  SalutTubesChannel *chan;
+
+  DEBUG ("contact#%u stream %s", handle, stream_id);
+  g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL));
+
+  chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));
+  if (chan == NULL)
+    {
+      chan = new_tubes_channel (self, handle);
+      tp_channel_factory_iface_emit_new_channel (self,
+          (TpChannelIface *) chan, NULL);
+
+      /* FIXME: Should we close the channel if the request is not properly
+       * handled by the newly created channel ? */
+    }
+
+  salut_tubes_channel_bytestream_offered (chan, bytestream, msg);
+}
+
+SalutTubesManager *
+salut_tubes_manager_new (
+    SalutConnection *conn,
+    SalutContactManager *contact_manager)
+{
+  g_return_val_if_fail (SALUT_IS_CONNECTION (conn), NULL);
+
+  return g_object_new (
+      SALUT_TYPE_TUBES_MANAGER,
+      "connection", conn,
+      NULL);
+}
+
+static void
+salut_tubes_manager_iface_init (gpointer g_iface,
+                                 gpointer iface_data)
+{
+  TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
+
+  klass->close_all = salut_tubes_manager_iface_close_all;
+  klass->connecting = salut_tubes_manager_iface_connecting;
+  klass->connected = salut_tubes_manager_iface_connected;
+  klass->disconnected = salut_tubes_manager_iface_disconnected;
+  klass->foreach = salut_tubes_manager_iface_foreach;
+  klass->request = salut_tubes_manager_iface_request;
+}
diff --git a/src/salut-tubes-manager.h b/src/salut-tubes-manager.h
new file mode 100644
index 0000000..1bf0ce1
--- /dev/null
+++ b/src/salut-tubes-manager.h
@@ -0,0 +1,75 @@
+/*
+ * salut-tubes-manager.h - Header for SalutTubesManager
+ * Copyright (C) 2006-2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SALUT_TUBES_MANAGER_H__
+#define __SALUT_TUBES_MANAGER_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/base-connection.h>
+#include "salut-connection.h"
+#include "salut-contact-manager.h"
+#include "salut-tubes-channel.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutTubesManagerClass SalutTubesManagerClass;
+typedef struct _SalutTubesManager SalutTubesManager;
+
+struct _SalutTubesManagerClass {
+  GObjectClass parent_class;
+};
+
+struct _SalutTubesManager {
+  GObject parent;
+
+  gpointer priv;
+};
+
+GType salut_tubes_manager_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_TUBES_MANAGER \
+  (salut_tubes_manager_get_type ())
+#define SALUT_TUBES_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_TUBES_MANAGER,\
+                              SalutTubesManager))
+#define SALUT_TUBES_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_TUBES_MANAGER,\
+                           SalutTubesManagerClass))
+#define SALUT_IS_TUBES_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_TUBES_MANAGER))
+#define SALUT_IS_TUBES_MANAGER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_TUBES_MANAGER))
+#define SALUT_TUBES_MANAGER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_TUBES_MANAGER,\
+                              SalutTubesManagerClass))
+
+SalutTubesManager * salut_tubes_manager_new (
+    SalutConnection *conn,
+    SalutContactManager *contact_manager);
+
+void salut_tubes_manager_handle_tube_request (
+    SalutTubesManager *self, GibberBytestreamIface *bytestream,
+    TpHandle handle, const gchar *stream_id, GibberXmppStanza *msg);
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_TUBES_MANAGER_H__ */
+
-- 
1.5.6.5




More information about the Telepathy-commits mailing list