diff options
author | Alban Crequy <alban.crequy@collabora.co.uk> | 2008-04-22 11:56:34 +0000 |
---|---|---|
committer | Jonny Lamb <jonnylamb@jonnylamb.com> | 2008-08-11 20:01:09 +0100 |
commit | 907613fee419094261d143c1b65abf2f8f943aa3 (patch) | |
tree | 61eb2ae54ac21e6f5d7340a7081a95fa1e24d2e5 /src | |
parent | 4a9a3bdd876046e800a9bacc369edd6b318e4d3e (diff) | |
download | telepathy-salut-907613fee419094261d143c1b65abf2f8f943aa3.tar.gz |
Salut Tubes Manager
20080422115634-a41c0-5076aef578391df8aa0052f3712b867344283399.gz
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/salut-connection.c | 17 | ||||
-rw-r--r-- | src/salut-tubes-manager.c | 447 | ||||
-rw-r--r-- | src/salut-tubes-manager.h | 75 |
4 files changed, 529 insertions, 12 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c1956369..b294c8da 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 71e40c1f..c946d2aa 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 00000000..0ba83d13 --- /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 00000000..1bf0ce14 --- /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__ */ + |