aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-tp-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy/empathy-tp-file.c')
-rw-r--r--libempathy/empathy-tp-file.c967
1 files changed, 474 insertions, 493 deletions
diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c
index fec91af5a..3e5a06d4c 100644
--- a/libempathy/empathy-tp-file.c
+++ b/libempathy/empathy-tp-file.c
@@ -66,24 +66,209 @@
* the transferred file is unknown.
*/
-static void empathy_tp_file_class_init (EmpathyTpFileClass *klass);
-static void empathy_tp_file_init (EmpathyTpFile *tp_file);
-static void tp_file_finalize (GObject *object);
-static GObject *tp_file_constructor (GType type, guint n_props,
- GObjectConstructParam *props);
-static void tp_file_get_property (GObject *object, guint param_id,
- GValue *value, GParamSpec *pspec);
-static void tp_file_set_property (GObject *object, guint param_id,
- const GValue *value, GParamSpec *pspec);
-static void tp_file_destroy_cb (TpChannel *file_chan, EmpathyTpFile *tp_file);
-static void tp_file_closed_cb (TpChannel *file_chan, EmpathyTpFile *tp_file,
- GObject *weak_object);
-static void tp_file_state_changed_cb (DBusGProxy *file_iface, guint state,
- guint reason, EmpathyTpFile *tp_file);
-static void tp_file_transferred_bytes_changed_cb (TpProxy *proxy,
- guint64 count, EmpathyTpFile *tp_file, GObject *weak_object);
-static void copy_stream (GInputStream *in, GOutputStream *out,
- GCancellable *cancellable);
+/* Functions to copy the content of a GInputStream to a GOutputStream */
+
+#define N_BUFFERS 2
+#define BUFFER_SIZE 4096
+
+typedef struct {
+ GInputStream *in;
+ GOutputStream *out;
+ GCancellable *cancellable;
+ char *buff[N_BUFFERS]; /* the temporary buffers */
+ gsize count[N_BUFFERS]; /* how many bytes are used in the buffers */
+ gboolean is_full[N_BUFFERS]; /* whether the buffers contain data */
+ gint curr_read; /* index of the buffer used for reading */
+ gint curr_write; /* index of the buffer used for writing */
+ gboolean is_reading; /* we are reading */
+ gboolean is_writing; /* we are writing */
+ guint n_closed; /* number of streams that have been closed */
+} CopyData;
+
+static void schedule_next (CopyData *copy);
+
+static void
+free_copy_data_if_closed (CopyData *copy)
+{
+ gint i;
+
+ /* Free the data only if both the input and output streams have
+ * been closed. */
+ copy->n_closed++;
+ if (copy->n_closed < 2)
+ return;
+
+ if (copy->in != NULL)
+ g_object_unref (copy->in);
+
+ if (copy->out != NULL)
+ g_object_unref (copy->out);
+
+ for (i = 0; i < N_BUFFERS; i++)
+ g_free (copy->buff[i]);
+
+ g_object_unref (copy->cancellable);
+ g_free (copy);
+}
+
+static void
+io_error (CopyData *copy,
+ GError *error)
+{
+ g_cancellable_cancel (copy->cancellable);
+
+ if (error == NULL)
+ g_warning ("I/O error");
+ else if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED)
+ ; /* Ignore cancellations */
+ else
+ g_warning ("I/O error: %d: %s\n", error->code, error->message);
+
+ if (copy->in != NULL)
+ g_input_stream_close (copy->in, NULL, NULL);
+
+ if (copy->out != NULL)
+ g_output_stream_close (copy->out, NULL, NULL);
+
+ free_copy_data_if_closed (copy);
+}
+
+static void
+close_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CopyData *copy = user_data;
+
+ g_object_unref (source_object);
+ free_copy_data_if_closed (copy);
+}
+
+static void
+write_done_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CopyData *copy = user_data;
+ gssize count_write;
+ GError *error = NULL;
+
+ count_write = g_output_stream_write_finish (copy->out, res, &error);
+
+ if (count_write <= 0)
+ {
+ io_error (copy, error);
+ g_error_free (error);
+ return;
+ }
+
+ copy->is_full[copy->curr_write] = FALSE;
+ copy->curr_write = (copy->curr_write + 1) % N_BUFFERS;
+ copy->is_writing = FALSE;
+
+ schedule_next (copy);
+}
+
+static void
+read_done_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CopyData *copy = user_data;
+ gssize count_read;
+ GError *error = NULL;
+
+ count_read = g_input_stream_read_finish (copy->in, res, &error);
+
+ if (count_read == 0)
+ {
+ g_input_stream_close_async (copy->in, 0, copy->cancellable,
+ close_done, copy);
+ copy->in = NULL;
+ }
+ else if (count_read < 0)
+ {
+ io_error (copy, error);
+ g_error_free (error);
+ return;
+ }
+
+ copy->count[copy->curr_read] = count_read;
+ copy->is_full[copy->curr_read] = TRUE;
+ copy->curr_read = (copy->curr_read + 1) % N_BUFFERS;
+ copy->is_reading = FALSE;
+
+ schedule_next (copy);
+}
+
+static void
+schedule_next (CopyData *copy)
+{
+ if (copy->in != NULL &&
+ !copy->is_reading &&
+ !copy->is_full[copy->curr_read])
+ {
+ /* We are not reading and the current buffer is empty, so
+ * start an async read. */
+ copy->is_reading = TRUE;
+ g_input_stream_read_async (copy->in,
+ copy->buff[copy->curr_read],
+ BUFFER_SIZE, 0, copy->cancellable,
+ read_done_cb, copy);
+ }
+
+ if (!copy->is_writing &&
+ copy->is_full[copy->curr_write])
+ {
+ if (copy->count[copy->curr_write] == 0)
+ {
+ /* The last read on the buffer read 0 bytes, this
+ * means that we got an EOF, so we can close
+ * the output channel. */
+ g_output_stream_close_async (copy->out, 0,
+ copy->cancellable,
+ close_done, copy);
+ copy->out = NULL;
+ }
+ else
+ {
+ /* We are not writing and the current buffer contains
+ * data, so start an async write. */
+ copy->is_writing = TRUE;
+ g_output_stream_write_async (copy->out,
+ copy->buff[copy->curr_write],
+ copy->count[copy->curr_write],
+ 0, copy->cancellable,
+ write_done_cb, copy);
+ }
+ }
+}
+
+static void
+copy_stream (GInputStream *in,
+ GOutputStream *out,
+ GCancellable *cancellable)
+{
+ CopyData *copy;
+ gint i;
+
+ g_return_if_fail (in != NULL);
+ g_return_if_fail (out != NULL);
+
+ copy = g_new0 (CopyData, 1);
+ copy->in = g_object_ref (in);
+ copy->out = g_object_ref (out);
+
+ if (cancellable != NULL)
+ copy->cancellable = g_object_ref (cancellable);
+ else
+ copy->cancellable = g_cancellable_new ();
+
+ for (i = 0; i < N_BUFFERS; i++)
+ copy->buff[i] = g_malloc (BUFFER_SIZE);
+
+ schedule_next (copy);
+}
/* EmpathyTpFile object */
@@ -136,122 +321,22 @@ enum {
G_DEFINE_TYPE (EmpathyTpFile, empathy_tp_file, G_TYPE_OBJECT);
static void
-empathy_tp_file_class_init (EmpathyTpFileClass *klass)
+empathy_tp_file_init (EmpathyTpFile *tp_file)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = tp_file_finalize;
- object_class->constructor = tp_file_constructor;
- object_class->get_property = tp_file_get_property;
- object_class->set_property = tp_file_set_property;
-
- /* Construct-only properties */
- g_object_class_install_property (object_class,
- PROP_ACCOUNT,
- g_param_spec_object ("account",
- "channel Account",
- "The account associated with the channel",
- MC_TYPE_ACCOUNT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_CHANNEL,
- g_param_spec_object ("channel",
- "telepathy channel",
- "The file transfer channel",
- TP_TYPE_CHANNEL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_STATE,
- g_param_spec_uint ("state",
- "state of the transfer",
- "The file transfer state",
- 0,
- G_MAXUINT,
- G_MAXUINT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (object_class,
- PROP_INCOMING,
- g_param_spec_boolean ("incoming",
- "incoming",
- "Whether the transfer is incoming",
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (object_class,
- PROP_FILENAME,
- g_param_spec_string ("filename",
- "name of the transfer",
- "The file transfer filename",
- "",
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_SIZE,
- g_param_spec_uint64 ("size",
- "size of the file",
- "The file transfer size",
- 0,
- G_MAXUINT64,
- G_MAXUINT64,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_CONTENT_TYPE,
- g_param_spec_string ("content-type",
- "file transfer content-type",
- "The file transfer content-type",
- "",
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_CONTENT_HASH_TYPE,
- g_param_spec_uint ("content-hash-type",
- "file transfer hash type",
- "The type of the file transfer hash",
- 0,
- G_MAXUINT,
- 0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_CONTENT_HASH,
- g_param_spec_string ("content-hash",
- "file transfer hash",
- "The hash of the transfer's contents",
- "",
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_TRANSFERRED_BYTES,
- g_param_spec_uint64 ("transferred-bytes",
- "bytes transferred",
- "The number of bytes transferred",
- 0,
- G_MAXUINT64,
- 0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_IN_STREAM,
- g_param_spec_object ("in-stream",
- "transfer input stream",
- "The input stream for file transfer",
- G_TYPE_INPUT_STREAM,
- G_PARAM_READWRITE));
-
- g_type_class_add_private (object_class, sizeof (EmpathyTpFilePriv));
}
static void
-empathy_tp_file_init (EmpathyTpFile *tp_file)
+tp_file_destroy_cb (TpChannel *file_channel,
+ EmpathyTpFile *tp_file)
{
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ DEBUG ("Channel Closed or CM crashed");
+
+ g_object_unref (priv->channel);
+ priv->channel = NULL;
}
static void
@@ -351,6 +436,169 @@ tp_file_get_all_cb (TpProxy *proxy,
g_hash_table_destroy (properties);
}
+static void
+tp_file_closed_cb (TpChannel *file_channel,
+ EmpathyTpFile *tp_file,
+ GObject *weak_object)
+{
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ /* The channel is closed, do just like if the proxy was destroyed */
+ g_signal_handlers_disconnect_by_func (priv->channel,
+ tp_file_destroy_cb,
+ tp_file);
+ tp_file_destroy_cb (file_channel, tp_file);
+}
+
+static gint64
+get_time_msec (void)
+{
+ GTimeVal tv;
+
+ g_get_current_time (&tv);
+ return ((gint64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+}
+
+static gint
+_get_local_socket (EmpathyTpFile *tp_file)
+{
+ gint fd;
+ size_t path_len;
+ struct sockaddr_un addr;
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ if (G_STR_EMPTY (priv->unix_socket_path))
+ return -1;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -1;
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ path_len = strlen (priv->unix_socket_path);
+ strncpy (addr.sun_path, priv->unix_socket_path, path_len);
+
+ if (connect (fd, (struct sockaddr*) &addr,
+ sizeof (addr)) < 0)
+ {
+ close (fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static void
+send_tp_file (EmpathyTpFile *tp_file)
+{
+ gint socket_fd;
+ GOutputStream *socket_stream;
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ DEBUG ("Sending file content: filename=%s",
+ priv->filename);
+
+ g_return_if_fail (priv->in_stream);
+
+ socket_fd = _get_local_socket (tp_file);
+ if (socket_fd < 0)
+ {
+ DEBUG ("failed to get local socket fd");
+ return;
+ }
+ DEBUG ("got local socket fd");
+ socket_stream = g_unix_output_stream_new (socket_fd, TRUE);
+
+ priv->cancellable = g_cancellable_new ();
+
+ copy_stream (priv->in_stream, socket_stream, priv->cancellable);
+
+ g_object_unref (socket_stream);
+}
+
+static void
+receive_tp_file (EmpathyTpFile *tp_file)
+{
+ EmpathyTpFilePriv *priv;
+ GInputStream *socket_stream;
+ gint socket_fd;
+
+ priv = GET_PRIV (tp_file);
+
+ socket_fd = _get_local_socket (tp_file);
+
+ if (socket_fd < 0)
+ return;
+
+ socket_stream = g_unix_input_stream_new (socket_fd, TRUE);
+
+ priv->cancellable = g_cancellable_new ();
+
+ copy_stream (socket_stream, priv->out_stream, priv->cancellable);
+
+ g_object_unref (socket_stream);
+}
+
+static void
+tp_file_state_changed_cb (DBusGProxy *tp_file_iface,
+ EmpFileTransferState state,
+ EmpFileTransferStateChangeReason reason,
+ EmpathyTpFile *tp_file)
+{
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ DEBUG ("File transfer state changed: filename=%s, "
+ "old state=%u, state=%u, reason=%u",
+ priv->filename, priv->state, state, reason);
+
+ if (state == EMP_FILE_TRANSFER_STATE_OPEN)
+ priv->start_time = get_time_msec ();
+
+ DEBUG ("state = %u, incoming = %s, in_stream = %s, out_stream = %s",
+ state, priv->incoming ? "yes" : "no",
+ priv->in_stream ? "present" : "not present",
+ priv->out_stream ? "present" : "not present");
+
+ if (state == EMP_FILE_TRANSFER_STATE_OPEN && !priv->incoming &&
+ priv->in_stream)
+ send_tp_file (tp_file);
+ else if (state == EMP_FILE_TRANSFER_STATE_OPEN && priv->incoming &&
+ priv->out_stream)
+ receive_tp_file (tp_file);
+
+ priv->state = state;
+ priv->state_change_reason = reason;
+
+ g_object_notify (G_OBJECT (tp_file), "state");
+}
+
+static void
+tp_file_transferred_bytes_changed_cb (TpProxy *proxy,
+ guint64 count,
+ EmpathyTpFile *tp_file,
+ GObject *weak_object)
+{
+ EmpathyTpFilePriv *priv;
+
+ priv = GET_PRIV (tp_file);
+
+ if (priv->transferred_bytes == count)
+ return;
+
+ priv->transferred_bytes = count;
+
+ g_object_notify (G_OBJECT (tp_file), "transferred-bytes");
+}
+
static GObject *
tp_file_constructor (GType type,
guint n_props,
@@ -551,77 +799,6 @@ empathy_tp_file_get_channel (EmpathyTpFile *tp_file)
}
static void
-tp_file_destroy_cb (TpChannel *file_channel,
- EmpathyTpFile *tp_file)
-{
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- DEBUG ("Channel Closed or CM crashed");
-
- g_object_unref (priv->channel);
- priv->channel = NULL;
-}
-
-static void
-tp_file_closed_cb (TpChannel *file_channel,
- EmpathyTpFile *tp_file,
- GObject *weak_object)
-{
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- /* The channel is closed, do just like if the proxy was destroyed */
- g_signal_handlers_disconnect_by_func (priv->channel,
- tp_file_destroy_cb,
- tp_file);
- tp_file_destroy_cb (file_channel, tp_file);
-}
-
-static gint64
-get_time_msec (void)
-{
- GTimeVal tv;
-
- g_get_current_time (&tv);
- return ((gint64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
-}
-
-static gint
-_get_local_socket (EmpathyTpFile *tp_file)
-{
- gint fd;
- size_t path_len;
- struct sockaddr_un addr;
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- if (G_STR_EMPTY (priv->unix_socket_path))
- return -1;
-
- fd = socket (PF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- return -1;
-
- memset (&addr, 0, sizeof (addr));
- addr.sun_family = AF_UNIX;
- path_len = strlen (priv->unix_socket_path);
- strncpy (addr.sun_path, priv->unix_socket_path, path_len);
-
- if (connect (fd, (struct sockaddr*) &addr,
- sizeof (addr)) < 0)
- {
- close (fd);
- return -1;
- }
-
- return fd;
-}
-
-static void
tp_file_method_cb (TpProxy *proxy,
const GValue *address,
const GError *error,
@@ -700,112 +877,6 @@ empathy_tp_file_offer (EmpathyTpFile *tp_file)
&nothing, tp_file_method_cb, priv, NULL, NULL);
}
-static void
-receive_tp_file (EmpathyTpFile *tp_file)
-{
- EmpathyTpFilePriv *priv;
- GInputStream *socket_stream;
- gint socket_fd;
-
- priv = GET_PRIV (tp_file);
-
- socket_fd = _get_local_socket (tp_file);
-
- if (socket_fd < 0)
- return;
-
- socket_stream = g_unix_input_stream_new (socket_fd, TRUE);
-
- priv->cancellable = g_cancellable_new ();
-
- copy_stream (socket_stream, priv->out_stream, priv->cancellable);
-
- g_object_unref (socket_stream);
-}
-
-static void
-send_tp_file (EmpathyTpFile *tp_file)
-{
- gint socket_fd;
- GOutputStream *socket_stream;
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- DEBUG ("Sending file content: filename=%s",
- priv->filename);
-
- g_return_if_fail (priv->in_stream);
-
- socket_fd = _get_local_socket (tp_file);
- if (socket_fd < 0)
- {
- DEBUG ("failed to get local socket fd");
- return;
- }
- DEBUG ("got local socket fd");
- socket_stream = g_unix_output_stream_new (socket_fd, TRUE);
-
- priv->cancellable = g_cancellable_new ();
-
- copy_stream (priv->in_stream, socket_stream, priv->cancellable);
-
- g_object_unref (socket_stream);
-}
-
-static void
-tp_file_state_changed_cb (DBusGProxy *tp_file_iface,
- EmpFileTransferState state,
- EmpFileTransferStateChangeReason reason,
- EmpathyTpFile *tp_file)
-{
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- DEBUG ("File transfer state changed: filename=%s, "
- "old state=%u, state=%u, reason=%u",
- priv->filename, priv->state, state, reason);
-
- if (state == EMP_FILE_TRANSFER_STATE_OPEN)
- priv->start_time = get_time_msec ();
-
- DEBUG ("state = %u, incoming = %s, in_stream = %s, out_stream = %s",
- state, priv->incoming ? "yes" : "no",
- priv->in_stream ? "present" : "not present",
- priv->out_stream ? "present" : "not present");
-
- if (state == EMP_FILE_TRANSFER_STATE_OPEN && !priv->incoming &&
- priv->in_stream)
- send_tp_file (tp_file);
- else if (state == EMP_FILE_TRANSFER_STATE_OPEN && priv->incoming &&
- priv->out_stream)
- receive_tp_file (tp_file);
-
- priv->state = state;
- priv->state_change_reason = reason;
-
- g_object_notify (G_OBJECT (tp_file), "state");
-}
-
-static void
-tp_file_transferred_bytes_changed_cb (TpProxy *proxy,
- guint64 count,
- EmpathyTpFile *tp_file,
- GObject *weak_object)
-{
- EmpathyTpFilePriv *priv;
-
- priv = GET_PRIV (tp_file);
-
- if (priv->transferred_bytes == count)
- return;
-
- priv->transferred_bytes = count;
-
- g_object_notify (G_OBJECT (tp_file), "transferred-bytes");
-}
-
EmpathyContact *
empathy_tp_file_get_contact (EmpathyTpFile *tp_file)
{
@@ -1004,206 +1075,116 @@ empathy_tp_file_set_filename (EmpathyTpFile *tp_file,
g_object_notify (G_OBJECT (tp_file), "filename");
}
-/* Functions to copy the content of a GInputStream to a GOutputStream */
-
-#define N_BUFFERS 2
-#define BUFFER_SIZE 4096
-
-typedef struct {
- GInputStream *in;
- GOutputStream *out;
- GCancellable *cancellable;
- char *buff[N_BUFFERS]; /* the temporary buffers */
- gsize count[N_BUFFERS]; /* how many bytes are used in the buffers */
- gboolean is_full[N_BUFFERS]; /* whether the buffers contain data */
- gint curr_read; /* index of the buffer used for reading */
- gint curr_write; /* index of the buffer used for writing */
- gboolean is_reading; /* we are reading */
- gboolean is_writing; /* we are writing */
- guint n_closed; /* number of streams that have been closed */
-} CopyData;
-
-static void schedule_next (CopyData *copy);
-
-static void
-free_copy_data_if_closed (CopyData *copy)
-{
- gint i;
-
- /* Free the data only if both the input and output streams have
- * been closed. */
- copy->n_closed++;
- if (copy->n_closed < 2)
- return;
-
- if (copy->in != NULL)
- g_object_unref (copy->in);
-
- if (copy->out != NULL)
- g_object_unref (copy->out);
-
- for (i = 0; i < N_BUFFERS; i++)
- g_free (copy->buff[i]);
-
- g_object_unref (copy->cancellable);
- g_free (copy);
-}
-
-static void
-io_error (CopyData *copy,
- GError *error)
-{
- g_cancellable_cancel (copy->cancellable);
-
- if (error == NULL)
- g_warning ("I/O error");
- else if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED)
- ; /* Ignore cancellations */
- else
- g_warning ("I/O error: %d: %s\n", error->code, error->message);
-
- if (copy->in != NULL)
- g_input_stream_close (copy->in, NULL, NULL);
-
- if (copy->out != NULL)
- g_output_stream_close (copy->out, NULL, NULL);
-
- free_copy_data_if_closed (copy);
-}
-
-static void
-close_done (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- CopyData *copy = user_data;
-
- g_object_unref (source_object);
- free_copy_data_if_closed (copy);
-}
-
static void
-write_done_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+empathy_tp_file_class_init (EmpathyTpFileClass *klass)
{
- CopyData *copy = user_data;
- gssize count_write;
- GError *error = NULL;
-
- count_write = g_output_stream_write_finish (copy->out, res, &error);
-
- if (count_write <= 0)
- {
- io_error (copy, error);
- g_error_free (error);
- return;
- }
-
- copy->is_full[copy->curr_write] = FALSE;
- copy->curr_write = (copy->curr_write + 1) % N_BUFFERS;
- copy->is_writing = FALSE;
-
- schedule_next (copy);
-}
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
-static void
-read_done_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- CopyData *copy = user_data;
- gssize count_read;
- GError *error = NULL;
+ object_class->finalize = tp_file_finalize;
+ object_class->constructor = tp_file_constructor;
+ object_class->get_property = tp_file_get_property;
+ object_class->set_property = tp_file_set_property;
- count_read = g_input_stream_read_finish (copy->in, res, &error);
+ /* Construct-only properties */
+ g_object_class_install_property (object_class,
+ PROP_ACCOUNT,
+ g_param_spec_object ("account",
+ "channel Account",
+ "The account associated with the channel",
+ MC_TYPE_ACCOUNT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
- if (count_read == 0)
- {
- g_input_stream_close_async (copy->in, 0, copy->cancellable,
- close_done, copy);
- copy->in = NULL;
- }
- else if (count_read < 0)
- {
- io_error (copy, error);
- g_error_free (error);
- return;
- }
+ g_object_class_install_property (object_class,
+ PROP_CHANNEL,
+ g_param_spec_object ("channel",
+ "telepathy channel",
+ "The file transfer channel",
+ TP_TYPE_CHANNEL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
- copy->count[copy->curr_read] = count_read;
- copy->is_full[copy->curr_read] = TRUE;
- copy->curr_read = (copy->curr_read + 1) % N_BUFFERS;
- copy->is_reading = FALSE;
+ g_object_class_install_property (object_class,
+ PROP_STATE,
+ g_param_spec_uint ("state",
+ "state of the transfer",
+ "The file transfer state",
+ 0,
+ G_MAXUINT,
+ G_MAXUINT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
- schedule_next (copy);
-}
+ g_object_class_install_property (object_class,
+ PROP_INCOMING,
+ g_param_spec_boolean ("incoming",
+ "incoming",
+ "Whether the transfer is incoming",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
-static void
-schedule_next (CopyData *copy)
-{
- if (copy->in != NULL &&
- !copy->is_reading &&
- !copy->is_full[copy->curr_read])
- {
- /* We are not reading and the current buffer is empty, so
- * start an async read. */
- copy->is_reading = TRUE;
- g_input_stream_read_async (copy->in,
- copy->buff[copy->curr_read],
- BUFFER_SIZE, 0, copy->cancellable,
- read_done_cb, copy);
- }
+ g_object_class_install_property (object_class,
+ PROP_FILENAME,
+ g_param_spec_string ("filename",
+ "name of the transfer",
+ "The file transfer filename",
+ "",
+ G_PARAM_READWRITE));
- if (!copy->is_writing &&
- copy->is_full[copy->curr_write])
- {
- if (copy->count[copy->curr_write] == 0)
- {
- /* The last read on the buffer read 0 bytes, this
- * means that we got an EOF, so we can close
- * the output channel. */
- g_output_stream_close_async (copy->out, 0,
- copy->cancellable,
- close_done, copy);
- copy->out = NULL;
- }
- else
- {
- /* We are not writing and the current buffer contains
- * data, so start an async write. */
- copy->is_writing = TRUE;
- g_output_stream_write_async (copy->out,
- copy->buff[copy->curr_write],
- copy->count[copy->curr_write],
- 0, copy->cancellable,
- write_done_cb, copy);
- }
- }
-}
+ g_object_class_install_property (object_class,
+ PROP_SIZE,
+ g_param_spec_uint64 ("size",
+ "size of the file",
+ "The file transfer size",
+ 0,
+ G_MAXUINT64,
+ G_MAXUINT64,
+ G_PARAM_READWRITE));
-static void
-copy_stream (GInputStream *in,
- GOutputStream *out,
- GCancellable *cancellable)
-{
- CopyData *copy;
- gint i;
+ g_object_class_install_property (object_class,
+ PROP_CONTENT_TYPE,
+ g_param_spec_string ("content-type",
+ "file transfer content-type",
+ "The file transfer content-type",
+ "",
+ G_PARAM_READWRITE));
- g_return_if_fail (in != NULL);
- g_return_if_fail (out != NULL);
+ g_object_class_install_property (object_class,
+ PROP_CONTENT_HASH_TYPE,
+ g_param_spec_uint ("content-hash-type",
+ "file transfer hash type",
+ "The type of the file transfer hash",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
- copy = g_new0 (CopyData, 1);
- copy->in = g_object_ref (in);
- copy->out = g_object_ref (out);
+ g_object_class_install_property (object_class,
+ PROP_CONTENT_HASH,
+ g_param_spec_string ("content-hash",
+ "file transfer hash",
+ "The hash of the transfer's contents",
+ "",
+ G_PARAM_READWRITE));
- if (cancellable != NULL)
- copy->cancellable = g_object_ref (cancellable);
- else
- copy->cancellable = g_cancellable_new ();
+ g_object_class_install_property (object_class,
+ PROP_TRANSFERRED_BYTES,
+ g_param_spec_uint64 ("transferred-bytes",
+ "bytes transferred",
+ "The number of bytes transferred",
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE));
- for (i = 0; i < N_BUFFERS; i++)
- copy->buff[i] = g_malloc (BUFFER_SIZE);
+ g_object_class_install_property (object_class,
+ PROP_IN_STREAM,
+ g_param_spec_object ("in-stream",
+ "transfer input stream",
+ "The input stream for file transfer",
+ G_TYPE_INPUT_STREAM,
+ G_PARAM_READWRITE));
- schedule_next (copy);
+ g_type_class_add_private (object_class, sizeof (EmpathyTpFilePriv));
}