summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-11-08 12:03:06 +0000
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-11-23 11:31:33 +0000
commitc50437349ed9abde5334285206cb1f942b09e077 (patch)
treeea50c8baec05ad5175e72812829f63c34d649287
parentf49f559ed949af867a8c055e8fc12a9fcf80c2f5 (diff)
tp-yts-glib tests: add file transfer test/example
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--.gitignore1
-rw-r--r--telepathy-ytstenut-glib/tests/Makefile.am3
-rw-r--r--telepathy-ytstenut-glib/tests/server-file-transfer.c303
3 files changed, 306 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index b839f5f..fb7c3bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ tp-glib-tools/telepathy-glib-env
/telepathy-ytstenut-glib/tests/server-nosey-status
/telepathy-ytstenut-glib/tests/server-passing-service
/telepathy-ytstenut-glib/tests/server-passing-status
+/telepathy-ytstenut-glib/tests/server-file-transfer
/docs/reference/xml
/docs/reference/html
diff --git a/telepathy-ytstenut-glib/tests/Makefile.am b/telepathy-ytstenut-glib/tests/Makefile.am
index 71b7260..f052e21 100644
--- a/telepathy-ytstenut-glib/tests/Makefile.am
+++ b/telepathy-ytstenut-glib/tests/Makefile.am
@@ -25,4 +25,5 @@ noinst_PROGRAMS = \
server-client-ping \
server-nosey-status \
server-passing-service \
- server-passing-status
+ server-passing-status \
+ server-file-transfer
diff --git a/telepathy-ytstenut-glib/tests/server-file-transfer.c b/telepathy-ytstenut-glib/tests/server-file-transfer.c
new file mode 100644
index 0000000..ddf1901
--- /dev/null
+++ b/telepathy-ytstenut-glib/tests/server-file-transfer.c
@@ -0,0 +1,303 @@
+/*
+ * server-file-transfer.c - send/receive a file to another ytstenut service
+ *
+ * Copyright (C) 2011 Intel Corp.
+ *
+ * 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 "config.h"
+
+#include <telepathy-ytstenut-glib/telepathy-ytstenut-glib.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+
+static GMainLoop *loop = NULL;
+
+static const gchar *local_service = NULL;
+static const gchar *remote_service = NULL;
+static const gchar *contact_id = NULL;
+static const gchar *file_path = NULL;
+
+static void
+getoutofhere (void)
+{
+ g_main_loop_quit (loop);
+}
+
+static void
+provide_file_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpFileTransferChannel *channel = TP_FILE_TRANSFER_CHANNEL (source_object);
+ GError *error = NULL;
+
+ if (!tp_file_transfer_channel_provide_file_finish (channel, result, &error))
+ {
+ g_printerr ("failed to provide file: %s\n", error->message);
+ g_clear_error (&error);
+ getoutofhere ();
+ }
+}
+
+static void
+state_changed_cb (TpFileTransferChannel *channel,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ TpFileTransferState state = tp_file_transfer_channel_get_state (channel, NULL);
+
+ if (state == TP_FILE_TRANSFER_STATE_ACCEPTED
+ && tp_channel_get_requested (TP_CHANNEL (channel)))
+ {
+ GFile *file = g_file_new_for_path (file_path);
+
+ tp_file_transfer_channel_provide_file_async (channel, file,
+ provide_file_cb, NULL);
+
+ g_object_unref (file);
+ }
+ else if (state == TP_FILE_TRANSFER_STATE_COMPLETED)
+ {
+ g_print ("transfer complete!\n");
+ getoutofhere ();
+ }
+}
+
+static void
+create_and_handle_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpAccountChannelRequest *channel_request = TP_ACCOUNT_CHANNEL_REQUEST (source);
+ GError *error = NULL;
+
+ TpChannel *channel = tp_account_channel_request_create_and_handle_channel_finish (
+ channel_request, result, NULL, &error);
+
+ if (channel == NULL)
+ {
+ g_printerr ("failed to create channel: %s\n", error->message);
+ g_clear_error (&error);
+ getoutofhere ();
+ return;
+ }
+
+ g_signal_connect (channel, "notify::state", G_CALLBACK (state_changed_cb), NULL);
+}
+
+static void
+got_account (TpAccount *account)
+{
+ TpYtsClient *client;
+ GHashTable *request;
+ TpAccountChannelRequest *channel_request;
+ GFile *file;
+ GFileInfo *info;
+ GError *error = NULL;
+
+ const gchar *name, *mimetype;
+ GTimeVal mtime;
+ goffset filesize;
+
+ g_print ("requesting FT channel...\n");
+
+ file = g_file_new_for_path (file_path);
+ info = g_file_query_info (file, "*", G_FILE_QUERY_INFO_NONE, NULL, &error);
+
+ if (info == NULL)
+ {
+ g_printerr ("failed to get information for file: %s\n", error->message);
+ goto out;
+ }
+
+ name = g_file_info_get_name (info);
+ mimetype = g_file_info_get_content_type (info);
+ g_file_info_get_modification_time (info, &mtime);
+ filesize = g_file_info_get_size (info);
+
+ /* Now we have everything prepared to continue, let's create the
+ * Ytstenut channel handler with service name specified on the
+ * command line. */
+ client = tp_yts_client_new (local_service, account);
+ tp_yts_client_register (client, NULL);
+
+ /* So let's request a channel. */
+ request = tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
+ TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, contact_id,
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_TYPE, G_TYPE_STRING, mimetype,
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DATE, G_TYPE_INT64, (gint64) mtime.tv_sec,
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DESCRIPTION, G_TYPE_STRING, "",
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, G_TYPE_STRING, name,
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_INITIAL_OFFSET, G_TYPE_UINT64, 0,
+ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, G_TYPE_UINT64, (guint64) filesize,
+ /* here is the remote service */
+ TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, G_TYPE_STRING, remote_service,
+ NULL);
+ channel_request = tp_account_channel_request_new (account, request,
+ TP_USER_ACTION_TIME_CURRENT_TIME);
+ g_hash_table_unref (request);
+
+ tp_account_channel_request_create_and_handle_channel_async (channel_request, NULL,
+ create_and_handle_cb, NULL);
+
+out:
+ g_object_unref (file);
+ g_clear_error (&error);
+}
+
+static void
+account_prepared_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpAccount *account = TP_ACCOUNT (source_object);
+ GError *error = NULL;
+
+ if (!tp_proxy_prepare_finish (account, result, &error))
+ {
+ g_print ("failed to prepare account: %s\n", error->message);
+ g_clear_error (&error);
+ getoutofhere ();
+ return;
+ }
+
+ got_account (account);
+}
+
+static void
+accept_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpFileTransferChannel *chan = TP_FILE_TRANSFER_CHANNEL (source);
+ GError *error = NULL;
+
+ if (!tp_file_transfer_channel_accept_file_finish (chan, result, &error))
+ {
+ g_printerr ("Failed to accept transfer: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ g_print ("saving file to: %s\n", file_path);
+ }
+}
+
+static void
+handle_channels_cb (TpSimpleHandler *handler,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ GList *requests_satisfied,
+ gint64 user_action_time,
+ TpHandleChannelsContext *context,
+ gpointer user_data)
+{
+ for (; channels != NULL; channels = channels->next)
+ {
+ TpFileTransferChannel *chan = channels->data;
+ GFile *file;
+
+ if (!TP_IS_FILE_TRANSFER_CHANNEL (chan))
+ continue;
+
+ g_signal_connect (chan, "notify::state",
+ G_CALLBACK (state_changed_cb), NULL);
+
+ g_print ("handling file transfer channel: %s\n",
+ tp_proxy_get_object_path (chan));
+
+ /* this is ugly, but it's only an example */
+ file_path = "/tmp/test-ft";
+ file = g_file_new_for_path (file_path);
+
+ tp_file_transfer_channel_accept_file_async (chan,
+ file, 0, accept_cb, NULL);
+ }
+
+ tp_handle_channels_context_accept (context);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ TpYtsAccountManager *am;
+ TpBaseClient *handler = NULL;
+ TpAccount *account = NULL;
+ gchar *path;
+
+ if (argc < 5
+ || !tp_dbus_check_valid_interface_name (argv[3], NULL)
+ || !tp_dbus_check_valid_interface_name (argv[4], NULL))
+ {
+ g_print ("usage: %s [account name] [contact id] [local service name] [remote service name] [file to send]\n", argv[0]);
+ return 1;
+ }
+
+ g_type_init ();
+
+ contact_id = argv[2];
+ local_service = argv[3];
+ remote_service = argv[4];
+ file_path = argv[5]; /* will be NULL when not provided because argv is NULL-terminated */
+
+ am = tp_yts_account_manager_dup ();
+
+ if (file_path != NULL)
+ {
+ /* sending */
+ path = g_strdup_printf ("%s%s", TP_ACCOUNT_OBJECT_PATH_BASE, argv[1]);
+ account = tp_yts_account_manager_ensure_account (am, path, NULL);
+ g_free (path);
+
+ tp_proxy_prepare_async (account, NULL, account_prepared_cb, NULL);
+ }
+ else
+ {
+ /* receiving */
+ handler = tp_simple_handler_new_with_factory (tp_proxy_get_factory (am),
+ TRUE, FALSE, local_service,
+ TRUE, handle_channels_cb, NULL, NULL);
+
+ tp_base_client_take_handler_filter (handler, tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
+ TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, FALSE,
+ TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, G_TYPE_STRING, local_service,
+ NULL));
+
+ tp_base_client_register (handler, NULL);
+
+ g_print ("waiting for a file transfer channel...\n");
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+
+ if (account != NULL)
+ g_object_unref (account);
+ if (handler != NULL)
+ g_object_unref (handler);
+ g_object_unref (am);
+
+ return 0;
+}