[Telepathy-commits] [telepathy-gabble/master] GabblePrivateTubesFactory: implement GabbleChannelManager
Simon McVittie
simon.mcvittie at collabora.co.uk
Thu Aug 21 06:31:56 PDT 2008
20080731191715-53eee-92ec3b350351652ad4f28820e8764eec90093abf.gz
---
src/private-tubes-factory.c | 237 ++++++++++++++++++++++++++++++++----------
1 files changed, 180 insertions(+), 57 deletions(-)
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index 55e073e..7175b12 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -26,10 +26,13 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <loudmouth/loudmouth.h>
#include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/dbus.h>
#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
#define DEBUG_FLAG GABBLE_DEBUG_TUBES
+#include "channel-manager.h"
#include "connection.h"
#include "debug.h"
#include "muc-channel.h"
@@ -39,7 +42,7 @@
#include "util.h"
static GabbleTubesChannel *new_tubes_channel (GabblePrivateTubesFactory *fac,
- TpHandle handle, TpHandle initiator);
+ TpHandle handle, TpHandle initiator, gpointer request_token);
static void tubes_channel_closed_cb (GabbleTubesChannel *chan,
gpointer user_data);
@@ -50,10 +53,13 @@ static LmHandlerResult private_tubes_factory_msg_tube_cb (
static void gabble_private_tubes_factory_iface_init (gpointer g_iface,
gpointer iface_data);
+static void channel_manager_iface_init (gpointer, gpointer);
G_DEFINE_TYPE_WITH_CODE (GabblePrivateTubesFactory,
gabble_private_tubes_factory,
G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CHANNEL_MANAGER,
+ channel_manager_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
gabble_private_tubes_factory_iface_init));
@@ -250,9 +256,9 @@ static void
tubes_channel_closed_cb (GabbleTubesChannel *chan,
gpointer user_data)
{
- GabblePrivateTubesFactory *conn = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
+ GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data);
GabblePrivateTubesFactoryPrivate *priv =
- GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (conn);
+ GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self);
TpHandle contact_handle;
if (priv->channels == NULL)
@@ -260,6 +266,9 @@ tubes_channel_closed_cb (GabbleTubesChannel *chan,
g_object_get (chan, "handle", &contact_handle, NULL);
+ gabble_channel_manager_emit_channel_closed_for_object (self,
+ GABBLE_EXPORTABLE_CHANNEL (chan));
+
DEBUG ("removing tubes channel with handle %d", contact_handle);
g_hash_table_remove (priv->channels, GUINT_TO_POINTER (contact_handle));
@@ -273,12 +282,14 @@ tubes_channel_closed_cb (GabbleTubesChannel *chan,
static GabbleTubesChannel *
new_tubes_channel (GabblePrivateTubesFactory *fac,
TpHandle handle,
- TpHandle initiator)
+ TpHandle initiator,
+ gpointer request_token)
{
GabblePrivateTubesFactoryPrivate *priv;
TpBaseConnection *conn;
GabbleTubesChannel *chan;
char *object_path;
+ GSList *request_tokens;
g_assert (GABBLE_IS_PRIVATE_TUBES_FACTORY (fac));
g_assert (handle != 0);
@@ -304,8 +315,21 @@ new_tubes_channel (GabblePrivateTubesFactory *fac,
g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);
+ tp_channel_factory_iface_emit_new_channel (fac, TP_CHANNEL_IFACE (chan),
+ request_token);
+
g_free (object_path);
+ if (request_token != NULL)
+ request_tokens = g_slist_prepend (NULL, request_token);
+ else
+ request_tokens = NULL;
+
+ gabble_channel_manager_emit_new_channel (fac,
+ GABBLE_EXPORTABLE_CHANNEL (chan), request_tokens);
+
+ g_slist_free (request_tokens);
+
return chan;
}
@@ -328,7 +352,7 @@ gabble_private_tubes_factory_close_all (GabblePrivateTubesFactory *fac)
struct _ForeachData
{
- TpChannelFunc foreach;
+ GabbleExportableChannelFunc foreach;
gpointer user_data;
};
@@ -338,17 +362,19 @@ _foreach_slave (gpointer key,
gpointer user_data)
{
struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
+ GabbleExportableChannel *chan = GABBLE_EXPORTABLE_CHANNEL (value);
+
+ g_assert (TP_IS_CHANNEL_IFACE (chan));
data->foreach (chan, data->user_data);
}
static void
-gabble_private_tubes_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc foreach,
- gpointer user_data)
+gabble_private_tubes_factory_foreach_channel (GabbleChannelManager *manager,
+ GabbleExportableChannelFunc foreach,
+ gpointer user_data)
{
- GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (iface);
+ GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (manager);
GabblePrivateTubesFactoryPrivate *priv =
GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac);
struct _ForeachData data;
@@ -368,46 +394,7 @@ gabble_private_tubes_factory_iface_request (TpChannelFactoryIface *iface,
TpChannelIface **ret,
GError **error)
{
- GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (iface);
- GabblePrivateTubesFactoryPrivate *priv =
- GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac);
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
- TpHandleRepoIface *contacts_repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
- GabbleTubesChannel *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, base_conn->self_handle);
- tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *) chan,
- request);
- }
-
- g_assert (chan);
- *ret = TP_CHANNEL_IFACE (chan);
- return status;
+ return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
}
void
@@ -430,9 +417,7 @@ gabble_private_tubes_factory_handle_si_tube_request (
chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle));
if (chan == NULL)
{
- chan = new_tubes_channel (self, handle, handle);
- tp_channel_factory_iface_emit_new_channel (self,
- (TpChannelIface *) chan, NULL);
+ chan = new_tubes_channel (self, handle, handle, NULL);
/* FIXME: Should we close the channel if the request is not properly
* handled by the newly created channel ? */
@@ -519,9 +504,7 @@ private_tubes_factory_msg_tube_cb (LmMessageHandler *handler,
{
/* We create the tubes channel only if the message is a new tube
* offer */
- chan = new_tubes_channel (self, handle, handle);
- tp_channel_factory_iface_emit_new_channel (self,
- (TpChannelIface *) chan, NULL);
+ chan = new_tubes_channel (self, handle, handle, NULL);
}
else
{
@@ -555,6 +538,146 @@ gabble_private_tubes_factory_iface_init (gpointer g_iface,
klass->close_all =
(TpChannelFactoryIfaceProc) gabble_private_tubes_factory_close_all;
- klass->foreach = gabble_private_tubes_factory_iface_foreach;
+ klass->foreach = (TpChannelFactoryIfaceForeachImpl)
+ gabble_private_tubes_factory_foreach_channel;
klass->request = gabble_private_tubes_factory_iface_request;
}
+
+
+static const gchar * const tubes_channel_required_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ NULL
+};
+
+
+static const gchar * const tubes_channel_optional_properties[] = {
+ NULL
+};
+
+
+static void
+gabble_private_tubes_factory_foreach_channel_class (
+ GabbleChannelManager *manager,
+ GabbleChannelManagerChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GValue *value;
+
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TUBES);
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType",
+ value);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+ value);
+
+ func (manager, table, tubes_channel_required_properties,
+ tubes_channel_optional_properties, user_data);
+
+ g_hash_table_destroy (table);
+}
+
+
+static gboolean
+gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
+{
+ TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn;
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_CONTACT);
+ TpHandle handle;
+ GError *error = NULL;
+ GabbleExportableChannel *channel;
+
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TUBES))
+ return FALSE;
+
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
+ return FALSE;
+
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+
+ if (!tp_handle_is_valid (contact_repo, handle, &error))
+ goto error;
+
+ /* Don't support opening a channel to our self handle */
+ if (handle == base_conn->self_handle)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Can't open a channel to your self handle");
+ goto error;
+ }
+
+ channel = g_hash_table_lookup (self->priv->channels,
+ GUINT_TO_POINTER (handle));
+
+ if (channel == NULL)
+ {
+ new_tubes_channel (self, handle, base_conn->self_handle, request_token);
+ return TRUE;
+ }
+
+ if (require_new)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Already chatting with contact #%u in another channel", handle);
+ goto error;
+ }
+
+ gabble_channel_manager_emit_request_already_satisfied (self, request_token,
+ channel);
+ return TRUE;
+
+error:
+ gabble_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
+}
+
+
+static gboolean
+gabble_private_tubes_factory_create_channel (GabbleChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager);
+
+ return gabble_private_tubes_factory_requestotron (self, request_token,
+ request_properties, TRUE);
+}
+
+
+static gboolean
+gabble_private_tubes_factory_request_channel (GabbleChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager);
+
+ return gabble_private_tubes_factory_requestotron (self, request_token,
+ request_properties, FALSE);
+}
+
+
+static void
+channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GabbleChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = gabble_private_tubes_factory_foreach_channel;
+ iface->foreach_channel_class =
+ gabble_private_tubes_factory_foreach_channel_class;
+ iface->create_channel = gabble_private_tubes_factory_create_channel;
+ iface->request_channel = gabble_private_tubes_factory_request_channel;
+}
--
1.5.6.3
More information about the Telepathy-commits
mailing list