diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2011-08-19 12:42:36 +0200 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2011-08-19 12:42:36 +0200 |
commit | 8db9abc63ea8a6a6765c50aa499e802254620f51 (patch) | |
tree | 77953cd96c375e72c5fe1240971f03a9cf61c1ee | |
parent | c64e8956fbcef37e579a4e64e4e889acc1d80983 (diff) |
Use new factory APIs from telepathy-glib 0.15.5
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/client-helpers.c | 21 | ||||
-rw-r--r-- | src/client-helpers.h | 2 | ||||
-rw-r--r-- | src/client.c | 439 | ||||
-rw-r--r-- | src/service.c | 9 |
5 files changed, 142 insertions, 331 deletions
diff --git a/configure.ac b/configure.ac index ec12de9..01e200c 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,7 @@ IT_PROG_INTLTOOL([0.35.0]) PKG_CHECK_MODULES(SSH_CONTACT, [ - telepathy-glib >= 0.13.9 + telepathy-glib >= 0.15.5 glib-2.0 >= 2.28 gio-2.0 ]) diff --git a/src/client-helpers.c b/src/client-helpers.c index a6b060e..6fa5df3 100644 --- a/src/client-helpers.c +++ b/src/client-helpers.c @@ -100,9 +100,6 @@ create_tube_offer_cb (GObject *object, { GSimpleAsyncResult *simple = user_data; GError *error = NULL; - CreateTubeData *data; - - data = g_simple_async_result_get_op_res_gpointer (simple); if (!tp_stream_tube_channel_offer_finish (TP_STREAM_TUBE_CHANNEL (object), res, &error)) @@ -154,7 +151,7 @@ create_channel_cb (GObject *acr, } void -_client_create_tube_async (const gchar *account_path, +_client_create_tube_async (TpAccount *account, const gchar *contact_id, GAsyncReadyCallback callback, gpointer user_data) @@ -162,21 +159,7 @@ _client_create_tube_async (const gchar *account_path, GSimpleAsyncResult *simple; CreateTubeData *data; GHashTable *request; - TpDBusDaemon *dbus; - TpAccount *account = NULL; TpAccountChannelRequest *acr; - GError *error = NULL; - - dbus = tp_dbus_daemon_dup (&error); - if (dbus != NULL) - account = tp_account_new (dbus, account_path, &error); - if (account == NULL) - { - g_simple_async_report_gerror_in_idle (NULL, callback, user_data, error); - g_clear_error (&error); - tp_clear_object (&dbus); - return; - } simple = g_simple_async_result_new (NULL, callback, user_data, _client_create_tube_finish); @@ -201,8 +184,6 @@ _client_create_tube_async (const gchar *account_path, NULL, create_channel_cb, simple); g_hash_table_unref (request); - g_object_unref (dbus); - g_object_unref (account); g_object_unref (acr); } diff --git a/src/client-helpers.h b/src/client-helpers.h index ecfc5cf..d69be0f 100644 --- a/src/client-helpers.h +++ b/src/client-helpers.h @@ -26,7 +26,7 @@ G_BEGIN_DECLS -void _client_create_tube_async (const gchar *account_path, +void _client_create_tube_async (TpAccount *account, const gchar *contact_id, GAsyncReadyCallback callback, gpointer user_data); GSocketConnection *_client_create_tube_finish (GAsyncResult *res, diff --git a/src/client.c b/src/client.c index 29e221a..6bca25f 100644 --- a/src/client.c +++ b/src/client.c @@ -39,16 +39,10 @@ typedef struct gchar *login; gchar **ssh_opts; - GList *accounts; - guint n_readying_connections; - TpAccount *account; - TpChannel *channel; GSocketConnection *tube_connection; GSocketConnection *ssh_connection; - gboolean account_set:1; - gboolean contact_set:1; gboolean success:1; } ClientContext; @@ -198,343 +192,167 @@ OUT: } static void -start_tube (ClientContext *context) +start_tube (ClientContext *context, + TpContact *contact) { - if (!context->account_set || !context->contact_set) + TpAccount *account; + + account = tp_connection_get_account (tp_contact_get_connection (contact)); + + if (context->account_path == NULL || context->contact_id == NULL) { g_print ("\nTo avoid interactive mode, you can use that command:\n" "%s --account %s --contact %s\n", context->argv0, - context->account_path, context->contact_id); + tp_proxy_get_object_path (account), + tp_contact_get_identifier (contact)); } - _client_create_tube_async (context->account_path, - context->contact_id, create_tube_cb, context); + _client_create_tube_async (account, tp_contact_get_identifier (contact), + create_tube_cb, context); } static void -got_contacts_cb (TpConnection *connection, - guint n_contacts, - TpContact * const *contacts, - guint n_failed, - const TpHandle *failed, - const GError *error, - gpointer user_data, - GObject *weak_object) +choose_contact (ClientContext *context, + GList *accounts) { - ClientContext *context = user_data; - guint i; - GList *candidates = NULL, *l; - guint count = 0; + GPtrArray *candidates; + GList *l; + GString *text; gchar buffer[10]; gchar *str; - if (error != NULL) - { - throw_error (context, error); - return; - } - - /* Build a list of all contacts supporting StreamTube */ - for (i = 0; i < n_contacts; i++) - if (_capabilities_has_stream_tube (tp_contact_get_capabilities (contacts[i]))) - candidates = g_list_prepend (candidates, contacts[i]); - - if (candidates == NULL) - { - throw_error_message (context, "No suitable contact"); - return; - } - - /* Ask the user which candidate to use */ - for (l = candidates; l != NULL; l = l->next) - { - TpContact *contact = l->data; - - g_print ("%d) %s (%s)\n", ++count, tp_contact_get_alias (contact), - tp_contact_get_identifier (contact)); - } - - g_print ("Which contact to use? "); - str = fgets (buffer, sizeof (buffer), stdin); - if (str != NULL) + text = g_string_new (NULL); + candidates = g_ptr_array_new_with_free_func (g_object_unref); + for (l = accounts; l != NULL; l = l->next) { - str[strlen (str) - 1] = '\0'; - l = g_list_nth (candidates, atoi (str) - 1); - } - if (l == NULL) - { - throw_error_message (context, "Invalid contact number"); - return; - } - - context->contact_id = g_strdup (tp_contact_get_identifier (l->data)); - start_tube (context); - - g_list_free (candidates); -} - -static void -stored_channel_prepare_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) -{ - ClientContext *context = user_data; - TpChannel *channel = TP_CHANNEL (object); - TpConnection *connection; - TpContactFeature features[] = { TP_CONTACT_FEATURE_ALIAS, - TP_CONTACT_FEATURE_CAPABILITIES }; - const TpIntSet *set; - GArray *handles; - GError *error = NULL; - - if (!tp_proxy_prepare_finish (channel, res, &error)) - { - throw_error (context, error); - g_clear_error (&error); - return; - } - - connection = tp_channel_borrow_connection (channel); - set = tp_channel_group_get_members (channel); - handles = tp_intset_to_array (set); - - if (handles->len <= 0) - { - throw_error_message(context, "No contacts available"); - return; - } - - tp_connection_get_contacts_by_handle (connection, handles->len, - (TpHandle *) handles->data, G_N_ELEMENTS (features), features, - got_contacts_cb, context, NULL, NULL); - - g_array_unref (handles); -} - -static void -ensure_stored_channel_cb (TpConnection *connection, - gboolean yours, - const gchar *channel_path, - GHashTable *properties, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - ClientContext *context = user_data; - TpChannel *channel; - GQuark features[] = { TP_CHANNEL_FEATURE_GROUP, 0 }; - GError *err = NULL; - - if (error != NULL) - { - throw_error (context, error); - return; - } + TpAccount *account = l->data; + TpConnection *connection; + TpCapabilities *caps; + GPtrArray *contacts; + GString *subtext; + gboolean found = FALSE; + guint i; - channel = tp_channel_new_from_properties (connection, channel_path, - properties, &err); - if (channel == NULL) - { - throw_error (context, err); - g_clear_error (&err); - return; - } + connection = tp_account_get_connection (account); + if (connection == NULL) + continue; - tp_proxy_prepare_async (TP_PROXY (channel), features, - stored_channel_prepare_cb, context); + caps = tp_connection_get_capabilities (connection); + if (!_capabilities_has_stream_tube (caps)) + continue; - g_object_unref (channel); -} + subtext = g_string_new (NULL); + contacts = tp_connection_dup_contact_list (connection); + for (i = 0; i < contacts->len; i++) + { + TpContact *contact = g_ptr_array_index (contacts, i); -static void -chooser_contact (ClientContext *context) -{ - TpConnection *connection; - GHashTable *request; + caps = tp_contact_get_capabilities (contact); + if (!_capabilities_has_stream_tube (caps)) + continue; - /* If a contact ID was passed in the options, use it */ - if (context->contact_set) - { - g_assert (context->contact_id != NULL); - start_tube (context); - return; - } + if (context->contact_id != NULL && + tp_strdiff (context->contact_id, + tp_contact_get_identifier (contact))) + continue; - /* Otherwise, we'll get TpContact objects for all stored contacts on that - * account. */ - request = tp_asv_new ( - TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, - TP_IFACE_CHANNEL_TYPE_CONTACT_LIST, - TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, - TP_HANDLE_TYPE_LIST, - TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, - "stored", - NULL); - - connection = tp_account_get_connection (context->account); - tp_cli_connection_interface_requests_call_ensure_channel (connection, -1, - request, ensure_stored_channel_cb, context, NULL, NULL); - - g_hash_table_unref (request); -} + found = TRUE; + g_ptr_array_add (candidates, g_object_ref (contact)); -static void -chooser_account (ClientContext *context) -{ - GList *l; - guint count = 0; - gchar buffer[10]; - gchar *str; + g_string_append_printf (subtext, " %d) %s (%s)\n", candidates->len, + tp_contact_get_alias (contact), + tp_contact_get_identifier (contact)); + } + g_ptr_array_unref (contacts); - if (context->accounts == NULL) - { - throw_error_message (context, "No suitable account"); - return; + if (found) + { + g_string_append_printf (text, + "Account %s (%s):\n%s", + tp_account_get_display_name (l->data), + tp_account_get_protocol (l->data), + subtext->str); + } + g_string_free (subtext, TRUE); } - if (context->account_set) + if (candidates->len == 0) { - g_assert (context->account != NULL); - g_assert (context->account_path != NULL); - chooser_contact (context); - return; + throw_error_message (context, "No suitable contact"); + goto OUT; } - for (l = context->accounts; l != NULL; l = l->next) + if (candidates->len == 1 && context->contact_id != NULL) { - g_print ("%d) %s (%s)\n", ++count, - tp_account_get_display_name (l->data), - tp_account_get_protocol (l->data)); + start_tube (context, g_ptr_array_index (candidates, 0)); + goto OUT; } - g_print ("Which account to use? "); + g_print ("%sWhich contact to use? ", text->str); str = fgets (buffer, sizeof (buffer), stdin); if (str != NULL) { - str[strlen (str) - 1] = '\0'; - l = g_list_nth (context->accounts, atoi (str) - 1); - } - if (l == NULL) - { - throw_error_message (context, "Invalid account number"); - return; - } - - context->account = g_object_ref (l->data); - context->account_path = g_strdup (tp_proxy_get_object_path (context->account)); - - chooser_contact (context); -} + guint i; -static void -connection_prepare_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) -{ - TpConnection *connection = TP_CONNECTION (object); - ClientContext *context = user_data; + str[strlen (str) - 1] = '\0'; + i = atoi (str) - 1; - if (!tp_proxy_prepare_finish (TP_PROXY (connection), res, NULL) || - !_capabilities_has_stream_tube (tp_connection_get_capabilities (connection))) - { - GList *l; - - /* Remove the account that has that connection from the list */ - for (l = context->accounts; l != NULL; l = l->next) - if (tp_account_get_connection (l->data) == connection) - { - g_object_unref (l->data); - context->accounts = g_list_delete_link (context->accounts, l); - break; - } + if (i < candidates->len) + { + start_tube (context, g_ptr_array_index (candidates, i)); + goto OUT; + } } - if (--context->n_readying_connections == 0) - chooser_account (context); + throw_error_message (context, "Invalid contact number"); + +OUT: + g_ptr_array_unref (candidates); + g_string_free (text, TRUE); } static void -account_manager_prepare_cb (GObject *object, +account_prepared_cb (GObject *object, GAsyncResult *res, gpointer user_data) { - TpAccountManager *manager = TP_ACCOUNT_MANAGER (object); + TpAccount *account = TP_ACCOUNT (object); ClientContext *context = user_data; - GList *l, *next; + GList *accounts; GError *error = NULL; - if (!tp_proxy_prepare_finish (TP_PROXY (manager), res, &error)) + if (!tp_proxy_prepare_finish (TP_PROXY (account), res, &error)) { throw_error (context, error); g_clear_error (&error); return; } - /* We want to list all accounts which has a connection that have StreamTube - * support. So first we prepare all connections, and we keep in - * context->accounts those that are suitable. */ - - context->accounts = tp_account_manager_get_valid_accounts (manager); - g_list_foreach (context->accounts, (GFunc) g_object_ref, NULL); - - for (l = context->accounts; l != NULL; l = next) - { - GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; - TpAccount *account = l->data; - TpConnection *connection; - - next = l->next; - - connection = tp_account_get_connection (account); - if (connection == NULL) - { - g_object_unref (account); - context->accounts = g_list_delete_link (context->accounts, l); - continue; - } - - context->n_readying_connections++; - tp_proxy_prepare_async (TP_PROXY (connection), features, - connection_prepare_cb, context); - } - - if (context->n_readying_connections == 0) - chooser_account (context); + accounts = g_list_prepend (NULL, account); + choose_contact (context, accounts); + g_list_free (accounts); } static void -account_prepare_cb (GObject *object, +account_manager_prepared_cb (GObject *object, GAsyncResult *res, gpointer user_data) { - TpAccount *account = TP_ACCOUNT (object); + TpAccountManager *manager = TP_ACCOUNT_MANAGER (object); ClientContext *context = user_data; - GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; - TpConnection *connection; + GList *accounts; GError *error = NULL; - /* We are in the case where an account was specified in options, so we have - * only one candidate, if that accounts has no connection or the connection - * has no StreamTube support, we'll fail. */ - - if (!tp_proxy_prepare_finish (TP_PROXY (account), res, &error)) + if (!tp_proxy_prepare_finish (TP_PROXY (manager), res, &error)) { throw_error (context, error); + g_clear_error (&error); return; } - connection = tp_account_get_connection (account); - if (connection == NULL) - { - throw_error_message (context, "Account not online"); - return; - } - - /* Prepare account's connection with caps feature */ - context->accounts = g_list_prepend (NULL, g_object_ref (account)); - context->n_readying_connections = 1; - tp_proxy_prepare_async (TP_PROXY (connection), features, - connection_prepare_cb, context); + accounts = tp_account_manager_get_valid_accounts (manager); + choose_contact (context, accounts); + g_list_free (accounts); } static void @@ -547,10 +365,6 @@ client_context_clear (ClientContext *context) g_free (context->login); g_strfreev (context->ssh_opts); - g_list_foreach (context->accounts, (GFunc) g_object_unref, NULL); - g_list_free (context->accounts); - tp_clear_object (&context->account); - tp_clear_object (&context->channel); tp_clear_object (&context->tube_connection); tp_clear_object (&context->ssh_connection); @@ -559,7 +373,8 @@ client_context_clear (ClientContext *context) int main (gint argc, gchar *argv[]) { - TpDBusDaemon *dbus = NULL; + TpDBusDaemon *dbus; + TpSimpleClientFactory *factory; GError *error = NULL; ClientContext context = { 0, }; GOptionContext *optcontext; @@ -595,49 +410,61 @@ main (gint argc, gchar *argv[]) } g_option_context_free (optcontext); + context.argv0 = g_strdup (argv[0]); g_set_application_name (PACKAGE_NAME); + tp_debug_set_flags (g_getenv ("SSH_CONTACT_DEBUG")); dbus = tp_dbus_daemon_dup (&error); if (dbus == NULL) goto OUT; - context.argv0 = g_strdup (argv[0]); + /* Create a factory and define the features we need */ + factory = (TpSimpleClientFactory *) tp_automatic_client_factory_new (dbus); + tp_simple_client_factory_add_account_features_varargs (factory, + TP_ACCOUNT_FEATURE_CONNECTION, + 0); + tp_simple_client_factory_add_connection_features_varargs (factory, + TP_CONNECTION_FEATURE_CONTACT_LIST, + TP_CONNECTION_FEATURE_CAPABILITIES, + 0); + tp_simple_client_factory_add_contact_features_varargs (factory, + TP_CONTACT_FEATURE_ALIAS, + TP_CONTACT_FEATURE_CAPABILITIES, + TP_CONTACT_FEATURE_INVALID); + g_object_unref (dbus); + + /* If user gave an account path, prepare only that account, otherwise prepare + * the whole account manager. */ if (context.account_path != NULL) - context.account_set = TRUE; - if (context.contact_id != NULL) - context.contact_set = TRUE; - - /* If an account id was specified in options, then prepare it, otherwise - * we get the account manager to get a list of all accounts */ - if (context.account_set) { - if (!g_str_has_prefix (context.account_path, TP_ACCOUNT_OBJECT_PATH_BASE)) - { - gchar *account_id = context.account_path; + TpAccount *account; + GArray *features; - context.account_path = g_strconcat (TP_ACCOUNT_OBJECT_PATH_BASE, - account_id, NULL); + account = tp_simple_client_factory_ensure_account (factory, + context.account_path, NULL, &error); + if (account == NULL) + goto OUT; - g_free (account_id); - } + features = tp_simple_client_factory_dup_account_features (factory, + account); - context.account = tp_account_new (dbus, context.account_path, &error); - if (context.account == NULL) - goto OUT; + tp_proxy_prepare_async (account, (GQuark *) features->data, + account_prepared_cb, &context); - tp_proxy_prepare_async (TP_PROXY (context.account), NULL, - account_prepare_cb, &context); + g_object_unref (account); + g_array_unref (features); } else { TpAccountManager *manager; - manager = tp_account_manager_new (dbus); - tp_proxy_prepare_async (TP_PROXY (manager), NULL, - account_manager_prepare_cb, &context); + manager = tp_account_manager_new_with_factory (factory); + tp_proxy_prepare_async (manager, NULL, + account_manager_prepared_cb, &context); g_object_unref (manager); } + g_object_unref (factory); context.loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (context.loop); @@ -650,10 +477,8 @@ OUT: g_debug ("Error: %s", error->message); } - tp_clear_object (&dbus); g_clear_error (&error); client_context_clear (&context); return context.success ? EXIT_SUCCESS : EXIT_FAILURE; } - diff --git a/src/service.c b/src/service.c index f440f2f..5134497 100644 --- a/src/service.c +++ b/src/service.c @@ -149,18 +149,22 @@ int main (gint argc, gchar *argv[]) { TpDBusDaemon *dbus = NULL; + TpSimpleClientFactory *factory = NULL; TpBaseClient *client = NULL; gboolean success = TRUE; GError *error = NULL; g_type_init (); + tp_debug_set_flags (g_getenv ("SSH_CONTACT_DEBUG")); + dbus = tp_dbus_daemon_dup (&error); if (dbus == NULL) goto OUT; - client = tp_simple_handler_new (dbus, FALSE, FALSE, "SSHContact", - FALSE, got_channel_cb, NULL, NULL); + factory = (TpSimpleClientFactory *) tp_automatic_client_factory_new (dbus); + client = tp_simple_handler_new_with_factory (factory, FALSE, FALSE, + "SSHContact", FALSE, got_channel_cb, NULL, NULL); tp_base_client_take_handler_filter (client, tp_asv_new ( TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, @@ -189,6 +193,7 @@ OUT: tp_clear_pointer (&loop, g_main_loop_unref); tp_clear_object (&dbus); + tp_clear_object (&factory); tp_clear_object (&client); g_clear_error (&error); |