diff options
author | Rob Staudinger <robsta@linux.intel.com> | 2012-02-14 10:55:12 +0100 |
---|---|---|
committer | Rob Staudinger <robsta@linux.intel.com> | 2012-02-14 10:55:12 +0100 |
commit | df8e6e7904be4f7ea632a956682eeb5471a5a95c (patch) | |
tree | 212a4ba0bfd4f7ce4273f1e2d17e22b92ff26a46 | |
parent | 8ffc4a2d4eb38f5ce99ee765ca4d80a705059332 (diff) |
file-transfer: Pass sender service-id in file metadata
The sender needs to add its own service-id to the metadata when
transferring a file, so the recipient can look up who it is coming
from.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=45733
-rw-r--r-- | examples/file-transfer.c | 20 | ||||
-rw-r--r-- | ytstenut/yts-client.c | 57 | ||||
-rw-r--r-- | ytstenut/yts-outgoing-file-internal.h | 1 | ||||
-rw-r--r-- | ytstenut/yts-outgoing-file.c | 109 | ||||
-rw-r--r-- | ytstenut/yts-outgoing-file.h | 1 |
5 files changed, 153 insertions, 35 deletions
diff --git a/examples/file-transfer.c b/examples/file-transfer.c index da95e28..cccd021 100644 --- a/examples/file-transfer.c +++ b/examples/file-transfer.c @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Intel Corp. + * Copyright © 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 @@ -162,7 +162,7 @@ run_client (bool p2p, roster = yts_client_get_roster (client); g_signal_connect (roster, "service-added", - G_CALLBACK (_client_roster_service_added), (void *) path); + G_CALLBACK (_client_roster_service_added), (gpointer) path); yts_client_connect (client); @@ -235,8 +235,8 @@ static int run_server (bool p2p, char const *path) { - YtsClient *client; - GMainLoop *mainloop; + YtsClient *client; + GMainLoop *mainloop; if (p2p) client = yts_client_new_p2p (SERVER_UID); @@ -250,8 +250,7 @@ run_server (bool p2p, g_signal_connect (client, "disconnected", G_CALLBACK (_server_disconnected), NULL); g_signal_connect (client, "incoming-file", - G_CALLBACK (_server_incoming_file), (void *) path); - + G_CALLBACK (_server_incoming_file), (gpointer) path); yts_client_connect (client); @@ -284,7 +283,7 @@ main (int argc, g_type_init (); - context = g_option_context_new ("- Ytstenut file-transfer example"); + context = g_option_context_new ("- Ytstenut echo example"); g_option_context_add_main_entries (context, entries, NULL); g_option_context_parse (context, &argc, &argv, &error); if (error) { @@ -292,11 +291,14 @@ main (int argc, g_clear_error (&error); } - if (client) { + if (NULL == path) { + g_critical ("No file specified, see --help"); + ret = -1; + } else if (client) { g_message ("Running as client ..."); ret = run_client (p2p, path); } else if (server) { - g_message ("Running as server ... "); + g_message ("Running as server ..."); ret = run_server (p2p, path); } else { g_warning ("%s : Not running as server or client, quitting", G_STRLOC); diff --git a/ytstenut/yts-client.c b/ytstenut/yts-client.c index 79aa44b..2eb9101 100644 --- a/ytstenut/yts-client.c +++ b/ytstenut/yts-client.c @@ -790,6 +790,27 @@ yts_client_setup_debug (YtsClient *self) g_free (busname); } +static char const * +extract_remote_service_id (YtsClient *self, + GHashTable *channel_properties) +{ + GHashTable *metadata; + char const *remote_service_id = NULL; + + metadata = tp_asv_get_boxed (channel_properties, + TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_METADATA, + TP_HASH_TYPE_METADATA); + + if (metadata) { + char **values = g_hash_table_lookup (metadata, (gpointer) "FromService"); + if (values && values[0]) { + remote_service_id = values[0]; + } + } + + return remote_service_id; +} + static void _file_handler_handle_channels (TpSimpleHandler *handler, TpAccount *account, @@ -811,29 +832,36 @@ _file_handler_handle_channels (TpSimpleHandler *handler, TpFileTransferChannel *channel = iter->data; char const *remote_contact_id = tp_channel_get_initiator_identifier (TP_CHANNEL (channel)); GHashTable *props = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel)); - char const *const key = "org.freedesktop.Telepathy.Channel.Interface.FileTransfer.Metadata.ServiceName"; - char const *remote_service_id = tp_asv_get_string (props, key); + char const *remote_service_id; + YtsService *service = NULL; - YtsService *service = yts_roster_find_service_by_id (priv->roster, - remote_contact_id, - remote_service_id); + remote_service_id = extract_remote_service_id (self, props); + service = yts_roster_find_service_by_id (priv->roster, + remote_contact_id, + remote_service_id); + if (service) { - YtsIncomingFile *incoming = yts_incoming_file_new (channel); + YtsIncomingFile *incoming = yts_incoming_file_new (channel); + GError *error = NULL; - GError *error = NULL; + if (g_initable_init (G_INITABLE (incoming), NULL, &error)) { - if (g_initable_init (G_INITABLE (incoming), NULL, &error)) { + g_signal_emit (self, signals[INCOMING_FILE], 0, + service, props, incoming); - g_signal_emit (self, signals[INCOMING_FILE], 0, - service, props, incoming); + } else { - } else { + // TODO if (error) {} + g_critical ("Handling incoming file failed -- no handler"); + } + g_clear_error (&error); + g_object_unref (incoming); + + } else { // TODO if (error) {} - g_critical ("Handling incoming file failed"); + g_critical ("Handling incoming file failed -- no recipient service"); } - - g_object_unref (incoming); } tp_handle_channels_context_accept (context); @@ -1020,6 +1048,7 @@ _roster_send_file (YtsRoster *roster, recipient_service_id = yts_service_get_id (service); outgoing = yts_outgoing_file_new (priv->tp_account, file, + priv->service_id, recipient_contact_id, recipient_service_id, description); diff --git a/ytstenut/yts-outgoing-file-internal.h b/ytstenut/yts-outgoing-file-internal.h index f350f7c..3eec3e2 100644 --- a/ytstenut/yts-outgoing-file-internal.h +++ b/ytstenut/yts-outgoing-file-internal.h @@ -47,6 +47,7 @@ typedef struct { YtsOutgoingFile * yts_outgoing_file_new (TpAccount *tp_account, GFile *file, + char const *sender_service_id, char const *recipient_contact_id, char const *recipient_service_id, char const *description); diff --git a/ytstenut/yts-outgoing-file.c b/ytstenut/yts-outgoing-file.c index 034517d..3a1dfb2 100644 --- a/ytstenut/yts-outgoing-file.c +++ b/ytstenut/yts-outgoing-file.c @@ -67,7 +67,8 @@ enum { PROP_TP_ACCOUNT, PROP_DESCRIPTION, PROP_RECIPIENT_CONTACT_ID, - PROP_RECIPIENT_SERVICE_ID + PROP_RECIPIENT_SERVICE_ID, + PROP_SENDER_SERVICE_ID }; typedef struct { @@ -76,6 +77,7 @@ typedef struct { GFile *file; char *recipient_contact_id; char *recipient_service_id; + char *sender_service_id; char *description; float progress; /* Data */ @@ -172,6 +174,15 @@ validate (YtsOutgoingFile *self, return false; } + if (NULL == priv->sender_service_id) { + if (error_out) { + *error_out = g_error_new (YTS_OUTGOING_FILE_ERROR, + YTS_OUTGOING_FILE_ERROR_NO_SENDER_SERVICE, + "No sender service specified for file transfer"); + } + return false; + } + return true; } @@ -343,6 +354,8 @@ _initable_init (GInitable *initable, char const *name; char const *mimetype; GTimeVal mtime; + GHashTable *metadata; + char **values; GHashTable *request; TpAccountChannelRequest *channel_request; GError *error = NULL; @@ -373,20 +386,62 @@ _initable_init (GInitable *initable, g_file_info_get_modification_time (info, &mtime); priv->size = g_file_info_get_size (info); + metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + values = g_new0 (char *, 2); + values[0] = priv->sender_service_id; + g_hash_table_insert (metadata, + g_strdup ("FromService"), + values); + /* Now we have everything prepared to continue, let's create the * Ytstenut channel handler with service name specified. */ 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, priv->recipient_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, priv->description, - TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, G_TYPE_STRING, name, - TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_INITIAL_OFFSET, G_TYPE_UINT64, (guint64) 0, - TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, G_TYPE_UINT64, (guint64) priv->size, - /* here is the remote service */ - TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, G_TYPE_STRING, priv->recipient_service_id, + 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, + priv->recipient_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, + priv->description, + + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, + G_TYPE_STRING, + name, + + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_INITIAL_OFFSET, + G_TYPE_UINT64, + (guint64) 0, + + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, + G_TYPE_UINT64, + (guint64) priv->size, + + /* Here is the remote service */ + TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, + G_TYPE_STRING, + priv->recipient_service_id, + + /* And include our own service name. FIXME this should be a define. */ + TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_METADATA, + TP_HASH_TYPE_METADATA, + metadata, + NULL); channel_request = tp_account_channel_request_new ( @@ -436,6 +491,9 @@ _get_property (GObject *object, case PROP_RECIPIENT_SERVICE_ID: g_value_set_string (value, priv->recipient_service_id); break; + case PROP_SENDER_SERVICE_ID: + g_value_set_string (value, priv->sender_service_id); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -476,6 +534,10 @@ _set_property (GObject *object, /* Construct-only */ priv->recipient_service_id = g_value_dup_string (value); break; + case PROP_SENDER_SERVICE_ID: + /* Construct-only */ + priv->sender_service_id = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -521,6 +583,11 @@ _finalize (GObject *object) priv->recipient_service_id = NULL; } + if (priv->sender_service_id) { + g_free (priv->sender_service_id); + priv->sender_service_id = NULL; + } + if (priv->description) { g_free (priv->description); priv->description = NULL; @@ -610,6 +677,22 @@ yts_outgoing_file_class_init (YtsOutgoingFileClass *klass) g_object_class_install_property (object_class, PROP_RECIPIENT_SERVICE_ID, pspec); + + /** + * YtsOutgoingFile:sender-service-id: + * + * Service ID of the file sender. + * + * Since: 0.4 + */ + pspec = g_param_spec_string ("sender-service-id", "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_SENDER_SERVICE_ID, + pspec); } static void @@ -620,6 +703,7 @@ yts_outgoing_file_init (YtsOutgoingFile *self) YtsOutgoingFile * yts_outgoing_file_new (TpAccount *tp_account, GFile *file, + char const *sender_service_id, char const *recipient_contact_id, char const *recipient_service_id, char const *description) @@ -627,6 +711,7 @@ yts_outgoing_file_new (TpAccount *tp_account, return g_object_new (YTS_TYPE_OUTGOING_FILE, "tp-account", tp_account, "file", file, + "sender-service-id", sender_service_id, "recipient-contact-id", recipient_contact_id, "recipient-service-id", recipient_service_id, "description", description, diff --git a/ytstenut/yts-outgoing-file.h b/ytstenut/yts-outgoing-file.h index a81390d..7bc22d3 100644 --- a/ytstenut/yts-outgoing-file.h +++ b/ytstenut/yts-outgoing-file.h @@ -47,6 +47,7 @@ enum { YTS_OUTGOING_FILE_ERROR_READ_FAILED, YTS_OUTGOING_FILE_ERROR_NO_RECIPIENT_CONTACT, YTS_OUTGOING_FILE_ERROR_NO_RECIPIENT_SERVICE, + YTS_OUTGOING_FILE_ERROR_NO_SENDER_SERVICE, YTS_OUTGOING_FILE_ERROR_CHANNEL_FAILED, YTS_OUTGOING_FILE_ERROR_TRANSFER_FAILED, YTS_OUTGOING_FILE_ERROR_LOCAL, |