[Telepathy-commits] [telepathy-salut/master] Start the convert from a channel factory to a channel manager
Guillaume Desmottes
guillaume.desmottes at collabora.co.uk
Fri Nov 21 03:46:33 PST 2008
---
src/salut-ft-manager.c | 301 +++++++++++++++++++++++++++++++++++-------------
1 files changed, 221 insertions(+), 80 deletions(-)
diff --git a/src/salut-ft-manager.c b/src/salut-ft-manager.c
index a4d0161..7273066 100644
--- a/src/salut-ft-manager.c
+++ b/src/salut-ft-manager.c
@@ -34,19 +34,24 @@
#include <telepathy-glib/channel-factory-iface.h>
#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/dbus.h>
#define DEBUG_FLAG DEBUG_FT
#include "debug.h"
static void
-salut_ft_manager_factory_iface_init (gpointer *g_iface, gpointer *iface_data);
+channel_manager_iface_init (gpointer, gpointer);
static SalutFileTransferChannel *
-salut_ft_manager_new_channel (SalutFtManager *mgr, TpHandle handle, gboolean incoming);
+salut_ft_manager_new_channel (SalutFtManager *mgr, TpHandle handle,
+ const gchar *content_type, const gchar *filename, guint64 size,
+ SalutFileHashType content_hash_type, const gchar *content_hash,
+ const gchar *description, guint64 date, guint64 initial_offset,
+ gpointer request);
G_DEFINE_TYPE_WITH_CODE (SalutFtManager, salut_ft_manager, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- salut_ft_manager_factory_iface_init));
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ channel_manager_iface_init));
/* signal enum */
/*
@@ -114,7 +119,13 @@ message_stanza_callback (SalutXmppConnectionManager *mgr,
handle = tp_handle_lookup (handle_repo, contact->name, NULL, NULL);
g_assert (handle != 0);
- chan = salut_ft_manager_new_channel (self, handle, TRUE);
+ /* FIXME: get content_type from the protocol */
+ /* FIXME: get filename from the protocol */
+ /* FIXME: get content_hash_type type and content_hash from the protocol */
+ /* FIXME: get date from the protocol */
+ /* FIXME: get initial offset from the protocol */
+ chan = salut_ft_manager_new_channel (self, handle, "application/octet-stream",
+ "test.txt", 1000, SALUT_FILE_HASH_TYPE_NONE, NULL, NULL, 0, 0, NULL);
salut_file_transfer_channel_received_file_offer (chan, stanza, conn);
}
@@ -180,36 +191,10 @@ salut_ft_manager_finalize (GObject *object)
G_OBJECT_CLASS (salut_ft_manager_parent_class)->finalize (object);
}
-/* Channel Factory interface */
-
-static void
-salut_ft_manager_factory_iface_close_all (TpChannelFactoryIface *iface)
-{
- SalutFtManager *mgr = SALUT_FT_MANAGER (iface);
- SalutFtManagerPrivate *priv = SALUT_FT_MANAGER_GET_PRIVATE (mgr);
-
- if (priv->channels)
- g_list_free (priv->channels);
-}
-
-static void
-salut_ft_manager_factory_iface_connecting (TpChannelFactoryIface *iface)
-{
-}
-
-static void
-salut_ft_manager_factory_iface_connected (TpChannelFactoryIface *iface)
-{
-}
-
-static void
-salut_ft_manager_factory_iface_disconnected (TpChannelFactoryIface *iface)
-{
- /* FIXME close all channels ? */
-}
+/* Channel Manager interface */
struct foreach_data {
- TpChannelFunc func;
+ TpExportableChannelFunc func;
gpointer data;
};
@@ -219,15 +204,17 @@ salut_ft_manager_iface_foreach_one (gpointer value,
{
if (!value)
return;
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
+
+ TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
struct foreach_data *f = (struct foreach_data *) data;
f->func (chan, f->data);
}
static void
-salut_ft_manager_factory_iface_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc func, gpointer data)
+salut_ft_manager_foreach_channel (TpChannelManager *iface,
+ TpExportableChannelFunc func,
+ gpointer data)
{
SalutFtManager *mgr = SALUT_FT_MANAGER (iface);
SalutFtManagerPrivate *priv = SALUT_FT_MANAGER_GET_PRIVATE (mgr);
@@ -235,7 +222,8 @@ salut_ft_manager_factory_iface_foreach (TpChannelFactoryIface *iface,
f.func = func;
f.data = data;
- g_list_foreach (priv->channels, (GFunc) salut_ft_manager_iface_foreach_one, &f);
+ g_list_foreach (priv->channels, (GFunc) salut_ft_manager_iface_foreach_one,
+ &f);
}
static void
@@ -256,7 +244,15 @@ file_channel_closed_cb (SalutFileTransferChannel *chan, gpointer user_data)
static SalutFileTransferChannel *
salut_ft_manager_new_channel (SalutFtManager *mgr,
TpHandle handle,
- gboolean incoming)
+ const gchar *content_type,
+ const gchar *filename,
+ guint64 size,
+ SalutFileHashType content_hash_type,
+ const gchar *content_hash,
+ const gchar *description,
+ guint64 date,
+ guint64 initial_offset,
+ gpointer request)
{
SalutFtManagerPrivate *priv = SALUT_FT_MANAGER_GET_PRIVATE (mgr);
TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->connection);
@@ -267,6 +263,8 @@ salut_ft_manager_new_channel (SalutFtManager *mgr,
const gchar *name;
gchar *path = NULL;
guint state;
+ GSList *requests = NULL;
+ TpHandle initiator;
/* Increasing guint to make sure object paths are random */
static guint id = 0;
@@ -277,12 +275,20 @@ salut_ft_manager_new_channel (SalutFtManager *mgr,
if (contact == NULL)
return NULL;
- DEBUG ("%s channel requested", incoming ? "Incoming" : "Outgoing");
+ DEBUG ("%s channel requested", request == NULL ? "Incoming" : "Outgoing");
- if (incoming)
- state = SALUT_FILE_TRANSFER_STATE_LOCAL_PENDING;
+ if (request == NULL)
+ {
+ /* incoming channel */
+ state = SALUT_FILE_TRANSFER_STATE_LOCAL_PENDING;
+ initiator = handle;
+ }
else
- state = SALUT_FILE_TRANSFER_STATE_NOT_OFFERED;
+ {
+ /* outgoing channel */
+ state = SALUT_FILE_TRANSFER_STATE_NOT_OFFERED;
+ initiator = base_connection->self_handle;
+ }
name = tp_handle_inspect (handle_repo, handle);
path = g_strdup_printf ("%s/FileTransferChannel/%u/%u",
@@ -296,14 +302,29 @@ salut_ft_manager_new_channel (SalutFtManager *mgr,
"object-path", path,
"handle", handle,
"xmpp-connection-manager", priv->xmpp_connection_manager,
- "incoming", incoming,
+ "initiator-handle", initiator,
"state", state,
+ "content-type", content_type,
+ "filename", filename,
+ "size", size,
+ "content-hash-type", content_hash_type,
+ "content-hash", content_hash,
+ "description", description,
+ "date", date,
+ "initial-offset", initial_offset,
NULL);
g_object_unref (contact);
g_free (path);
- tp_channel_factory_iface_emit_new_channel (mgr, TP_CHANNEL_IFACE (chan),
- NULL);
+
+ if (request != NULL)
+ requests = g_slist_prepend (requests, request);
+
+ tp_channel_manager_emit_new_channel (mgr, TP_EXPORTABLE_CHANNEL (chan),
+ requests);
+
+ g_slist_free (requests);
+
g_signal_connect (chan, "closed", G_CALLBACK (file_channel_closed_cb), mgr);
priv->channels = g_list_append (priv->channels, chan);
@@ -311,65 +332,185 @@ salut_ft_manager_new_channel (SalutFtManager *mgr,
return chan;
}
-static TpChannelFactoryRequestStatus
-salut_ft_manager_factory_iface_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
+static gboolean
+salut_ft_manager_handle_request (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
{
- SalutFtManager *mgr = SALUT_FT_MANAGER (iface);
- SalutFtManagerPrivate *priv = SALUT_FT_MANAGER_GET_PRIVATE (mgr);
+ SalutFtManager *self = SALUT_FT_MANAGER (manager);
+ SalutFtManagerPrivate *priv = SALUT_FT_MANAGER_GET_PRIVATE (self);
SalutFileTransferChannel *chan;
TpBaseConnection *base_connection = TP_BASE_CONNECTION (priv->connection);
- TpHandleRepoIface *handle_repo =
+ TpHandleRepoIface *contact_repo =
tp_base_connection_get_handles (base_connection, TP_HANDLE_TYPE_CONTACT);
+ TpHandle handle;
+ const gchar *content_type, *filename, *content_hash, *description;
+ guint64 size, date, initial_offset;
+ SalutFileHashType content_hash_type;
+ GError *error = NULL;
+ gboolean valid;
DEBUG ("File transfer request");
/* We only support file transfer channels */
- if (tp_strdiff (chan_type, SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"),
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER))
+ return FALSE;
+
+ /* And only contact handles */
+ 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);
+
+ /* Must be a valid contact handle */
+ if (!tp_handle_is_valid (contact_repo, handle, &error))
+ goto error;
+
+ /* Don't support opening a channel to our self handle */
+ if (handle == base_connection->self_handle)
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+ "Can't open a file transfer channel to yourself");
+ goto error;
}
- /* And only contact handles */
- if (handle_type != TP_HANDLE_TYPE_CONTACT)
+ content_type = tp_asv_get_string (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentType");
+ if (content_type == NULL)
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "ContentType property is mandatory");
+ goto error;
}
- /* Must be a valid contact handle */
- if (!tp_handle_is_valid (handle_repo, TP_HANDLE_TYPE_CONTACT, NULL))
+ filename = tp_asv_get_string (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Filename");
+ if (filename == NULL)
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Filename property is mandatory");
+ goto error;
}
- /* Don't support opening a channel to our self handle */
- if (handle == base_connection->self_handle)
+ size = tp_asv_get_uint64 (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Size", NULL);
+ if (size == 0)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Size property is mandatory");
+ goto error;
+ }
+
+ content_hash_type = tp_asv_get_uint32 (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", &valid);
+ if (!valid)
+ {
+ /* Assume File_Hash_Type_None */
+ content_hash_type = SALUT_FILE_HASH_TYPE_NONE;
+ }
+
+ if (content_hash_type != SALUT_FILE_HASH_TYPE_NONE)
+ {
+ content_hash = tp_asv_get_string (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHash");
+ if (content_hash == NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "ContentHash property is mandatory if ContentHashType is "
+ "not None");
+ goto error;
+ }
+ }
+ else
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
+ content_hash = NULL;
}
- chan = salut_ft_manager_new_channel (mgr, handle, FALSE);
- *ret = TP_CHANNEL_IFACE (chan);
+ description = tp_asv_get_string (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Description");
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
+ date = tp_asv_get_uint64 (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Date", NULL);
+ /* FIXME: can we have a valid date of 0 ? */
+
+ initial_offset = tp_asv_get_uint64 (request_properties,
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".InitialOffset", NULL);
+
+ chan = salut_ft_manager_new_channel (self, handle, content_type, filename,
+ size, content_hash_type, content_hash, description, date,
+ initial_offset, request_token);
+ return TRUE;
+
+error:
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
}
-static void salut_ft_manager_factory_iface_init (gpointer *g_iface,
- gpointer *iface_data)
+static const gchar * const file_transfer_channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
+};
+
+static const gchar * const file_transfer_channel_allowed_properties[] =
{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *)g_iface;
-
- klass->close_all = salut_ft_manager_factory_iface_close_all;
- klass->connecting = salut_ft_manager_factory_iface_connecting;
- klass->connected = salut_ft_manager_factory_iface_connected;
- klass->disconnected = salut_ft_manager_factory_iface_disconnected;
- klass->foreach = salut_ft_manager_factory_iface_foreach;
- klass->request = salut_ft_manager_factory_iface_request;
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentType",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Filename",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Size",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHash",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Description",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Date",
+ SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".InitialOffset",
+ NULL
+};
+
+static void
+salut_ft_manager_foreach_channel_class (TpChannelManager *manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table;
+ GValue *value;
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER);
+ g_hash_table_insert (table,
+ (gchar *) file_transfer_channel_fixed_properties[0], value);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ g_hash_table_insert (table,
+ (gchar *) file_transfer_channel_fixed_properties[1], value);
+
+ func (manager, table, file_transfer_channel_allowed_properties,
+ user_data);
+
+ g_hash_table_destroy (table);
+}
+
+static void
+channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = salut_ft_manager_foreach_channel;
+ iface->foreach_channel_class = salut_ft_manager_foreach_channel_class;
+ iface->request_channel = salut_ft_manager_handle_request;
+ iface->create_channel = salut_ft_manager_handle_request;
+ iface->ensure_channel = salut_ft_manager_handle_request;
}
/* public functions */
--
1.5.6.5
More information about the Telepathy-commits
mailing list