[Telepathy-commits] [telepathy-salut/master] move salut-file-channel.[ch] to salut-file-transfer-channel.[ch]

Guillaume Desmottes guillaume.desmottes at collabora.co.uk
Fri Nov 21 03:46:33 PST 2008


---
 src/Makefile.am                   |    4 +-
 src/salut-file-channel.c          | 1225 -------------------------------------
 src/salut-file-channel.h          |   74 ---
 src/salut-file-transfer-channel.c | 1225 +++++++++++++++++++++++++++++++++++++
 src/salut-file-transfer-channel.h |   74 +++
 src/salut-ft-manager.c            |    2 +-
 6 files changed, 1302 insertions(+), 1302 deletions(-)
 delete mode 100644 src/salut-file-channel.c
 delete mode 100644 src/salut-file-channel.h
 create mode 100644 src/salut-file-transfer-channel.c
 create mode 100644 src/salut-file-transfer-channel.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 0df73f4..336f1fd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,8 +28,8 @@ CORE_SOURCES =                                          \
     salut-muc-channel.c                                 \
     salut-ft-manager.c                                  \
     salut-ft-manager.h                                  \
-    salut-file-channel.c                                \
-    salut-file-channel.h                                \
+    salut-file-transfer-channel.c                       \
+    salut-file-transfer-channel.h                       \
     salut-muc-channel.h                                 \
     salut-contact.h                                     \
     salut-contact.c                                     \
diff --git a/src/salut-file-channel.c b/src/salut-file-channel.c
deleted file mode 100644
index 6624911..0000000
--- a/src/salut-file-channel.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- * salut-file-channel.c - Source for SalutFileChannel
- * Copyright (C) 2007 Marco Barisione <marco at barisione.org>
- * Copyright (C) 2005, 2007, 2008 Collabora Ltd.
- *   @author: Sjoerd Simons <sjoerd at luon.net>
- *   @author: Jonny Lamb <jonny.lamb at collabora.co.uk>
- *
- * 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 <glib/gstdio.h>
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#define DEBUG_FLAG DEBUG_FT
-#include "debug.h"
-
-#include "salut-file-channel.h"
-#include "signals-marshal.h"
-
-#include "salut-connection.h"
-#include "salut-im-manager.h"
-#include "salut-contact.h"
-
-#include <gibber/gibber-xmpp-stanza.h>
-#include <gibber/gibber-file-transfer.h>
-#include <gibber/gibber-oob-file-transfer.h>
-
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/svc-generic.h>
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data);
-static void
-file_transfer_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (SalutFileChannel, salut_file_channel, G_TYPE_OBJECT,
-    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
-                           tp_dbus_properties_mixin_iface_init);
-    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
-    G_IMPLEMENT_INTERFACE (SALUT_TYPE_SVC_CHANNEL_TYPE_FILE_TRANSFER,
-                           file_transfer_iface_init);
-);
-
-#define CHECK_STR_EMPTY(x) ((x) == NULL || (x)[0] == '\0')
-
-#define SALUT_UNDEFINED_FILE_SIZE G_MAXUINT64
-
-static const char *salut_file_channel_interfaces[] = { NULL };
-
-/* properties */
-enum
-{
-  PROP_OBJECT_PATH = 1,
-  PROP_CHANNEL_TYPE,
-  PROP_HANDLE_TYPE,
-  PROP_HANDLE,
-  PROP_CONTACT,
-  PROP_CONNECTION,
-  PROP_INTERFACES,
-  PROP_XMPP_CONNECTION_MANAGER,
-  PROP_INCOMING,
-  PROP_STATE,
-  PROP_CONTENT_TYPE,
-  PROP_FILENAME,
-  PROP_SIZE,
-  PROP_CONTENT_HASH_TYPE,
-  PROP_CONTENT_HASH,
-  PROP_DESCRIPTION,
-  PROP_AVAILABLE_SOCKET_TYPES,
-  PROP_TRANSFERRED_BYTES,
-  PROP_INITIAL_OFFSET,
-  LAST_PROPERTY
-};
-
-/* private structure */
-struct _SalutFileChannelPrivate {
-  gboolean dispose_has_run;
-  gboolean closed;
-  gchar *object_path;
-  TpHandle handle;
-  SalutContact *contact;
-  SalutConnection *connection;
-  SalutXmppConnectionManager *xmpp_connection_manager;
-  GibberXmppConnection *xmpp_connection;
-  GibberFileTransfer *ft;
-  glong last_transferred_bytes_emitted;
-  gchar *socket_path;
-  gboolean incoming;
-
-  /* properties */
-  SalutFileTransferState state;
-  gchar *content_type;
-  gchar *filename;
-  guint64 size;
-  SalutFileHashType content_hash_type;
-  gchar *content_hash;
-  gchar *description;
-  GHashTable *available_socket_types;
-  guint64 transferred_bytes;
-  guint64 initial_offset;
-};
-
-static void
-salut_file_channel_do_close (SalutFileChannel *self)
-{
-  if (self->priv->closed)
-    return;
-
-  DEBUG ("Emitting closed signal for %s", self->priv->object_path);
-  tp_svc_channel_emit_closed (self);
-  self->priv->closed = TRUE;
-}
-
-static void
-salut_file_channel_init (SalutFileChannel *obj)
-{
-  obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, SALUT_TYPE_FILE_CHANNEL,
-      SalutFileChannelPrivate);
-
-  /* allocate any data required by the object here */
-  obj->priv->object_path = NULL;
-  obj->priv->connection = NULL;
-  obj->priv->xmpp_connection_manager = NULL;
-  obj->priv->contact = NULL;
-}
-
-static void salut_file_channel_set_state (SalutSvcChannelTypeFileTransfer *iface,
-    SalutFileTransferState state, SalutFileTransferStateChangeReason reason);
-
-static void
-salut_file_channel_get_property (GObject    *object,
-                                 guint       property_id,
-                                 GValue     *value,
-                                 GParamSpec *pspec)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
-
-  switch (property_id)
-    {
-      case PROP_OBJECT_PATH:
-        g_value_set_string (value, self->priv->object_path);
-        break;
-      case PROP_CHANNEL_TYPE:
-        g_value_set_static_string (value,
-            SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER);
-        break;
-      case PROP_HANDLE_TYPE:
-        g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
-        break;
-      case PROP_HANDLE:
-        g_value_set_uint (value, self->priv->handle);
-        break;
-      case PROP_CONTACT:
-        g_value_set_object (value, self->priv->contact);
-        break;
-      case PROP_CONNECTION:
-        g_value_set_object (value, self->priv->connection);
-        break;
-      case PROP_INTERFACES:
-        g_value_set_boxed (value, salut_file_channel_interfaces);
-        break;
-      case PROP_XMPP_CONNECTION_MANAGER:
-        g_value_set_object (value, self->priv->xmpp_connection_manager);
-        break;
-      case PROP_INCOMING:
-        g_value_set_boolean (value, self->priv->incoming);
-        break;
-      case PROP_STATE:
-        g_value_set_uint (value, self->priv->state);
-        break;
-      case PROP_CONTENT_TYPE:
-        g_value_set_string (value, self->priv->content_type);
-        break;
-      case PROP_FILENAME:
-        g_value_set_string (value, self->priv->filename);
-        break;
-      case PROP_SIZE:
-        g_value_set_uint64 (value, self->priv->size);
-        break;
-      case PROP_CONTENT_HASH_TYPE:
-        g_value_set_uint (value, self->priv->content_hash_type);
-        break;
-      case PROP_CONTENT_HASH:
-        g_value_set_string (value, self->priv->content_hash);
-        break;
-      case PROP_DESCRIPTION:
-        g_value_set_string (value, self->priv->description);
-        break;
-      case PROP_AVAILABLE_SOCKET_TYPES:
-        g_value_set_boxed (value, self->priv->available_socket_types);
-        break;
-      case PROP_TRANSFERRED_BYTES:
-        g_value_set_uint64 (value, self->priv->transferred_bytes);
-        break;
-      case PROP_INITIAL_OFFSET:
-        g_value_set_uint64 (value, self->priv->initial_offset);
-        break;
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-        break;
-    }
-}
-
-static void
-salut_file_channel_set_property (GObject *object,
-                                 guint property_id,
-                                 const GValue *value,
-                                 GParamSpec *pspec)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
-  const gchar *tmp;
-
-  switch (property_id)
-    {
-      case PROP_OBJECT_PATH:
-        g_free (self->priv->object_path);
-        self->priv->object_path = g_value_dup_string (value);
-        break;
-      case PROP_HANDLE:
-        self->priv->handle = g_value_get_uint (value);
-        break;
-      case PROP_CONTACT:
-        self->priv->contact = g_value_dup_object (value);
-        break;
-      case PROP_CONNECTION:
-        self->priv->connection = g_value_get_object (value);
-        break;
-      case PROP_HANDLE_TYPE:
-        g_assert (g_value_get_uint (value) == 0
-                  || g_value_get_uint (value) == TP_HANDLE_TYPE_CONTACT);
-        break;
-      case PROP_CHANNEL_TYPE:
-        tmp = g_value_get_string (value);
-        g_assert (tmp == NULL
-                  || !tp_strdiff (g_value_get_string (value),
-                         SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER));
-        break;
-      case PROP_XMPP_CONNECTION_MANAGER:
-        self->priv->xmpp_connection_manager = g_value_dup_object (value);
-        break;
-      case PROP_STATE:
-        salut_file_channel_set_state (
-            SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (object),
-            g_value_get_uint (value),
-            SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-        break;
-      case PROP_INCOMING:
-        self->priv->incoming = g_value_get_boolean (value);
-        break;
-      case PROP_CONTENT_TYPE:
-        /* This should not be writeable with the new request API */
-        self->priv->content_type = g_value_dup_string (value);
-        break;
-      case PROP_FILENAME:
-        /* This should not be writeable with the new request API */
-        self->priv->filename = g_value_dup_string (value);
-        break;
-      case PROP_SIZE:
-        /* This should not be writeable with the new request API */
-        self->priv->size = g_value_get_uint64 (value);
-        break;
-      case PROP_CONTENT_HASH_TYPE:
-        /* This should not be writeable with the new request API */
-        self->priv->content_hash_type = g_value_get_uint (value);
-        break;
-      case PROP_CONTENT_HASH:
-        /* This should not be writeable with the new request API */
-        self->priv->content_hash = g_value_dup_string (value);
-        break;
-      case PROP_DESCRIPTION:
-        /* This should not be writeable with the new request API */
-        self->priv->description = g_value_dup_string (value);
-        break;
-      case PROP_AVAILABLE_SOCKET_TYPES:
-        self->priv->available_socket_types = g_value_get_boxed (value);
-        break;
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-        break;
-    }
-}
-
-static GObject *
-salut_file_channel_constructor (GType type, guint n_props,
-                                GObjectConstructParam *props)
-{
-  GObject *obj;
-  SalutFileChannel *self;
-  DBusGConnection *bus;
-  TpBaseConnection *base_conn;
-  TpHandleRepoIface *contact_repo;
-
-  /* Parent constructor chain */
-  obj = G_OBJECT_CLASS (salut_file_channel_parent_class)->
-          constructor (type, n_props, props);
-
-  self = SALUT_FILE_CHANNEL (obj);
-
-  /* Ref our handle */
-  base_conn = TP_BASE_CONNECTION (self->priv->connection);
-
-  contact_repo = tp_base_connection_get_handles (base_conn,
-      TP_HANDLE_TYPE_CONTACT);
-
-  tp_handle_ref (contact_repo, self->priv->handle);
-
-  /* Connect to the bus */
-  bus = tp_get_bus ();
-  dbus_g_connection_register_g_object (bus, self->priv->object_path, obj);
-
-  /* Initialise the available socket types hash table */
-  self->priv->available_socket_types = g_hash_table_new (g_int_hash,
-      g_int_equal);
-
-  self->priv->last_transferred_bytes_emitted = 0;
-
-  return obj;
-}
-
-static void
-salut_file_channel_dispose (GObject *object);
-static void
-salut_file_channel_finalize (GObject *object);
-
-static void
-salut_file_channel_class_init (SalutFileChannelClass *salut_file_channel_class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (salut_file_channel_class);
-  GParamSpec *param_spec;
-
-  static TpDBusPropertiesMixinPropImpl channel_props[] = {
-    { "TargetHandleType", "handle-type", NULL },
-    { "TargetHandle", "handle", NULL },
-    { "ChannelType", "channel-type", NULL },
-    { "Interfaces", "interfaces", NULL },
-    { NULL }
-  };
-
-  static TpDBusPropertiesMixinPropImpl file_props[] = {
-    { "State", "state", NULL },
-    { "ContentType", "content-type", "content-type" },
-    { "Filename", "filename", "filename" },
-    { "Size", "size", "size" },
-    { "ContentHashType", "content-hash-type", "content-hash-type" },
-    { "ContentHash", "content-hash", "content-hash" },
-    { "Description", "description", "description" },
-    { "AvailableSocketTypes", "available-socket-types", NULL },
-    { "TransferredBytes", "transferred-bytes", NULL },
-    { "InitialOffset", "initial-offset", NULL },
-    { NULL }
-  };
-
-  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
-    { TP_IFACE_CHANNEL,
-      tp_dbus_properties_mixin_getter_gobject_properties,
-      NULL,
-      channel_props
-    },
-    { SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
-      tp_dbus_properties_mixin_getter_gobject_properties,
-      tp_dbus_properties_mixin_setter_gobject_properties,
-      file_props
-    },
-    { NULL }
-  };
-
-  g_type_class_add_private (salut_file_channel_class,
-      sizeof (SalutFileChannelPrivate));
-
-  object_class->dispose = salut_file_channel_dispose;
-  object_class->finalize = salut_file_channel_finalize;
-
-  object_class->constructor = salut_file_channel_constructor;
-  object_class->get_property = salut_file_channel_get_property;
-  object_class->set_property = salut_file_channel_set_property;
-
-  g_object_class_override_property (object_class, PROP_OBJECT_PATH,
-      "object-path");
-  g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
-      "channel-type");
-  g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
-      "handle-type");
-  g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
-  param_spec = g_param_spec_object ("contact",
-      "SalutContact object",
-      "Salut Contact to which this channel is dedicated",
-      SALUT_TYPE_CONTACT,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
-
-  param_spec = g_param_spec_object ("connection",
-      "SalutConnection object",
-      "Salut Connection that owns the"
-      "connection for this IM channel",
-      SALUT_TYPE_CONNECTION,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
-  param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
-      "Additional Channel.Interface.* interfaces",
-      G_TYPE_STRV,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB |
-      G_PARAM_STATIC_NAME);
-  g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
-  param_spec = g_param_spec_object (
-      "xmpp-connection-manager",
-      "SalutXmppConnectionManager object",
-      "Salut XMPP Connection manager used for this file channel",
-      SALUT_TYPE_XMPP_CONNECTION_MANAGER,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_XMPP_CONNECTION_MANAGER,
-      param_spec);
-
-  param_spec = g_param_spec_boolean (
-      "incoming",
-      "incoming",
-      "Whether the transfer is incoming",
-      FALSE,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_INCOMING, param_spec);
-
-  param_spec = g_param_spec_uint (
-      "state",
-      "SalutFileTransferState state",
-      "State of the file transfer in this channel",
-      0,
-      G_MAXUINT,
-      0,
-      G_PARAM_CONSTRUCT_ONLY |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_STATE, param_spec);
-
-  param_spec = g_param_spec_string (
-      "content-type",
-      "gchar *content-type",
-      "ContentType of the file",
-      "",
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONTENT_TYPE,
-      param_spec);
-
-  param_spec = g_param_spec_string (
-      "filename",
-      "gchar *filename",
-      "Name of the file",
-      "",
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_FILENAME, param_spec);
-
-  param_spec = g_param_spec_uint64 (
-      "size",
-      "guint size",
-      "Size of the file in bytes",
-      0,
-      G_MAXUINT64,
-      SALUT_UNDEFINED_FILE_SIZE,
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_SIZE, param_spec);
-
-  param_spec = g_param_spec_uint (
-      "content-hash-type",
-      "SalutFileHashType content-hash-type",
-      "Hash type",
-      0,
-      G_MAXUINT,
-      SALUT_FILE_HASH_TYPE_NONE,
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONTENT_HASH_TYPE,
-      param_spec);
-
-  param_spec = g_param_spec_string (
-      "content-hash",
-      "gchar *content-hash",
-      "Hash of the file contents",
-      "",
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_CONTENT_HASH,
-      param_spec);
-
-  param_spec = g_param_spec_string (
-      "description",
-      "gchar *description",
-      "Description of the file",
-      "",
-      /* TODO: change this to CONSTRUCT_ONLY when
-       * the new request API is used.
-       */
-      G_PARAM_CONSTRUCT |
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_DESCRIPTION, param_spec);
-
-  param_spec = g_param_spec_boxed (
-      "available-socket-types",
-      "SalutSupportedSocketMap available-socket-types",
-      "Available socket types",
-      dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, DBUS_TYPE_G_UINT_ARRAY),
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_AVAILABLE_SOCKET_TYPES,
-      param_spec);
-
-  param_spec = g_param_spec_uint64 (
-      "transferred-bytes",
-      "guint64 transferred-bytes",
-      "Bytes transferred",
-      0,
-      G_MAXUINT64,
-      0,
-      G_PARAM_READABLE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_TRANSFERRED_BYTES,
-      param_spec);
-
-  param_spec = g_param_spec_uint64 (
-      "initial-offset",
-      "guint64 initial_offset",
-      "Offset set at the beginning of the transfer",
-      0,
-      G_MAXUINT64,
-      0,
-      G_PARAM_READWRITE |
-      G_PARAM_STATIC_NICK |
-      G_PARAM_STATIC_BLURB);
-  g_object_class_install_property (object_class, PROP_INITIAL_OFFSET,
-      param_spec);
-
-  salut_file_channel_class->dbus_props_class.interfaces = prop_interfaces;
-  tp_dbus_properties_mixin_class_init (object_class,
-      G_STRUCT_OFFSET (SalutFileChannelClass, dbus_props_class));
-}
-
-void
-salut_file_channel_dispose (GObject *object)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
-  TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->connection);
-  TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (base_conn,
-      TP_HANDLE_TYPE_CONTACT);
-
-  if (self->priv->dispose_has_run)
-    return;
-
-  self->priv->dispose_has_run = TRUE;
-
-  tp_handle_unref (handle_repo, self->priv->handle);
-
-  salut_file_channel_do_close (self);
-
-  if (self->priv->contact)
-    {
-      g_object_unref (self->priv->contact);
-      self->priv->contact = NULL;
-    }
-
-  if (self->priv->xmpp_connection_manager != NULL)
-    {
-      g_object_unref (self->priv->xmpp_connection_manager);
-      self->priv->xmpp_connection_manager = NULL;
-    }
-
-  if (self->priv->xmpp_connection != NULL)
-    {
-      g_object_unref (self->priv->xmpp_connection);
-      self->priv->xmpp_connection = NULL;
-    }
-
-  /* release any references held by the object here */
-
-  if (G_OBJECT_CLASS (salut_file_channel_parent_class)->dispose)
-    G_OBJECT_CLASS (salut_file_channel_parent_class)->dispose (object);
-}
-
-static void
-salut_file_channel_finalize (GObject *object)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
-
-  /* free any data held directly by the object here */
-  g_free (self->priv->object_path);
-  g_free (self->priv->filename);
-
-  G_OBJECT_CLASS (salut_file_channel_parent_class)->finalize (object);
-}
-
-
-/**
- * salut_file_channel_close
- *
- * Implements DBus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_file_channel_close (TpSvcChannel *iface,
-                          DBusGMethodInvocation *context)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
-
-  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_COMPLETED)
-    {
-      gibber_file_transfer_cancel (self->priv->ft, 406);
-      salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (iface),
-          SALUT_FILE_TRANSFER_STATE_CANCELLED,
-          SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED);
-    }
-
-  salut_file_channel_do_close (SALUT_FILE_CHANNEL (iface));
-  tp_svc_channel_return_from_close (context);
-}
-
-/**
- * salut_file_channel_get_channel_type
- *
- * Implements DBus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_file_channel_get_channel_type (TpSvcChannel *iface,
-                                     DBusGMethodInvocation *context)
-{
-  tp_svc_channel_return_from_get_channel_type (context,
-      SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER);
-}
-
-/**
- * salut_file_channel_get_handle
- *
- * Implements DBus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_file_channel_get_handle (TpSvcChannel *iface,
-                               DBusGMethodInvocation *context)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
-
-  tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
-                                         self->priv->handle);
-}
-
-/**
- * salut_file_channel_get_interfaces
- *
- * Implements DBus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_file_channel_get_interfaces (TpSvcChannel *iface,
-                                   DBusGMethodInvocation *context)
-{
-  tp_svc_channel_return_from_get_interfaces (context,
-      salut_file_channel_interfaces);
-}
-
-static void
-channel_iface_init (gpointer g_iface, gpointer iface_data)
-{
-  TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
-    klass, salut_file_channel_##x)
-  IMPLEMENT (close);
-  IMPLEMENT (get_channel_type);
-  IMPLEMENT (get_handle);
-  IMPLEMENT (get_interfaces);
-#undef IMPLEMENT
-}
-
-static void
-error_cb (GibberFileTransfer *ft,
-          guint domain,
-          gint code,
-          const gchar *message,
-          SalutFileChannel *self)
-{
-}
-
-static void
-ft_finished_cb (GibberFileTransfer *ft,
-                SalutFileChannel *self)
-{
-  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
-      SALUT_FILE_TRANSFER_STATE_COMPLETED,
-      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-
-  salut_xmpp_connection_manager_release_connection (
-      self->priv->xmpp_connection_manager,
-      self->priv->xmpp_connection);
-}
-
-static void
-ft_remote_canceled_cb (GibberFileTransfer *ft,
-                       SalutFileChannel *self)
-{
-  gibber_file_transfer_cancel (ft, 406);
-  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
-      SALUT_FILE_TRANSFER_STATE_CANCELLED,
-      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED);
-
-  salut_xmpp_connection_manager_release_connection (
-      self->priv->xmpp_connection_manager,
-      self->priv->xmpp_connection);
-}
-
-static void
-remote_accepted_cb (GibberFileTransfer *ft,
-                    SalutFileChannel *self)
-{
-  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
-      SALUT_FILE_TRANSFER_STATE_OPEN,
-      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-
-  g_signal_connect (ft, "finished", G_CALLBACK (ft_finished_cb), self);
-  g_signal_connect (ft, "canceled", G_CALLBACK (ft_remote_canceled_cb), self);
-}
-
-static gboolean setup_local_socket (SalutFileChannel *self);
-static void ft_transferred_chunk_cb (GibberFileTransfer *ft, guint64 count,
-    SalutFileChannel *self);
-
-static void
-send_file_offer (SalutFileChannel *self)
-{
-  GibberFileTransfer *ft;
-
-  ft = g_object_new (GIBBER_TYPE_OOB_FILE_TRANSFER,
-      "self-id", self->priv->connection->name,
-      "peer-id", self->priv->contact->name,
-      "filename", self->priv->filename,
-      "connection", self->priv->xmpp_connection,
-      NULL);
-  g_signal_connect (ft, "remote-accepted",
-      G_CALLBACK (remote_accepted_cb), self);
-  g_signal_connect (ft, "error", G_CALLBACK (error_cb), self);
-
-  self->priv->ft = ft;
-
-  g_signal_connect (ft, "transferred-chunk",
-      G_CALLBACK (ft_transferred_chunk_cb), self);
-
-  gibber_file_transfer_set_size (ft, self->priv->size);
-
-  gibber_file_transfer_offer (ft);
-}
-
-static void
-xmpp_connection_manager_new_connection_cb (SalutXmppConnectionManager *mgr,
-                                           GibberXmppConnection *connection,
-                                           SalutContact *contact,
-                                           gpointer user_data)
-{
-  SalutFileChannel *channel = user_data;
-
-  channel->priv->xmpp_connection = g_object_ref (connection);
-  salut_xmpp_connection_manager_take_connection (mgr, connection);
-  g_signal_handlers_disconnect_by_func (mgr,
-      xmpp_connection_manager_new_connection_cb, user_data);
-  send_file_offer (channel);
-}
-
-void
-salut_file_channel_received_file_offer (SalutFileChannel *self,
-                                        GibberXmppStanza *stanza,
-                                        GibberXmppConnection *conn)
-{
-  GibberFileTransfer *ft;
-
-  salut_xmpp_connection_manager_take_connection (
-      self->priv->xmpp_connection_manager , conn);
-  ft = gibber_file_transfer_new_from_stanza (stanza, conn);
-
-  g_return_if_fail (ft);
-
-  g_signal_connect (ft, "error", G_CALLBACK (error_cb), self);
-
-  DEBUG ("Received file offer with id '%s'", ft->id);
-
-  self->priv->ft = ft;
-
-  self->priv->filename = g_strdup (ft->filename);
-  self->priv->size = gibber_file_transfer_get_size (ft);
-}
-
-static void
-salut_file_channel_set_state (SalutSvcChannelTypeFileTransfer *iface,
-                              SalutFileTransferState state,
-                              SalutFileTransferStateChangeReason reason)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
-
-  self->priv->state = state;
-  salut_svc_channel_type_file_transfer_emit_file_transfer_state_changed (iface,
-      state, reason);
-}
-
-static void
-ft_transferred_chunk_cb (GibberFileTransfer *ft,
-                         guint64 count,
-                         SalutFileChannel *self)
-{
-  SalutSvcChannelTypeFileTransfer *iface = SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self);
-  GTimeVal timeval;
-
-  self->priv->transferred_bytes += count;
-
-  g_get_current_time (&timeval);
-
-  /* Only emit the TransferredBytes signal if it has been one second since its
-   * last emission, OR if the transfer has finished.
-   */
-  if (timeval.tv_sec >= (self->priv->last_transferred_bytes_emitted + 1)
-      || self->priv->transferred_bytes == self->priv->size)
-    {
-      salut_svc_channel_type_file_transfer_emit_transferred_bytes_changed (
-          iface, self->priv->transferred_bytes);
-      self->priv->last_transferred_bytes_emitted = timeval.tv_sec;
-    }
-}
-
-/**
- * salut_file_channel_accept_file
- *
- * Implements D-Bus method AcceptFile
- * on interface org.freedesktop.Telepathy.Channel.Type.File
- */
-static void
-salut_file_channel_accept_file (SalutSvcChannelTypeFileTransfer *iface,
-                                guint address_type,
-                                guint access_control,
-                                const GValue *access_control_param,
-                                guint64 offset,
-                                DBusGMethodInvocation *context)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
-  GError *error = NULL;
-  GValue out_address = { 0 };
-  GibberFileTransfer *ft;
-
-  ft = self->priv->ft;
-  if (ft == NULL)
-    {
-      dbus_g_method_return_error (context, error);
-      g_error_free (error);
-    }
-
-  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_LOCAL_PENDING)
-    {
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-        "State is not local pending; cannot accept file");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX)
-    {
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
-        "Address type %u not implemented", address_type);
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  g_signal_connect (ft, "finished", G_CALLBACK (ft_finished_cb), self);
-  g_signal_connect (ft, "transferred-chunk",
-      G_CALLBACK (ft_transferred_chunk_cb), self);
-  g_signal_connect (ft, "canceled", G_CALLBACK (ft_remote_canceled_cb), self);
-
-  if (!setup_local_socket(self))
-    {
-      DEBUG ("Could not set up local socket");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-          "Could not set up local socket");
-      dbus_g_method_return_error (context, error);
-    }
-
-  DEBUG ("local socket %s", self->priv->socket_path);
-
-  salut_file_channel_set_state (iface, SALUT_FILE_TRANSFER_STATE_ACCEPTED,
-        SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-
-  g_value_init (&out_address, G_TYPE_STRING);
-  g_value_set_string (&out_address, self->priv->socket_path);
-
-  salut_svc_channel_type_file_transfer_return_from_accept_file (context,
-      &out_address);
-
-  self->priv->initial_offset = 0;
-  salut_file_channel_set_state (iface, SALUT_FILE_TRANSFER_STATE_OPEN,
-      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-}
-
-/**
- * salut_file_channel_offer_file
- *
- * Implements D-Bus method OfferFile
- * on interface org.freedesktop.Telepathy.Channel.Type.File
- */
-static void
-salut_file_channel_offer_file (SalutSvcChannelTypeFileTransfer *iface,
-                               guint address_type,
-                               guint access_control,
-                               const GValue *access_control_param,
-                               DBusGMethodInvocation *context)
-{
-  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
-  GibberXmppConnection *connection = NULL;
-  SalutXmppConnectionManagerRequestConnectionResult request_result;
-  GError *error = NULL;
-  SalutFileChannel *channel = SALUT_FILE_CHANNEL (iface);
-  GValue out_address = { 0 };
-
-  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_NOT_OFFERED)
-    {
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-          "State is not not offered; cannot offer file");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX)
-    {
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
-        "Address type %u not implemented", address_type);
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (CHECK_STR_EMPTY (channel->priv->content_type))
-    {
-      DEBUG ("ContentType property not set");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-        "ContentType property not set");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (CHECK_STR_EMPTY (channel->priv->filename))
-    {
-      DEBUG ("Filename property not set");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-        "Filename property not set");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (channel->priv->size == SALUT_UNDEFINED_FILE_SIZE)
-    {
-      DEBUG ("Size property not set");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-        "Size property not set");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  DEBUG ("Offering file transfer");
-
-  request_result = salut_xmpp_connection_manager_request_connection (
-      channel->priv->xmpp_connection_manager, channel->priv->contact,
-      &connection, &error);
-
-  if (request_result ==
-      SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_DONE)
-    {
-      channel->priv->xmpp_connection = connection;
-      send_file_offer (channel);
-    }
-  else if (request_result ==
-      SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_PENDING)
-    {
-      g_signal_connect (channel->priv->xmpp_connection_manager,
-          "new-connection",
-          G_CALLBACK (xmpp_connection_manager_new_connection_cb), channel);
-    }
-  else
-    {
-      DEBUG ("Request connection failed");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
-        "Request connection failed");
-      dbus_g_method_return_error (context, error);
-      return;
-    }
-
-  if (!setup_local_socket(self))
-    {
-      DEBUG ("Could not set up local socket");
-      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
-          "Could not set up local socket");
-      dbus_g_method_return_error (context, error);
-    }
-
-  g_value_init (&out_address, G_TYPE_STRING);
-  g_value_set_string (&out_address, channel->priv->socket_path);
-
-  salut_file_channel_set_state (iface,
-      SALUT_FILE_TRANSFER_STATE_REMOTE_PENDING,
-      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
-
-  salut_svc_channel_type_file_transfer_return_from_offer_file (context,
-      &out_address);
-}
-
-static void
-file_transfer_iface_init (gpointer g_iface,
-                          gpointer iface_data)
-{
-  SalutSvcChannelTypeFileTransferClass *klass =
-      (SalutSvcChannelTypeFileTransferClass *)g_iface;
-
-#define IMPLEMENT(x) salut_svc_channel_type_file_transfer_implement_##x (\
-    klass, salut_file_channel_##x)
-  IMPLEMENT (accept_file);
-  IMPLEMENT (offer_file);
-#undef IMPLEMENT
-}
-
-static const gchar *
-get_local_unix_socket_path (SalutFileChannel *self)
-{
-  gchar *path = NULL;
-  gint32 random;
-  gchar *random_str;
-  struct stat buf;
-
-  while (TRUE)
-    {
-      random = g_random_int_range (0, G_MAXINT32);
-      random_str = g_strdup_printf ("tp-ft-%i", random);
-      path = g_build_filename (g_get_tmp_dir (), random_str, NULL);
-      g_free (random_str);
-
-      if (g_stat (path, &buf) != 0)
-        break;
-
-      g_free (path);
-    }
-
-  if (self->priv->socket_path)
-    g_free (self->priv->socket_path);
-
-  self->priv->socket_path = path;
-
-  return path;
-}
-
-/*
- * Return a GIOChannel for the local unix socket path.
- */
-static GIOChannel *
-get_socket_channel (SalutFileChannel *self)
-{
-  gint fd;
-  const gchar *path;
-  size_t path_len;
-  struct sockaddr_un addr;
-  GIOChannel *io_channel;
-
-  path = get_local_unix_socket_path (self);
-
-  fd = socket (PF_UNIX, SOCK_STREAM, 0);
-  if (fd < 0)
-    {
-      DEBUG("socket() failed");
-      return NULL;
-    }
-
-  memset (&addr, 0, sizeof (addr));
-  addr.sun_family = AF_UNIX;
-  path_len = strlen (path);
-  strncpy (addr.sun_path, path, path_len);
-  g_unlink (path);
-
-  if (bind (fd, (struct sockaddr*) &addr,
-        G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
-    {
-      DEBUG ("bind failed");
-      close (fd);
-      return NULL;
-    }
-
-  if (listen (fd, 1) < 0)
-    {
-      DEBUG ("listen failed");
-      close (fd);
-      return NULL;
-    }
-
-  io_channel = g_io_channel_unix_new (fd);
-  g_io_channel_set_close_on_unref (io_channel, TRUE);
-  return io_channel;
-}
-
-/*
- * Some client is connecting to the Unix socket.
- */
-static gboolean
-accept_local_socket_connection (GIOChannel *source,
-                                GIOCondition condition,
-                                gpointer user_data)
-{
-  GibberFileTransfer *ft;
-  int new_fd;
-  struct sockaddr_un addr;
-  socklen_t addrlen;
-  GIOChannel *channel;
-
-  ft = SALUT_FILE_CHANNEL (user_data)->priv->ft;
-
-  g_assert (ft != NULL);
-
-  if (condition & G_IO_IN)
-    {
-      DEBUG ("Client connected to local socket");
-
-      addrlen = sizeof (addr);
-      new_fd = accept (g_io_channel_unix_get_fd (source),
-          (struct sockaddr *) &addr, &addrlen);
-      if (new_fd < 0)
-        {
-          DEBUG ("accept() failed");
-          return FALSE;
-        }
-
-      channel = g_io_channel_unix_new (new_fd);
-      g_io_channel_set_close_on_unref (channel, TRUE);
-      g_io_channel_set_encoding (channel, NULL, NULL);
-      if (ft->direction == GIBBER_FILE_TRANSFER_DIRECTION_INCOMING)
-        gibber_file_transfer_receive (ft, channel);
-      else
-        gibber_file_transfer_send (ft, channel);
-      g_io_channel_unref (channel);
-    }
-
-  return FALSE;
-}
-
-static gboolean
-setup_local_socket (SalutFileChannel *self)
-{
-  GIOChannel *io_channel;
-
-  io_channel = get_socket_channel (self);
-  if (io_channel == NULL)
-    {
-      return FALSE;
-    }
-
-  g_io_add_watch (io_channel, G_IO_IN | G_IO_HUP,
-      accept_local_socket_connection, self);
-  g_io_channel_unref (io_channel);
-
-  return TRUE;
-}
-
diff --git a/src/salut-file-channel.h b/src/salut-file-channel.h
deleted file mode 100644
index 2c7fa29..0000000
--- a/src/salut-file-channel.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * salut-file-channel.h - Header for SalutFileChannel
- * Copyright (C) 2007 Marco Barisione <marco at barisione.org>
- * Copyright (C) 2005, 2007, 2008 Collabora Ltd.
- *   @author: Sjoerd Simons <sjoerd at luon.net>
- *   @author: Jonny Lamb <jonny.lamb at collabora.co.uk>
- *
- * 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_FILE_CHANNEL_H__
-#define __SALUT_FILE_CHANNEL_H__
-
-#include <glib-object.h>
-#include <gibber/gibber-file-transfer.h>
-
-#include <extensions/_gen/svc.h>
-#include <extensions/_gen/interfaces.h>
-#include <extensions/_gen/enums.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SalutFileChannel SalutFileChannel;
-typedef struct _SalutFileChannelClass SalutFileChannelClass;
-typedef struct _SalutFileChannelPrivate SalutFileChannelPrivate;
-
-struct _SalutFileChannelClass {
-    GObjectClass parent_class;
-    TpDBusPropertiesMixinClass dbus_props_class;
-};
-
-struct _SalutFileChannel {
-    GObject parent;
-
-    SalutFileChannelPrivate *priv;
-};
-
-GType salut_file_channel_get_type (void);
-
-/* TYPE MACROS */
-#define SALUT_TYPE_FILE_CHANNEL \
-  (salut_file_channel_get_type ())
-#define SALUT_FILE_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_FILE_CHANNEL, SalutFileChannel))
-#define SALUT_FILE_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_FILE_CHANNEL, \
-                           SalutFileChannelClass))
-#define SALUT_IS_FILE_CHANNEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_FILE_CHANNEL))
-#define SALUT_IS_FILE_CHANNEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_FILE_CHANNEL))
-#define SALUT_FILE_CHANNEL_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_FILE_CHANNEL, \
-                              SalutFileChannelClass))
-
-void
-salut_file_channel_received_file_offer (SalutFileChannel *self,
-    GibberXmppStanza *stanza, GibberXmppConnection *conn);
-
-G_END_DECLS
-
-#endif /* #ifndef __SALUT_FILE_CHANNEL_H__*/
diff --git a/src/salut-file-transfer-channel.c b/src/salut-file-transfer-channel.c
new file mode 100644
index 0000000..04dee10
--- /dev/null
+++ b/src/salut-file-transfer-channel.c
@@ -0,0 +1,1225 @@
+/*
+ * salut-file-transfer-channel.c - Source for SalutFileChannel
+ * Copyright (C) 2007 Marco Barisione <marco at barisione.org>
+ * Copyright (C) 2005, 2007, 2008 Collabora Ltd.
+ *   @author: Sjoerd Simons <sjoerd at luon.net>
+ *   @author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+ *
+ * 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 <glib/gstdio.h>
+#include <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define DEBUG_FLAG DEBUG_FT
+#include "debug.h"
+
+#include "salut-file-transfer-channel.h"
+#include "signals-marshal.h"
+
+#include "salut-connection.h"
+#include "salut-im-manager.h"
+#include "salut-contact.h"
+
+#include <gibber/gibber-xmpp-stanza.h>
+#include <gibber/gibber-file-transfer.h>
+#include <gibber/gibber-oob-file-transfer.h>
+
+#include <telepathy-glib/channel-iface.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/svc-generic.h>
+
+static void
+channel_iface_init (gpointer g_iface, gpointer iface_data);
+static void
+file_transfer_iface_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (SalutFileChannel, salut_file_channel, G_TYPE_OBJECT,
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
+                           tp_dbus_properties_mixin_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
+    G_IMPLEMENT_INTERFACE (SALUT_TYPE_SVC_CHANNEL_TYPE_FILE_TRANSFER,
+                           file_transfer_iface_init);
+);
+
+#define CHECK_STR_EMPTY(x) ((x) == NULL || (x)[0] == '\0')
+
+#define SALUT_UNDEFINED_FILE_SIZE G_MAXUINT64
+
+static const char *salut_file_channel_interfaces[] = { NULL };
+
+/* properties */
+enum
+{
+  PROP_OBJECT_PATH = 1,
+  PROP_CHANNEL_TYPE,
+  PROP_HANDLE_TYPE,
+  PROP_HANDLE,
+  PROP_CONTACT,
+  PROP_CONNECTION,
+  PROP_INTERFACES,
+  PROP_XMPP_CONNECTION_MANAGER,
+  PROP_INCOMING,
+  PROP_STATE,
+  PROP_CONTENT_TYPE,
+  PROP_FILENAME,
+  PROP_SIZE,
+  PROP_CONTENT_HASH_TYPE,
+  PROP_CONTENT_HASH,
+  PROP_DESCRIPTION,
+  PROP_AVAILABLE_SOCKET_TYPES,
+  PROP_TRANSFERRED_BYTES,
+  PROP_INITIAL_OFFSET,
+  LAST_PROPERTY
+};
+
+/* private structure */
+struct _SalutFileChannelPrivate {
+  gboolean dispose_has_run;
+  gboolean closed;
+  gchar *object_path;
+  TpHandle handle;
+  SalutContact *contact;
+  SalutConnection *connection;
+  SalutXmppConnectionManager *xmpp_connection_manager;
+  GibberXmppConnection *xmpp_connection;
+  GibberFileTransfer *ft;
+  glong last_transferred_bytes_emitted;
+  gchar *socket_path;
+  gboolean incoming;
+
+  /* properties */
+  SalutFileTransferState state;
+  gchar *content_type;
+  gchar *filename;
+  guint64 size;
+  SalutFileHashType content_hash_type;
+  gchar *content_hash;
+  gchar *description;
+  GHashTable *available_socket_types;
+  guint64 transferred_bytes;
+  guint64 initial_offset;
+};
+
+static void
+salut_file_channel_do_close (SalutFileChannel *self)
+{
+  if (self->priv->closed)
+    return;
+
+  DEBUG ("Emitting closed signal for %s", self->priv->object_path);
+  tp_svc_channel_emit_closed (self);
+  self->priv->closed = TRUE;
+}
+
+static void
+salut_file_channel_init (SalutFileChannel *obj)
+{
+  obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, SALUT_TYPE_FILE_CHANNEL,
+      SalutFileChannelPrivate);
+
+  /* allocate any data required by the object here */
+  obj->priv->object_path = NULL;
+  obj->priv->connection = NULL;
+  obj->priv->xmpp_connection_manager = NULL;
+  obj->priv->contact = NULL;
+}
+
+static void salut_file_channel_set_state (SalutSvcChannelTypeFileTransfer *iface,
+    SalutFileTransferState state, SalutFileTransferStateChangeReason reason);
+
+static void
+salut_file_channel_get_property (GObject    *object,
+                                 guint       property_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
+
+  switch (property_id)
+    {
+      case PROP_OBJECT_PATH:
+        g_value_set_string (value, self->priv->object_path);
+        break;
+      case PROP_CHANNEL_TYPE:
+        g_value_set_static_string (value,
+            SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER);
+        break;
+      case PROP_HANDLE_TYPE:
+        g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+        break;
+      case PROP_HANDLE:
+        g_value_set_uint (value, self->priv->handle);
+        break;
+      case PROP_CONTACT:
+        g_value_set_object (value, self->priv->contact);
+        break;
+      case PROP_CONNECTION:
+        g_value_set_object (value, self->priv->connection);
+        break;
+      case PROP_INTERFACES:
+        g_value_set_boxed (value, salut_file_channel_interfaces);
+        break;
+      case PROP_XMPP_CONNECTION_MANAGER:
+        g_value_set_object (value, self->priv->xmpp_connection_manager);
+        break;
+      case PROP_INCOMING:
+        g_value_set_boolean (value, self->priv->incoming);
+        break;
+      case PROP_STATE:
+        g_value_set_uint (value, self->priv->state);
+        break;
+      case PROP_CONTENT_TYPE:
+        g_value_set_string (value, self->priv->content_type);
+        break;
+      case PROP_FILENAME:
+        g_value_set_string (value, self->priv->filename);
+        break;
+      case PROP_SIZE:
+        g_value_set_uint64 (value, self->priv->size);
+        break;
+      case PROP_CONTENT_HASH_TYPE:
+        g_value_set_uint (value, self->priv->content_hash_type);
+        break;
+      case PROP_CONTENT_HASH:
+        g_value_set_string (value, self->priv->content_hash);
+        break;
+      case PROP_DESCRIPTION:
+        g_value_set_string (value, self->priv->description);
+        break;
+      case PROP_AVAILABLE_SOCKET_TYPES:
+        g_value_set_boxed (value, self->priv->available_socket_types);
+        break;
+      case PROP_TRANSFERRED_BYTES:
+        g_value_set_uint64 (value, self->priv->transferred_bytes);
+        break;
+      case PROP_INITIAL_OFFSET:
+        g_value_set_uint64 (value, self->priv->initial_offset);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+salut_file_channel_set_property (GObject *object,
+                                 guint property_id,
+                                 const GValue *value,
+                                 GParamSpec *pspec)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
+  const gchar *tmp;
+
+  switch (property_id)
+    {
+      case PROP_OBJECT_PATH:
+        g_free (self->priv->object_path);
+        self->priv->object_path = g_value_dup_string (value);
+        break;
+      case PROP_HANDLE:
+        self->priv->handle = g_value_get_uint (value);
+        break;
+      case PROP_CONTACT:
+        self->priv->contact = g_value_dup_object (value);
+        break;
+      case PROP_CONNECTION:
+        self->priv->connection = g_value_get_object (value);
+        break;
+      case PROP_HANDLE_TYPE:
+        g_assert (g_value_get_uint (value) == 0
+                  || g_value_get_uint (value) == TP_HANDLE_TYPE_CONTACT);
+        break;
+      case PROP_CHANNEL_TYPE:
+        tmp = g_value_get_string (value);
+        g_assert (tmp == NULL
+                  || !tp_strdiff (g_value_get_string (value),
+                         SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER));
+        break;
+      case PROP_XMPP_CONNECTION_MANAGER:
+        self->priv->xmpp_connection_manager = g_value_dup_object (value);
+        break;
+      case PROP_STATE:
+        salut_file_channel_set_state (
+            SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (object),
+            g_value_get_uint (value),
+            SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+        break;
+      case PROP_INCOMING:
+        self->priv->incoming = g_value_get_boolean (value);
+        break;
+      case PROP_CONTENT_TYPE:
+        /* This should not be writeable with the new request API */
+        self->priv->content_type = g_value_dup_string (value);
+        break;
+      case PROP_FILENAME:
+        /* This should not be writeable with the new request API */
+        self->priv->filename = g_value_dup_string (value);
+        break;
+      case PROP_SIZE:
+        /* This should not be writeable with the new request API */
+        self->priv->size = g_value_get_uint64 (value);
+        break;
+      case PROP_CONTENT_HASH_TYPE:
+        /* This should not be writeable with the new request API */
+        self->priv->content_hash_type = g_value_get_uint (value);
+        break;
+      case PROP_CONTENT_HASH:
+        /* This should not be writeable with the new request API */
+        self->priv->content_hash = g_value_dup_string (value);
+        break;
+      case PROP_DESCRIPTION:
+        /* This should not be writeable with the new request API */
+        self->priv->description = g_value_dup_string (value);
+        break;
+      case PROP_AVAILABLE_SOCKET_TYPES:
+        self->priv->available_socket_types = g_value_get_boxed (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static GObject *
+salut_file_channel_constructor (GType type, guint n_props,
+                                GObjectConstructParam *props)
+{
+  GObject *obj;
+  SalutFileChannel *self;
+  DBusGConnection *bus;
+  TpBaseConnection *base_conn;
+  TpHandleRepoIface *contact_repo;
+
+  /* Parent constructor chain */
+  obj = G_OBJECT_CLASS (salut_file_channel_parent_class)->
+          constructor (type, n_props, props);
+
+  self = SALUT_FILE_CHANNEL (obj);
+
+  /* Ref our handle */
+  base_conn = TP_BASE_CONNECTION (self->priv->connection);
+
+  contact_repo = tp_base_connection_get_handles (base_conn,
+      TP_HANDLE_TYPE_CONTACT);
+
+  tp_handle_ref (contact_repo, self->priv->handle);
+
+  /* Connect to the bus */
+  bus = tp_get_bus ();
+  dbus_g_connection_register_g_object (bus, self->priv->object_path, obj);
+
+  /* Initialise the available socket types hash table */
+  self->priv->available_socket_types = g_hash_table_new (g_int_hash,
+      g_int_equal);
+
+  self->priv->last_transferred_bytes_emitted = 0;
+
+  return obj;
+}
+
+static void
+salut_file_channel_dispose (GObject *object);
+static void
+salut_file_channel_finalize (GObject *object);
+
+static void
+salut_file_channel_class_init (SalutFileChannelClass *salut_file_channel_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (salut_file_channel_class);
+  GParamSpec *param_spec;
+
+  static TpDBusPropertiesMixinPropImpl channel_props[] = {
+    { "TargetHandleType", "handle-type", NULL },
+    { "TargetHandle", "handle", NULL },
+    { "ChannelType", "channel-type", NULL },
+    { "Interfaces", "interfaces", NULL },
+    { NULL }
+  };
+
+  static TpDBusPropertiesMixinPropImpl file_props[] = {
+    { "State", "state", NULL },
+    { "ContentType", "content-type", "content-type" },
+    { "Filename", "filename", "filename" },
+    { "Size", "size", "size" },
+    { "ContentHashType", "content-hash-type", "content-hash-type" },
+    { "ContentHash", "content-hash", "content-hash" },
+    { "Description", "description", "description" },
+    { "AvailableSocketTypes", "available-socket-types", NULL },
+    { "TransferredBytes", "transferred-bytes", NULL },
+    { "InitialOffset", "initial-offset", NULL },
+    { NULL }
+  };
+
+  static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
+    { TP_IFACE_CHANNEL,
+      tp_dbus_properties_mixin_getter_gobject_properties,
+      NULL,
+      channel_props
+    },
+    { SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+      tp_dbus_properties_mixin_getter_gobject_properties,
+      tp_dbus_properties_mixin_setter_gobject_properties,
+      file_props
+    },
+    { NULL }
+  };
+
+  g_type_class_add_private (salut_file_channel_class,
+      sizeof (SalutFileChannelPrivate));
+
+  object_class->dispose = salut_file_channel_dispose;
+  object_class->finalize = salut_file_channel_finalize;
+
+  object_class->constructor = salut_file_channel_constructor;
+  object_class->get_property = salut_file_channel_get_property;
+  object_class->set_property = salut_file_channel_set_property;
+
+  g_object_class_override_property (object_class, PROP_OBJECT_PATH,
+      "object-path");
+  g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
+      "channel-type");
+  g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
+      "handle-type");
+  g_object_class_override_property (object_class, PROP_HANDLE, "handle");
+
+  param_spec = g_param_spec_object ("contact",
+      "SalutContact object",
+      "Salut Contact to which this channel is dedicated",
+      SALUT_TYPE_CONTACT,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
+
+  param_spec = g_param_spec_object ("connection",
+      "SalutConnection object",
+      "Salut Connection that owns the"
+      "connection for this IM channel",
+      SALUT_TYPE_CONNECTION,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+
+  param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
+      "Additional Channel.Interface.* interfaces",
+      G_TYPE_STRV,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB |
+      G_PARAM_STATIC_NAME);
+  g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
+
+  param_spec = g_param_spec_object (
+      "xmpp-connection-manager",
+      "SalutXmppConnectionManager object",
+      "Salut XMPP Connection manager used for this file channel",
+      SALUT_TYPE_XMPP_CONNECTION_MANAGER,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_XMPP_CONNECTION_MANAGER,
+      param_spec);
+
+  param_spec = g_param_spec_boolean (
+      "incoming",
+      "incoming",
+      "Whether the transfer is incoming",
+      FALSE,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_INCOMING, param_spec);
+
+  param_spec = g_param_spec_uint (
+      "state",
+      "SalutFileTransferState state",
+      "State of the file transfer in this channel",
+      0,
+      G_MAXUINT,
+      0,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_STATE, param_spec);
+
+  param_spec = g_param_spec_string (
+      "content-type",
+      "gchar *content-type",
+      "ContentType of the file",
+      "",
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONTENT_TYPE,
+      param_spec);
+
+  param_spec = g_param_spec_string (
+      "filename",
+      "gchar *filename",
+      "Name of the file",
+      "",
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_FILENAME, param_spec);
+
+  param_spec = g_param_spec_uint64 (
+      "size",
+      "guint size",
+      "Size of the file in bytes",
+      0,
+      G_MAXUINT64,
+      SALUT_UNDEFINED_FILE_SIZE,
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_SIZE, param_spec);
+
+  param_spec = g_param_spec_uint (
+      "content-hash-type",
+      "SalutFileHashType content-hash-type",
+      "Hash type",
+      0,
+      G_MAXUINT,
+      SALUT_FILE_HASH_TYPE_NONE,
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONTENT_HASH_TYPE,
+      param_spec);
+
+  param_spec = g_param_spec_string (
+      "content-hash",
+      "gchar *content-hash",
+      "Hash of the file contents",
+      "",
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CONTENT_HASH,
+      param_spec);
+
+  param_spec = g_param_spec_string (
+      "description",
+      "gchar *description",
+      "Description of the file",
+      "",
+      /* TODO: change this to CONSTRUCT_ONLY when
+       * the new request API is used.
+       */
+      G_PARAM_CONSTRUCT |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_DESCRIPTION, param_spec);
+
+  param_spec = g_param_spec_boxed (
+      "available-socket-types",
+      "SalutSupportedSocketMap available-socket-types",
+      "Available socket types",
+      dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, DBUS_TYPE_G_UINT_ARRAY),
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_AVAILABLE_SOCKET_TYPES,
+      param_spec);
+
+  param_spec = g_param_spec_uint64 (
+      "transferred-bytes",
+      "guint64 transferred-bytes",
+      "Bytes transferred",
+      0,
+      G_MAXUINT64,
+      0,
+      G_PARAM_READABLE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_TRANSFERRED_BYTES,
+      param_spec);
+
+  param_spec = g_param_spec_uint64 (
+      "initial-offset",
+      "guint64 initial_offset",
+      "Offset set at the beginning of the transfer",
+      0,
+      G_MAXUINT64,
+      0,
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_INITIAL_OFFSET,
+      param_spec);
+
+  salut_file_channel_class->dbus_props_class.interfaces = prop_interfaces;
+  tp_dbus_properties_mixin_class_init (object_class,
+      G_STRUCT_OFFSET (SalutFileChannelClass, dbus_props_class));
+}
+
+void
+salut_file_channel_dispose (GObject *object)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
+  TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->connection);
+  TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (base_conn,
+      TP_HANDLE_TYPE_CONTACT);
+
+  if (self->priv->dispose_has_run)
+    return;
+
+  self->priv->dispose_has_run = TRUE;
+
+  tp_handle_unref (handle_repo, self->priv->handle);
+
+  salut_file_channel_do_close (self);
+
+  if (self->priv->contact)
+    {
+      g_object_unref (self->priv->contact);
+      self->priv->contact = NULL;
+    }
+
+  if (self->priv->xmpp_connection_manager != NULL)
+    {
+      g_object_unref (self->priv->xmpp_connection_manager);
+      self->priv->xmpp_connection_manager = NULL;
+    }
+
+  if (self->priv->xmpp_connection != NULL)
+    {
+      g_object_unref (self->priv->xmpp_connection);
+      self->priv->xmpp_connection = NULL;
+    }
+
+  /* release any references held by the object here */
+
+  if (G_OBJECT_CLASS (salut_file_channel_parent_class)->dispose)
+    G_OBJECT_CLASS (salut_file_channel_parent_class)->dispose (object);
+}
+
+static void
+salut_file_channel_finalize (GObject *object)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (object);
+
+  /* free any data held directly by the object here */
+  g_free (self->priv->object_path);
+  g_free (self->priv->filename);
+
+  G_OBJECT_CLASS (salut_file_channel_parent_class)->finalize (object);
+}
+
+
+/**
+ * salut_file_channel_close
+ *
+ * Implements DBus method Close
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+salut_file_channel_close (TpSvcChannel *iface,
+                          DBusGMethodInvocation *context)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
+
+  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_COMPLETED)
+    {
+      gibber_file_transfer_cancel (self->priv->ft, 406);
+      salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (iface),
+          SALUT_FILE_TRANSFER_STATE_CANCELLED,
+          SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED);
+    }
+
+  salut_file_channel_do_close (SALUT_FILE_CHANNEL (iface));
+  tp_svc_channel_return_from_close (context);
+}
+
+/**
+ * salut_file_channel_get_channel_type
+ *
+ * Implements DBus method GetChannelType
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+salut_file_channel_get_channel_type (TpSvcChannel *iface,
+                                     DBusGMethodInvocation *context)
+{
+  tp_svc_channel_return_from_get_channel_type (context,
+      SALUT_IFACE_CHANNEL_TYPE_FILE_TRANSFER);
+}
+
+/**
+ * salut_file_channel_get_handle
+ *
+ * Implements DBus method GetHandle
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+salut_file_channel_get_handle (TpSvcChannel *iface,
+                               DBusGMethodInvocation *context)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
+
+  tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT,
+                                         self->priv->handle);
+}
+
+/**
+ * salut_file_channel_get_interfaces
+ *
+ * Implements DBus method GetInterfaces
+ * on interface org.freedesktop.Telepathy.Channel
+ */
+static void
+salut_file_channel_get_interfaces (TpSvcChannel *iface,
+                                   DBusGMethodInvocation *context)
+{
+  tp_svc_channel_return_from_get_interfaces (context,
+      salut_file_channel_interfaces);
+}
+
+static void
+channel_iface_init (gpointer g_iface, gpointer iface_data)
+{
+  TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
+
+#define IMPLEMENT(x) tp_svc_channel_implement_##x (\
+    klass, salut_file_channel_##x)
+  IMPLEMENT (close);
+  IMPLEMENT (get_channel_type);
+  IMPLEMENT (get_handle);
+  IMPLEMENT (get_interfaces);
+#undef IMPLEMENT
+}
+
+static void
+error_cb (GibberFileTransfer *ft,
+          guint domain,
+          gint code,
+          const gchar *message,
+          SalutFileChannel *self)
+{
+}
+
+static void
+ft_finished_cb (GibberFileTransfer *ft,
+                SalutFileChannel *self)
+{
+  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
+      SALUT_FILE_TRANSFER_STATE_COMPLETED,
+      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+
+  salut_xmpp_connection_manager_release_connection (
+      self->priv->xmpp_connection_manager,
+      self->priv->xmpp_connection);
+}
+
+static void
+ft_remote_canceled_cb (GibberFileTransfer *ft,
+                       SalutFileChannel *self)
+{
+  gibber_file_transfer_cancel (ft, 406);
+  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
+      SALUT_FILE_TRANSFER_STATE_CANCELLED,
+      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED);
+
+  salut_xmpp_connection_manager_release_connection (
+      self->priv->xmpp_connection_manager,
+      self->priv->xmpp_connection);
+}
+
+static void
+remote_accepted_cb (GibberFileTransfer *ft,
+                    SalutFileChannel *self)
+{
+  salut_file_channel_set_state (SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self),
+      SALUT_FILE_TRANSFER_STATE_OPEN,
+      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+
+  g_signal_connect (ft, "finished", G_CALLBACK (ft_finished_cb), self);
+  g_signal_connect (ft, "canceled", G_CALLBACK (ft_remote_canceled_cb), self);
+}
+
+static gboolean setup_local_socket (SalutFileChannel *self);
+static void ft_transferred_chunk_cb (GibberFileTransfer *ft, guint64 count,
+    SalutFileChannel *self);
+
+static void
+send_file_offer (SalutFileChannel *self)
+{
+  GibberFileTransfer *ft;
+
+  ft = g_object_new (GIBBER_TYPE_OOB_FILE_TRANSFER,
+      "self-id", self->priv->connection->name,
+      "peer-id", self->priv->contact->name,
+      "filename", self->priv->filename,
+      "connection", self->priv->xmpp_connection,
+      NULL);
+  g_signal_connect (ft, "remote-accepted",
+      G_CALLBACK (remote_accepted_cb), self);
+  g_signal_connect (ft, "error", G_CALLBACK (error_cb), self);
+
+  self->priv->ft = ft;
+
+  g_signal_connect (ft, "transferred-chunk",
+      G_CALLBACK (ft_transferred_chunk_cb), self);
+
+  gibber_file_transfer_set_size (ft, self->priv->size);
+
+  gibber_file_transfer_offer (ft);
+}
+
+static void
+xmpp_connection_manager_new_connection_cb (SalutXmppConnectionManager *mgr,
+                                           GibberXmppConnection *connection,
+                                           SalutContact *contact,
+                                           gpointer user_data)
+{
+  SalutFileChannel *channel = user_data;
+
+  channel->priv->xmpp_connection = g_object_ref (connection);
+  salut_xmpp_connection_manager_take_connection (mgr, connection);
+  g_signal_handlers_disconnect_by_func (mgr,
+      xmpp_connection_manager_new_connection_cb, user_data);
+  send_file_offer (channel);
+}
+
+void
+salut_file_channel_received_file_offer (SalutFileChannel *self,
+                                        GibberXmppStanza *stanza,
+                                        GibberXmppConnection *conn)
+{
+  GibberFileTransfer *ft;
+
+  salut_xmpp_connection_manager_take_connection (
+      self->priv->xmpp_connection_manager , conn);
+  ft = gibber_file_transfer_new_from_stanza (stanza, conn);
+
+  g_return_if_fail (ft);
+
+  g_signal_connect (ft, "error", G_CALLBACK (error_cb), self);
+
+  DEBUG ("Received file offer with id '%s'", ft->id);
+
+  self->priv->ft = ft;
+
+  self->priv->filename = g_strdup (ft->filename);
+  self->priv->size = gibber_file_transfer_get_size (ft);
+}
+
+static void
+salut_file_channel_set_state (SalutSvcChannelTypeFileTransfer *iface,
+                              SalutFileTransferState state,
+                              SalutFileTransferStateChangeReason reason)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
+
+  self->priv->state = state;
+  salut_svc_channel_type_file_transfer_emit_file_transfer_state_changed (iface,
+      state, reason);
+}
+
+static void
+ft_transferred_chunk_cb (GibberFileTransfer *ft,
+                         guint64 count,
+                         SalutFileChannel *self)
+{
+  SalutSvcChannelTypeFileTransfer *iface = SALUT_SVC_CHANNEL_TYPE_FILE_TRANSFER (self);
+  GTimeVal timeval;
+
+  self->priv->transferred_bytes += count;
+
+  g_get_current_time (&timeval);
+
+  /* Only emit the TransferredBytes signal if it has been one second since its
+   * last emission, OR if the transfer has finished.
+   */
+  if (timeval.tv_sec >= (self->priv->last_transferred_bytes_emitted + 1)
+      || self->priv->transferred_bytes == self->priv->size)
+    {
+      salut_svc_channel_type_file_transfer_emit_transferred_bytes_changed (
+          iface, self->priv->transferred_bytes);
+      self->priv->last_transferred_bytes_emitted = timeval.tv_sec;
+    }
+}
+
+/**
+ * salut_file_channel_accept_file
+ *
+ * Implements D-Bus method AcceptFile
+ * on interface org.freedesktop.Telepathy.Channel.Type.File
+ */
+static void
+salut_file_channel_accept_file (SalutSvcChannelTypeFileTransfer *iface,
+                                guint address_type,
+                                guint access_control,
+                                const GValue *access_control_param,
+                                guint64 offset,
+                                DBusGMethodInvocation *context)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
+  GError *error = NULL;
+  GValue out_address = { 0 };
+  GibberFileTransfer *ft;
+
+  ft = self->priv->ft;
+  if (ft == NULL)
+    {
+      dbus_g_method_return_error (context, error);
+      g_error_free (error);
+    }
+
+  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_LOCAL_PENDING)
+    {
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+        "State is not local pending; cannot accept file");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX)
+    {
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+        "Address type %u not implemented", address_type);
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  g_signal_connect (ft, "finished", G_CALLBACK (ft_finished_cb), self);
+  g_signal_connect (ft, "transferred-chunk",
+      G_CALLBACK (ft_transferred_chunk_cb), self);
+  g_signal_connect (ft, "canceled", G_CALLBACK (ft_remote_canceled_cb), self);
+
+  if (!setup_local_socket(self))
+    {
+      DEBUG ("Could not set up local socket");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+          "Could not set up local socket");
+      dbus_g_method_return_error (context, error);
+    }
+
+  DEBUG ("local socket %s", self->priv->socket_path);
+
+  salut_file_channel_set_state (iface, SALUT_FILE_TRANSFER_STATE_ACCEPTED,
+        SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+
+  g_value_init (&out_address, G_TYPE_STRING);
+  g_value_set_string (&out_address, self->priv->socket_path);
+
+  salut_svc_channel_type_file_transfer_return_from_accept_file (context,
+      &out_address);
+
+  self->priv->initial_offset = 0;
+  salut_file_channel_set_state (iface, SALUT_FILE_TRANSFER_STATE_OPEN,
+      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+}
+
+/**
+ * salut_file_channel_offer_file
+ *
+ * Implements D-Bus method OfferFile
+ * on interface org.freedesktop.Telepathy.Channel.Type.File
+ */
+static void
+salut_file_channel_offer_file (SalutSvcChannelTypeFileTransfer *iface,
+                               guint address_type,
+                               guint access_control,
+                               const GValue *access_control_param,
+                               DBusGMethodInvocation *context)
+{
+  SalutFileChannel *self = SALUT_FILE_CHANNEL (iface);
+  GibberXmppConnection *connection = NULL;
+  SalutXmppConnectionManagerRequestConnectionResult request_result;
+  GError *error = NULL;
+  SalutFileChannel *channel = SALUT_FILE_CHANNEL (iface);
+  GValue out_address = { 0 };
+
+  if (self->priv->state != SALUT_FILE_TRANSFER_STATE_NOT_OFFERED)
+    {
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+          "State is not not offered; cannot offer file");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX)
+    {
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
+        "Address type %u not implemented", address_type);
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (CHECK_STR_EMPTY (channel->priv->content_type))
+    {
+      DEBUG ("ContentType property not set");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+        "ContentType property not set");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (CHECK_STR_EMPTY (channel->priv->filename))
+    {
+      DEBUG ("Filename property not set");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+        "Filename property not set");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (channel->priv->size == SALUT_UNDEFINED_FILE_SIZE)
+    {
+      DEBUG ("Size property not set");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+        "Size property not set");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  DEBUG ("Offering file transfer");
+
+  request_result = salut_xmpp_connection_manager_request_connection (
+      channel->priv->xmpp_connection_manager, channel->priv->contact,
+      &connection, &error);
+
+  if (request_result ==
+      SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_DONE)
+    {
+      channel->priv->xmpp_connection = connection;
+      send_file_offer (channel);
+    }
+  else if (request_result ==
+      SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_PENDING)
+    {
+      g_signal_connect (channel->priv->xmpp_connection_manager,
+          "new-connection",
+          G_CALLBACK (xmpp_connection_manager_new_connection_cb), channel);
+    }
+  else
+    {
+      DEBUG ("Request connection failed");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NETWORK_ERROR,
+        "Request connection failed");
+      dbus_g_method_return_error (context, error);
+      return;
+    }
+
+  if (!setup_local_socket(self))
+    {
+      DEBUG ("Could not set up local socket");
+      g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+          "Could not set up local socket");
+      dbus_g_method_return_error (context, error);
+    }
+
+  g_value_init (&out_address, G_TYPE_STRING);
+  g_value_set_string (&out_address, channel->priv->socket_path);
+
+  salut_file_channel_set_state (iface,
+      SALUT_FILE_TRANSFER_STATE_REMOTE_PENDING,
+      SALUT_FILE_TRANSFER_STATE_CHANGE_REASON_NONE);
+
+  salut_svc_channel_type_file_transfer_return_from_offer_file (context,
+      &out_address);
+}
+
+static void
+file_transfer_iface_init (gpointer g_iface,
+                          gpointer iface_data)
+{
+  SalutSvcChannelTypeFileTransferClass *klass =
+      (SalutSvcChannelTypeFileTransferClass *)g_iface;
+
+#define IMPLEMENT(x) salut_svc_channel_type_file_transfer_implement_##x (\
+    klass, salut_file_channel_##x)
+  IMPLEMENT (accept_file);
+  IMPLEMENT (offer_file);
+#undef IMPLEMENT
+}
+
+static const gchar *
+get_local_unix_socket_path (SalutFileChannel *self)
+{
+  gchar *path = NULL;
+  gint32 random;
+  gchar *random_str;
+  struct stat buf;
+
+  while (TRUE)
+    {
+      random = g_random_int_range (0, G_MAXINT32);
+      random_str = g_strdup_printf ("tp-ft-%i", random);
+      path = g_build_filename (g_get_tmp_dir (), random_str, NULL);
+      g_free (random_str);
+
+      if (g_stat (path, &buf) != 0)
+        break;
+
+      g_free (path);
+    }
+
+  if (self->priv->socket_path)
+    g_free (self->priv->socket_path);
+
+  self->priv->socket_path = path;
+
+  return path;
+}
+
+/*
+ * Return a GIOChannel for the local unix socket path.
+ */
+static GIOChannel *
+get_socket_channel (SalutFileChannel *self)
+{
+  gint fd;
+  const gchar *path;
+  size_t path_len;
+  struct sockaddr_un addr;
+  GIOChannel *io_channel;
+
+  path = get_local_unix_socket_path (self);
+
+  fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (fd < 0)
+    {
+      DEBUG("socket() failed");
+      return NULL;
+    }
+
+  memset (&addr, 0, sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  path_len = strlen (path);
+  strncpy (addr.sun_path, path, path_len);
+  g_unlink (path);
+
+  if (bind (fd, (struct sockaddr*) &addr,
+        G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+    {
+      DEBUG ("bind failed");
+      close (fd);
+      return NULL;
+    }
+
+  if (listen (fd, 1) < 0)
+    {
+      DEBUG ("listen failed");
+      close (fd);
+      return NULL;
+    }
+
+  io_channel = g_io_channel_unix_new (fd);
+  g_io_channel_set_close_on_unref (io_channel, TRUE);
+  return io_channel;
+}
+
+/*
+ * Some client is connecting to the Unix socket.
+ */
+static gboolean
+accept_local_socket_connection (GIOChannel *source,
+                                GIOCondition condition,
+                                gpointer user_data)
+{
+  GibberFileTransfer *ft;
+  int new_fd;
+  struct sockaddr_un addr;
+  socklen_t addrlen;
+  GIOChannel *channel;
+
+  ft = SALUT_FILE_CHANNEL (user_data)->priv->ft;
+
+  g_assert (ft != NULL);
+
+  if (condition & G_IO_IN)
+    {
+      DEBUG ("Client connected to local socket");
+
+      addrlen = sizeof (addr);
+      new_fd = accept (g_io_channel_unix_get_fd (source),
+          (struct sockaddr *) &addr, &addrlen);
+      if (new_fd < 0)
+        {
+          DEBUG ("accept() failed");
+          return FALSE;
+        }
+
+      channel = g_io_channel_unix_new (new_fd);
+      g_io_channel_set_close_on_unref (channel, TRUE);
+      g_io_channel_set_encoding (channel, NULL, NULL);
+      if (ft->direction == GIBBER_FILE_TRANSFER_DIRECTION_INCOMING)
+        gibber_file_transfer_receive (ft, channel);
+      else
+        gibber_file_transfer_send (ft, channel);
+      g_io_channel_unref (channel);
+    }
+
+  return FALSE;
+}
+
+static gboolean
+setup_local_socket (SalutFileChannel *self)
+{
+  GIOChannel *io_channel;
+
+  io_channel = get_socket_channel (self);
+  if (io_channel == NULL)
+    {
+      return FALSE;
+    }
+
+  g_io_add_watch (io_channel, G_IO_IN | G_IO_HUP,
+      accept_local_socket_connection, self);
+  g_io_channel_unref (io_channel);
+
+  return TRUE;
+}
+
diff --git a/src/salut-file-transfer-channel.h b/src/salut-file-transfer-channel.h
new file mode 100644
index 0000000..8fefa35
--- /dev/null
+++ b/src/salut-file-transfer-channel.h
@@ -0,0 +1,74 @@
+/*
+ * salut-file-transfer-channel.h - Header for SalutFileChannel
+ * Copyright (C) 2007 Marco Barisione <marco at barisione.org>
+ * Copyright (C) 2005, 2007, 2008 Collabora Ltd.
+ *   @author: Sjoerd Simons <sjoerd at luon.net>
+ *   @author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+ *
+ * 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_FILE_CHANNEL_H__
+#define __SALUT_FILE_CHANNEL_H__
+
+#include <glib-object.h>
+#include <gibber/gibber-file-transfer.h>
+
+#include <extensions/_gen/svc.h>
+#include <extensions/_gen/interfaces.h>
+#include <extensions/_gen/enums.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SalutFileChannel SalutFileChannel;
+typedef struct _SalutFileChannelClass SalutFileChannelClass;
+typedef struct _SalutFileChannelPrivate SalutFileChannelPrivate;
+
+struct _SalutFileChannelClass {
+    GObjectClass parent_class;
+    TpDBusPropertiesMixinClass dbus_props_class;
+};
+
+struct _SalutFileChannel {
+    GObject parent;
+
+    SalutFileChannelPrivate *priv;
+};
+
+GType salut_file_channel_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_FILE_CHANNEL \
+  (salut_file_channel_get_type ())
+#define SALUT_FILE_CHANNEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_FILE_CHANNEL, SalutFileChannel))
+#define SALUT_FILE_CHANNEL_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_FILE_CHANNEL, \
+                           SalutFileChannelClass))
+#define SALUT_IS_FILE_CHANNEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_FILE_CHANNEL))
+#define SALUT_IS_FILE_CHANNEL_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_FILE_CHANNEL))
+#define SALUT_FILE_CHANNEL_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_FILE_CHANNEL, \
+                              SalutFileChannelClass))
+
+void
+salut_file_channel_received_file_offer (SalutFileChannel *self,
+    GibberXmppStanza *stanza, GibberXmppConnection *conn);
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_FILE_CHANNEL_H__*/
diff --git a/src/salut-ft-manager.c b/src/salut-ft-manager.c
index f6dc110..6a8576d 100644
--- a/src/salut-ft-manager.c
+++ b/src/salut-ft-manager.c
@@ -29,7 +29,7 @@
 #include "salut-ft-manager.h"
 #include "signals-marshal.h"
 
-#include "salut-file-channel.h"
+#include "salut-file-transfer-channel.h"
 #include "salut-contact-manager.h"
 
 #include <telepathy-glib/channel-factory-iface.h>
-- 
1.5.6.5




More information about the Telepathy-commits mailing list