summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2009-08-26 13:05:44 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2009-08-26 13:05:45 +0100
commit65f2c739ddbdfeb2ab9a4f0b38b4e7d906b9abcb (patch)
treee9c44fd630d082cef512456e071d75de95c62ea0
parent07248b054fe4a78166de01d66029f3151b012890 (diff)
downloadtelepathy-mission-control-65f2c739ddbdfeb2ab9a4f0b38b4e7d906b9abcb.tar.gz
mcd-account: refactored set_parameters to be async and iteratively set params
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/mcd-account-connection.c28
-rw-r--r--src/mcd-account-manager.c99
-rw-r--r--src/mcd-account-priv.h24
-rw-r--r--src/mcd-account.c976
-rw-r--r--src/mcd-account.h17
5 files changed, 781 insertions, 363 deletions
diff --git a/src/mcd-account-connection.c b/src/mcd-account-connection.c
index 37cbd869..ec119d7f 100644
--- a/src/mcd-account-connection.c
+++ b/src/mcd-account-connection.c
@@ -51,29 +51,37 @@ _mcd_account_connection_context_free (McdAccountConnectionContext *c)
g_free (c);
}
-void
-_mcd_account_connection_begin (McdAccount *account)
+static void
+connection_begin_dup_params_cb (McdAccount *account, GHashTable *params,
+ gpointer user_data)
{
McdAccountConnectionContext *ctx;
- /* check whether a connection process is already ongoing */
- if (_mcd_account_get_connection_context (account) != NULL)
- {
- DEBUG ("already trying to connect");
- return;
- }
-
/* get account params */
/* create dynamic params HT */
/* run the handlers */
ctx = g_malloc (sizeof (McdAccountConnectionContext));
ctx->i_filter = 0;
- ctx->params = _mcd_account_dup_parameters (account);
+
+ ctx->params = params;
g_assert (ctx->params != NULL);
_mcd_account_set_connection_context (account, ctx);
mcd_account_connection_proceed (account, TRUE);
}
+void
+_mcd_account_connection_begin (McdAccount *account)
+{
+ /* check whether a connection process is already ongoing */
+ if (_mcd_account_get_connection_context (account) != NULL)
+ {
+ DEBUG ("already trying to connect");
+ return;
+ }
+
+ _mcd_account_dup_parameters (account, connection_begin_dup_params_cb, NULL);
+}
+
void
mcd_account_connection_proceed (McdAccount *account, gboolean success)
{
diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c
index 2bb85f61..84e5090d 100644
--- a/src/mcd-account-manager.c
+++ b/src/mcd-account-manager.c
@@ -115,6 +115,9 @@ typedef struct
McdGetAccountCb callback;
gpointer user_data;
GDestroyNotify destroy;
+
+ gboolean ok;
+ GError *error;
} McdCreateAccountData;
enum
@@ -346,6 +349,9 @@ mcd_create_account_data_free (McdCreateAccountData *cad)
g_hash_table_unref (cad->properties);
}
+ if (G_UNLIKELY (cad->error))
+ g_error_free (cad->error);
+
g_slice_free (McdCreateAccountData, cad);
}
@@ -408,44 +414,22 @@ create_account_with_properties_cb (McdAccountManager *account_manager,
}
static void
-complete_account_creation (McdAccount *account,
- const GError *cb_error,
- gpointer user_data)
+complete_account_creation_finish (McdAccount *account, gboolean valid,
+ gpointer user_data)
{
- McdCreateAccountData *cad = user_data;
+ McdCreateAccountData *cad = (McdCreateAccountData *) user_data;
McdAccountManager *account_manager;
- GError *error = NULL;
- gboolean ok;
account_manager = cad->account_manager;
- if (G_UNLIKELY (cb_error))
- {
- cad->callback (account_manager, account, cb_error, cad->user_data);
- mcd_create_account_data_free (cad);
- return;
- }
-
- ok = _mcd_account_set_parameters (account, cad->parameters, NULL, NULL,
- &error);
- if (ok && cad->properties != NULL)
+ if (!valid)
{
- ok = set_new_account_properties (account, cad->properties, &error);
- }
-
- if (ok)
- {
- add_account (account_manager, account);
-
- if (!mcd_account_check_validity (account))
- {
- ok = FALSE;
- g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ cad->ok = FALSE;
+ g_set_error (&cad->error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
"The supplied CM parameters were not valid");
- }
}
- if (!ok)
+ if (!cad->ok)
{
mcd_account_delete (account, NULL, NULL);
g_object_unref (account);
@@ -454,15 +438,65 @@ complete_account_creation (McdAccount *account,
mcd_account_manager_write_conf_async (account_manager, NULL, NULL);
- cad->callback (account_manager, account, error, cad->user_data);
- if (G_UNLIKELY (error))
- g_error_free (error);
+ if (cad->callback != NULL)
+ cad->callback (account_manager, account, cad->error, cad->user_data);
mcd_create_account_data_free (cad);
if (account != NULL)
{
g_object_unref (account);
}
+
+}
+
+static void
+complete_account_creation_set_cb (McdAccount *account, GPtrArray *not_yet,
+ const GError *set_error, gpointer user_data)
+{
+ McdCreateAccountData *cad = user_data;
+ McdAccountManager *account_manager;
+ cad->ok = (set_error == NULL);
+
+ account_manager = cad->account_manager;
+
+ if (cad->ok && cad->properties != NULL)
+ {
+ cad->ok = set_new_account_properties (account, cad->properties, &cad->error);
+ }
+
+ if (cad->ok)
+ {
+ add_account (account_manager, account);
+ mcd_account_check_validity (account, complete_account_creation_finish, cad);
+ }
+ else
+ {
+ complete_account_creation_finish (account, TRUE, cad);
+ }
+
+ g_ptr_array_foreach (not_yet, (GFunc) g_free, NULL);
+ g_ptr_array_free (not_yet, TRUE);
+}
+
+static void
+complete_account_creation (McdAccount *account,
+ const GError *cb_error,
+ gpointer user_data)
+{
+ McdCreateAccountData *cad = user_data;
+ McdAccountManager *account_manager;
+
+ account_manager = cad->account_manager;
+ if (G_UNLIKELY (cb_error))
+ {
+ cad->callback (account_manager, account, cb_error, cad->user_data);
+ mcd_create_account_data_free (cad);
+ return;
+ }
+
+ _mcd_account_set_parameters (account, cad->parameters, NULL,
+ complete_account_creation_set_cb,
+ cad);
}
static gchar *
@@ -566,6 +600,7 @@ _mcd_account_manager_create_account (McdAccountManager *account_manager,
cad->callback = callback;
cad->user_data = user_data;
cad->destroy = destroy;
+ cad->error = NULL;
_mcd_account_load (account, complete_account_creation, cad);
}
else
diff --git a/src/mcd-account-priv.h b/src/mcd-account-priv.h
index af4d130f..b5e2f39a 100644
--- a/src/mcd-account-priv.h
+++ b/src/mcd-account-priv.h
@@ -43,11 +43,17 @@ G_GNUC_INTERNAL void _mcd_account_maybe_autoconnect (McdAccount *account);
G_GNUC_INTERNAL void _mcd_account_connect (McdAccount *account,
GHashTable *params);
-G_GNUC_INTERNAL gboolean _mcd_account_set_parameters (McdAccount *account,
- GHashTable *params,
- const gchar **unset,
- GPtrArray *not_yet,
- GError **error);
+
+typedef void (McdAccountSetParametersCb) (McdAccount *account,
+ GPtrArray *not_yet,
+ const GError *error,
+ gpointer user_data);
+
+G_GNUC_INTERNAL void _mcd_account_set_parameters (McdAccount *account,
+ GHashTable *params,
+ const gchar **unset,
+ McdAccountSetParametersCb callback,
+ gpointer user_data);
G_GNUC_INTERNAL void _mcd_account_request_temporary_presence (McdAccount *self,
TpConnectionPresenceType type, const gchar *status);
@@ -152,7 +158,13 @@ void _mcd_account_set_connection_context (McdAccount *self,
G_GNUC_INTERNAL void _mcd_account_connection_context_free
(McdAccountConnectionContext *c);
-G_GNUC_INTERNAL GHashTable *_mcd_account_dup_parameters (McdAccount *account);
+typedef void (*McdAccountDupParametersCb) (McdAccount *account,
+ GHashTable *params,
+ gpointer user_data);
+
+G_GNUC_INTERNAL void _mcd_account_dup_parameters (McdAccount *account,
+ McdAccountDupParametersCb callback,
+ gpointer user_data);
extern const McdDBusProp account_conditions_properties[];
diff --git a/src/mcd-account.c b/src/mcd-account.c
index 9a3e5ab7..427b2a34 100644
--- a/src/mcd-account.c
+++ b/src/mcd-account.c
@@ -342,6 +342,14 @@ set_parameter (McdAccount *account, const gchar *name, const GValue *value,
McdAccountPrivate *priv = account->priv;
gchar key[MAX_KEY_LENGTH];
gchar buf[21]; /* enough for '-' + the 19 digits of 2**63 + '\0' */
+ const TpConnectionManagerParam *param;
+ gboolean is_secret = FALSE;
+
+ param = mcd_manager_get_protocol_param (priv->manager,
+ priv->protocol_name, name);
+
+ if (param != NULL && param->flags & TP_CONN_MGR_PARAM_FLAG_SECRET)
+ is_secret = TRUE;
g_snprintf (key, sizeof (key), "param-%s", name);
@@ -428,138 +436,184 @@ out:
}
}
-static gboolean
-get_parameter (McdAccount *account, const gchar *name, GValue *value)
+static GType mc_param_type (const TpConnectionManagerParam *param);
+
+
+static void
+get_parameter (McdAccount *account, const gchar *name,
+ McdAccountGetParameterCb callback, gpointer user_data)
{
McdAccountPrivate *priv = account->priv;
gchar key[MAX_KEY_LENGTH];
+ const TpConnectionManagerParam *param;
+ gboolean is_secret = FALSE;
+ GError *error = NULL;
+ GValue *value = NULL;
+ GType type;
+
+ gchar *v_string = NULL;
+ gint64 v_int = 0;
+ guint64 v_uint = 0;
+ gboolean v_bool = FALSE;
+ double v_double = 0.0;
+
+ param = mcd_manager_get_protocol_param (priv->manager,
+ priv->protocol_name, name);
+
+ if (param != NULL && param->flags & TP_CONN_MGR_PARAM_FLAG_SECRET)
+ is_secret = TRUE;
g_snprintf (key, sizeof (key), "param-%s", name);
if (!g_key_file_has_key (priv->keyfile, priv->unique_name, key, NULL))
- return FALSE;
+ goto error;
+
+ type = mc_param_type (param);
- if (value)
+ switch (type)
{
- gchar *v_string = NULL;
- gint64 v_int = 0;
- guint64 v_uint = 0;
- gboolean v_bool = FALSE;
- double v_double = 0.0;
+ case G_TYPE_STRING:
+ v_string = g_key_file_get_string (priv->keyfile, priv->unique_name,
+ key, NULL);
+ value = tp_g_value_slice_new_take_string (v_string);
+ break;
+
+ case G_TYPE_INT:
+ v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
+ key, NULL);
+ value = tp_g_value_slice_new_int (v_int);
+ break;
+
+ case G_TYPE_INT64:
+ v_int = tp_g_key_file_get_int64 (priv->keyfile, priv->unique_name,
+ key, NULL);
+ value = tp_g_value_slice_new_int64 (v_int);
+ break;
- switch (G_VALUE_TYPE (value))
+ case G_TYPE_UINT:
+ v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
+ priv->unique_name, key, NULL);
+
+ if (v_uint > 0xFFFFFFFFU)
{
- case G_TYPE_STRING:
- v_string = g_key_file_get_string (priv->keyfile, priv->unique_name,
- key, NULL);
- g_value_take_string (value, v_string);
- break;
-
- case G_TYPE_INT:
- v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
- key, NULL);
- g_value_set_int (value, v_int);
- break;
-
- case G_TYPE_INT64:
- v_int = tp_g_key_file_get_int64 (priv->keyfile, priv->unique_name,
- key, NULL);
- g_value_set_int64 (value, v_int);
- break;
-
- case G_TYPE_UCHAR:
- v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
- key, NULL);
-
- if (v_int < 0 || v_int > 0xFF)
- {
- return FALSE;
- }
+ goto error;
+ }
- g_value_set_uchar (value, v_int);
- break;
+ value = tp_g_value_slice_new_uint (v_uint);
+ break;
- case G_TYPE_UINT:
- v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
- priv->unique_name, key, NULL);
+ case G_TYPE_UCHAR:
+ v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
+ key, NULL);
- if (v_uint > 0xFFFFFFFFU)
- {
- return FALSE;
- }
+ if (v_int < 0 || v_int > 0xFF)
+ {
+ goto error;
+ }
+ value = tp_g_value_slice_new (G_TYPE_UCHAR);
+ g_value_set_uchar (value, v_int);
+ break;
- g_value_set_uint (value, v_uint);
- break;
+ case G_TYPE_UINT64:
+ v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
+ priv->unique_name, key, NULL);
- case G_TYPE_UINT64:
- v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
- priv->unique_name, key, NULL);
- g_value_set_uint64 (value, v_uint);
- break;
+ value = tp_g_value_slice_new_uint64 (v_uint);
+ break;
- case G_TYPE_BOOLEAN:
- v_bool = g_key_file_get_boolean (priv->keyfile, priv->unique_name,
- key, NULL);
- g_value_set_boolean (value, v_bool);
- break;
+ case G_TYPE_BOOLEAN:
+ v_bool = g_key_file_get_boolean (priv->keyfile, priv->unique_name,
+ key, NULL);
- case G_TYPE_DOUBLE:
- v_double = g_key_file_get_double (priv->keyfile, priv->unique_name,
- key, NULL);
- g_value_set_double (value, v_double);
- break;
+ value = tp_g_value_slice_new_boolean (v_bool);
+ break;
- default:
- if (G_VALUE_HOLDS (value, G_TYPE_STRV))
- {
- gchar **v = g_key_file_get_string_list (priv->keyfile,
- priv->unique_name, key,
- NULL, NULL);
+ case G_TYPE_DOUBLE:
+ v_double = g_key_file_get_double (priv->keyfile, priv->unique_name,
+ key, NULL);
- g_value_take_boxed (value, v);
- }
- else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
- {
- v_string = g_key_file_get_string (priv->keyfile,
- priv->unique_name, key,
- NULL);
+ value = tp_g_value_slice_new_double (v_double);
+ break;
- if (!tp_dbus_check_valid_object_path (v_string, NULL))
- {
- g_free (v_string);
- return FALSE;
- }
+ default:
+ if (type == G_TYPE_STRV)
+ {
+ gchar **v = g_key_file_get_string_list (priv->keyfile,
+ priv->unique_name, key,
+ NULL, NULL);
- g_value_take_boxed (value, v_string);
- }
- else
+ value = tp_g_value_slice_new_take_boxed (G_TYPE_STRV, v);
+ }
+ else if (type == DBUS_TYPE_G_OBJECT_PATH)
+ {
+ v_string = g_key_file_get_string (priv->keyfile,
+ priv->unique_name, key,
+ NULL);
+
+ if (!tp_dbus_check_valid_object_path (v_string, NULL))
{
- g_warning ("%s: skipping parameter %s, unknown type %s",
- G_STRFUNC, name, G_VALUE_TYPE_NAME (value));
- return FALSE;
+ g_free (v_string);
+ goto error;
}
+
+ value = tp_g_value_slice_new_take_object_path (v_string);
+ }
+ else
+ {
+ g_warning ("%s: skipping parameter %s, unknown type %s",
+ G_STRFUNC, name,
+ value ? G_VALUE_TYPE_NAME (value) : "(null)");
+ goto error;
}
}
- return TRUE;
+ if (value != NULL)
+ {
+ if (callback != NULL)
+ callback (account, value, NULL, user_data);
+ tp_g_value_slice_free (value);
+
+ return;
+ }
+
+error:
+ if (callback != NULL)
+ callback (account, NULL, error, user_data);
+ if (error != NULL)
+ g_error_free (error);
}
-static gboolean mcd_account_check_parameters (McdAccount *account);
+
+typedef void (*CheckParametersCb) (McdAccount *account, gboolean valid,
+ gpointer user_data);
+static void mcd_account_check_parameters (McdAccount *account,
+ CheckParametersCb callback, gpointer user_data);
+
+static void
+manager_ready_check_params_cb (McdAccount *account,
+ gboolean valid,
+ gpointer user_data)
+{
+ McdAccountPrivate *priv = account->priv;
+
+ priv->valid = valid;
+ mcd_account_loaded (account);
+}
static void on_manager_ready (McdManager *manager, const GError *error,
gpointer user_data)
{
McdAccount *account = MCD_ACCOUNT (user_data);
- McdAccountPrivate *priv = account->priv;
if (error)
{
DEBUG ("got error: %s", error->message);
+ mcd_account_loaded (account);
}
else
{
- priv->valid = mcd_account_check_parameters (account);
+ mcd_account_check_parameters (account, manager_ready_check_params_cb,
+ NULL);
}
- mcd_account_loaded (account);
}
static gboolean
@@ -1122,10 +1176,16 @@ get_avatar (TpSvcDBusProperties *self, const gchar *name, GValue *value)
static void
get_parameters (TpSvcDBusProperties *self, const gchar *name, GValue *value)
{
- McdAccount *account = MCD_ACCOUNT (self);
- GHashTable *parameters;
+ GHashTable *parameters = NULL;
+
+ /* TODO FIXME RIGHT NOW: move to async dbus properties solution
+ * so we can call dup_parameters
+ * parameters = _mcd_account_dup_parameters (account);
+ * For now, just return an empty asv.
+ */
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
- parameters = _mcd_account_dup_parameters (account);
g_value_init (value, TP_HASH_TYPE_STRING_VARIANT_MAP);
g_value_take_boxed (value, parameters);
}
@@ -1591,50 +1651,90 @@ account_remove (TpSvcAccount *svc, DBusGMethodInvocation *context)
mcd_account_delete (self, account_remove_delete_cb, data);
}
-/*
+/**
* mcd_account_get_parameter:
* @account: the #McdAccount.
* @name: the parameter name.
- * @value: a initialized #GValue to receive the parameter value, or %NULL.
- *
- * Get the @name parameter for @account.
+ * @callback: function to call with the value
+ * @user_data: data to pass to @callback
*
- * Returns: %TRUE if found, %FALSE otherwise.
+ * Get the @name parameter for @account, asynchronously.
*/
-static gboolean
+static void
mcd_account_get_parameter (McdAccount *account, const gchar *name,
- GValue *value)
+ McdAccountGetParameterCb callback,
+ gpointer user_data)
{
- return MCD_ACCOUNT_GET_CLASS (account)->get_parameter (account, name,
- value);
+ MCD_ACCOUNT_GET_CLASS (account)->get_parameter (account, name,
+ callback, user_data);
}
-static gboolean
-mcd_account_check_parameters (McdAccount *account)
+typedef struct
+{
+ McdAccount *account;
+ const TpConnectionManagerParam *param;
+ CheckParametersCb callback;
+ gpointer user_data;
+} CheckParameterData;
+
+static void
+check_parameters_get_param_cb (McdAccount *account, const GValue *value,
+ const GError *error, gpointer user_data)
+{
+ CheckParameterData *data = (CheckParameterData *) user_data;
+ const TpConnectionManagerParam *p;
+
+ if ((account != NULL && value == NULL) || error != NULL)
+ {
+ data->callback (data->account, FALSE, data->user_data);
+ }
+ else
+ {
+ while (data->param->name != NULL
+ && !(data->param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED))
+ {
+ data->param++;
+ }
+
+ if (data->param->name != NULL)
+ {
+ p = data->param++;
+ mcd_account_get_parameter (data->account, p->name,
+ check_parameters_get_param_cb, data);
+ }
+ else
+ {
+ data->callback (data->account, TRUE, data->user_data);
+ g_slice_free (CheckParameterData, data);
+ }
+ }
+}
+
+static void
+mcd_account_check_parameters (McdAccount *account,
+ CheckParametersCb callback,
+ gpointer user_data)
{
McdAccountPrivate *priv = account->priv;
const TpConnectionManagerParam *param;
- gboolean valid;
+ CheckParameterData *data;
DEBUG ("called for %s", priv->unique_name);
param = mcd_manager_get_parameters (priv->manager, priv->protocol_name);
- if (!param) return FALSE;
- valid = TRUE;
- while (param->name != NULL)
+ if (!param)
{
- if (param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED)
- {
- if (!mcd_account_get_parameter (account, param->name, NULL))
- {
- DEBUG ("missing required parameter %s", param->name);
- valid = FALSE;
- break;
- }
- }
- param++;
+ if (callback != NULL)
+ callback (account, FALSE, user_data);
+ return;
}
- return valid;
+ data = g_slice_new0 (CheckParameterData);
+ data->account = account;
+ data->param = param;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ check_parameters_get_param_cb (NULL, NULL, NULL, data);
}
/*
@@ -1658,206 +1758,392 @@ _mcd_account_set_parameter (McdAccount *account, const gchar *name,
callback, user_data);
}
+static GHashTable *
+hash_table_copy (GHashTable *orig)
+{
+ GHashTable *dest;
+
+ dest = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+ tp_g_hash_table_update (dest, orig, (GBoxedCopyFunc) g_strdup,
+ (GBoxedCopyFunc) tp_g_value_slice_dup);
+ return dest;
+}
+
+typedef struct
+{
+ McdAccount *account;
+ GHashTable *params;
+ GHashTableIter iter;
+ gchar **unset;
+ gchar **unset_iter;
+ const TpConnectionManagerParam *param;
+ const GValue *new;
+ guint n_params;
+ GSList *dbus_properties;
+ GPtrArray *not_yet;
+ McdAccountSetParametersCb *callback;
+ gpointer user_data;
+} SetParametersData;
+
+static void
+set_parameters_data_free (SetParametersData *data)
+{
+ if (data->account != NULL)
+ g_object_unref (data->account);
+
+ if (data->params != NULL)
+ g_hash_table_destroy (data->params);
+
+ if (data->unset != NULL)
+ g_strfreev (data->unset);
+
+ if (data->dbus_properties != NULL)
+ g_slist_free (data->dbus_properties);
+
+ g_slice_free (SetParametersData, data);
+}
+
+static void
+set_parameters_finish (SetParametersData *data)
+{
+ McdAccountPrivate *priv = data->account->priv;
+
+ if (mcd_account_get_connection_status (data->account) ==
+ TP_CONNECTION_STATUS_CONNECTED)
+ {
+ GSList *list;
+ const gchar *name;
+ const GValue *value;
+
+ for (list = data->dbus_properties; list != NULL; list = list->next)
+ {
+ name = list->data;
+ DEBUG ("updating parameter %s", name);
+ value = g_hash_table_lookup (data->params, name);
+ _mcd_connection_update_property (priv->connection, name, value);
+ }
+ }
+
+ mcd_account_check_validity (data->account, NULL, NULL);
+ _mcd_account_maybe_autoconnect (data->account);
+
+ if (data->callback != NULL)
+ {
+ data->callback (data->account, data->not_yet, NULL, data->user_data);
+ }
+ set_parameters_data_free (data);
+}
+
+static void set_parameters_unset_single (McdAccount *account,
+ const GError *error,
+ gpointer user_data);
+
+
+static void
+set_parameters_unset_check_present (McdAccount *account,
+ const GValue *value,
+ const GError *error,
+ gpointer user_data)
+{
+ SetParametersData *data = (SetParametersData *) user_data;
+
+ if (value != NULL)
+ {
+ DEBUG ("unsetting %s", *data->unset_iter);
+ /* pessimistically assume that removing any parameter merits
+ * reconnection (in a perfect implementation, if the
+ * Has_Default flag was set we'd check whether the current
+ * value is the default already) */
+
+ g_ptr_array_add (data->not_yet, g_strdup (*data->unset_iter));
+ }
+ _mcd_account_set_parameter (data->account, *data->unset_iter, NULL,
+ set_parameters_unset_single, data);
+}
+
+static void
+set_parameters_unset_single (McdAccount *account, const GError *error,
+ gpointer user_data)
+{
+ SetParametersData *data = (SetParametersData *) user_data;
+
+ if (data->unset == NULL)
+ {
+ set_parameters_finish (data);
+ return;
+ }
+
+ if (account == NULL)
+ {
+ data->unset_iter = data->unset; /* first time */
+ }
+ else
+ {
+ data->unset_iter++;
+ }
+
+ if (*data->unset_iter != NULL)
+ {
+ mcd_account_get_parameter (data->account, *data->unset_iter,
+ set_parameters_unset_check_present, data);
+ }
+ else
+ {
+ set_parameters_finish (data);
+ }
+}
+
+static void
+set_parameters_set_single (McdAccount *account,
+ const GError *error,
+ gpointer user_data)
+{
+ SetParametersData *data = (SetParametersData *) user_data;
+ const gchar *name;
+ const GValue *value;
+
+ if (g_hash_table_iter_next (&data->iter, (gpointer) &name, (gpointer) &value))
+ {
+ _mcd_account_set_parameter (data->account, name, value,
+ set_parameters_set_single, data);
+ }
+ else
+ {
+ /* End of the hash table */
+ set_parameters_unset_single (NULL, NULL, data);
+ }
+}
+
+static void
+set_parameters_iter_param (McdAccount *account,
+ const GValue *ret_value,
+ const GError *error,
+ gpointer user_data)
+{
+ SetParametersData *data = (SetParametersData *) user_data;
+ GError *out_error = NULL;
+
+ /* account == NULL means this is the first run by
+ * _mcd_account_set_parameters itself or in this function,
+ * but with no call to mcd_account_get_parameter. */
+ if (account != NULL
+ && (ret_value == NULL || !value_is_same (ret_value, data->new)))
+ {
+ DEBUG ("Parameter %s changed", data->param->name);
+ /* can the param be updated on the fly? If yes, prepare to
+ * do so; and if not, prepare to reset the connection */
+ if (data->param->flags & TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY)
+ {
+ data->dbus_properties = g_slist_prepend (data->dbus_properties,
+ data->param->name);
+ }
+ else
+ {
+ g_ptr_array_add (data->not_yet, g_strdup (data->param->name));
+ }
+
+ data->param++;
+ }
+
+ if (data->param->name != NULL)
+ {
+ GType type;
+
+ type = mc_param_type (data->param);
+ data->new = g_hash_table_lookup (data->params, data->param->name);
+
+ if (data->new != NULL)
+ {
+ DEBUG ("Got param %s", data->param->name);
+ data->n_params++;
+
+ if (G_VALUE_TYPE (data->new) != type)
+ {
+ /* FIXME: define proper error */
+ g_set_error (&out_error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "parameter %s must be of type %s, not %s",
+ data->param->name,
+ g_type_name (type), G_VALUE_TYPE_NAME (data->new));
+ goto error;
+ }
+
+ if (mcd_account_get_connection_status (data->account) ==
+ TP_CONNECTION_STATUS_CONNECTED)
+ {
+ mcd_account_get_parameter (data->account, data->param->name,
+ set_parameters_iter_param, data);
+ }
+ else
+ {
+ data->param++;
+ set_parameters_iter_param (NULL, NULL, NULL, data);
+ }
+ }
+ else
+ {
+ data->param++;
+ set_parameters_iter_param (NULL, NULL, NULL, data);
+ }
+ }
+ else
+ {
+ if (data->n_params != g_hash_table_size (data->params))
+ {
+ g_set_error (&out_error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Not all parameters were recognized");
+ goto error;
+ }
+ g_hash_table_iter_init (&data->iter, data->params);
+ set_parameters_set_single (data->account, NULL, data);
+ }
+
+ return;
+
+error:
+ if (data->callback != NULL)
+ data->callback (data->account, data->not_yet, out_error, data->user_data);
+
+ set_parameters_data_free (data);
+}
+
/*
* _mcd_account_set_parameters:
* @account: the #McdAccount.
* @name: the parameter name.
* @params: names and values of parameters to set
* @unset: names of parameters to unset
- * @not_yet: if not %NULL, borrowed names of parameters that cannot take
- * effect until Reconnect() is called will be appended to this array
+ * @callback: function to be called when finished
+ * @user_data: data to be passed to @callback
*
* Alter the account parameters.
*
- * Returns: %TRUE (possibly appending borrowed strings to @not_yet) on success,
- * %FALSE (setting @error) on failure
*/
-gboolean
+void
_mcd_account_set_parameters (McdAccount *account, GHashTable *params,
- const gchar ** unset, GPtrArray *not_yet,
- GError **error)
+ const gchar **unset,
+ McdAccountSetParametersCb callback,
+ gpointer user_data)
{
McdAccountPrivate *priv = account->priv;
const TpConnectionManagerParam *param;
- guint n_params = 0;
- GHashTableIter iter;
- const gchar *name;
- const GValue *value;
GSList *dbus_properties = NULL;
- gboolean reset_connection;
+ GPtrArray *not_yet = NULL;
+ SetParametersData *data;
+ GError *error = NULL;
+ guint unset_size;
DEBUG ("called");
if (G_UNLIKELY (!priv->manager && !load_manager (account)))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
"Manager %s not found", priv->manager_name);
- return FALSE;
+ goto error;
}
param = mcd_manager_get_parameters (priv->manager, priv->protocol_name);
if (G_UNLIKELY (!param))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
"Protocol %s not found", priv->protocol_name);
- return FALSE;
+ goto error;
}
- reset_connection = FALSE;
- while (param->name != NULL)
- {
- GType type;
+ unset_size = (unset != NULL) ? g_strv_length ((gchar **) unset) : 0;
- type = mc_param_type (param);
- value = g_hash_table_lookup (params, param->name);
- if (value)
- {
- DEBUG ("Got param %s", param->name);
- if (G_VALUE_TYPE (value) != type)
- {
- /* FIXME: define proper error */
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "parameter %s must be of type %s, not %s",
- param->name,
- g_type_name (type), G_VALUE_TYPE_NAME (value));
- return FALSE;
- }
+ /* pessimistically assume that every parameter mentioned will be deferred
+ * until reconnection */
+ not_yet = g_ptr_array_sized_new (g_hash_table_size (params) + unset_size);
+
+ data = g_slice_new0 (SetParametersData);
+ data->account = g_object_ref (account);
+ data->params = hash_table_copy (params);
+ data->unset = g_strdupv ((gchar **) unset);
+ data->param = param;
+ data->n_params = 0;
+ data->dbus_properties = dbus_properties;
+ data->not_yet = not_yet;
+ data->callback = callback;
+ data->user_data = user_data;
- if (mcd_account_get_connection_status (account) ==
- TP_CONNECTION_STATUS_CONNECTED)
- {
- GValue old = { 0 };
+ set_parameters_iter_param (NULL, NULL, NULL, data);
+ return;
- g_value_init (&old, type);
- if (!mcd_account_get_parameter (account, param->name, &old) ||
- !value_is_same (value, &old))
- {
- DEBUG ("Parameter %s changed", param->name);
- /* can the param be updated on the fly? If yes, prepare to
- * do so; and if not, prepare to reset the connection */
- if (param->flags & TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY)
- {
- dbus_properties = g_slist_prepend (dbus_properties,
- param->name);
- }
- else
- {
- if (not_yet != NULL)
- {
- /* we assume that the TpConnectionManager won't get
- * freed */
- g_ptr_array_add (not_yet, param->name);
- }
-
- reset_connection = TRUE;
- }
- }
- g_value_unset (&old);
- }
- n_params++;
- }
- param++;
- }
+error:
+ if (callback != NULL)
+ callback (account, NULL, error, user_data);
- if (n_params != g_hash_table_size (params))
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "Not all parameters were recognized");
- return FALSE;
- }
+ g_error_free (error);
+ if (not_yet != NULL)
+ g_ptr_array_free (not_yet, TRUE);
+}
- g_hash_table_iter_init (&iter, params);
- while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&value))
- {
- _mcd_account_set_parameter (account, name, value, NULL, NULL);
- }
+typedef struct
+{
+ DBusGMethodInvocation *context;
+ GPtrArray *not_yet;
+} UpdateParametersData;
- if (unset != NULL)
- {
- const gchar **unset_iter;
+static void
+update_parameters_dup_params_cb (McdAccount *account, GHashTable *params,
+ gpointer user_data)
+{
+ McdAccountPrivate *priv = account->priv;
+ UpdateParametersData *data = (UpdateParametersData *) user_data;
+ GValue value = { 0 };
- for (unset_iter = unset; *unset_iter != NULL; unset_iter++)
- {
- if (mcd_account_get_parameter (account, *unset_iter, NULL))
- {
- DEBUG ("unsetting %s", *unset_iter);
- /* pessimistically assume that removing any parameter merits
- * reconnection (in a perfect implementation, if the
- * Has_Default flag was set we'd check whether the current
- * value is the default already) */
- if (not_yet != NULL)
- {
- /* we assume that the TpConnectionManager won't get
- * freed */
- g_ptr_array_add (not_yet, (gchar *) *unset_iter);
- }
+ g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP);
+ g_value_take_boxed (&value, params);
+ mcd_account_changed_property (account, "Parameters", &value);
+ g_value_unset (&value);
- reset_connection = TRUE;
- }
+ mcd_account_manager_write_conf_async (priv->account_manager, NULL, NULL);
- _mcd_account_set_parameter (account, *unset_iter, NULL, NULL, NULL);
- }
- }
+ g_ptr_array_add (data->not_yet, NULL);
- if (mcd_account_get_connection_status (account) ==
- TP_CONNECTION_STATUS_CONNECTED)
- {
- GSList *list;
+ tp_svc_account_return_from_update_parameters (data->context,
+ (const gchar **) data->not_yet->pdata);
- for (list = dbus_properties; list != NULL; list = list->next)
- {
- name = list->data;
- DEBUG ("updating parameter %s", name);
- value = g_hash_table_lookup (params, name);
- _mcd_connection_update_property (priv->connection, name, value);
- }
- }
- g_slist_free (dbus_properties);
+ g_ptr_array_foreach (data->not_yet, (GFunc) g_free, NULL);
+ g_ptr_array_free (data->not_yet, TRUE);
- mcd_account_check_validity (account);
- _mcd_account_maybe_autoconnect (account);
- return TRUE;
+ g_slice_free (UpdateParametersData, data);
}
static void
-account_update_parameters (TpSvcAccount *self, GHashTable *set,
- const gchar **unset, DBusGMethodInvocation *context)
+account_update_parameters_cb (McdAccount *account, GPtrArray *not_yet,
+ const GError *error, gpointer user_data)
{
- McdAccount *account = MCD_ACCOUNT (self);
- McdAccountPrivate *priv = account->priv;
- GHashTable *parameters;
- GValue value = { 0 };
- GError *error = NULL;
- GPtrArray *not_yet;
-
- DEBUG ("called for %s", priv->unique_name);
-
- /* pessimistically assume that every parameter mentioned will be deferred
- * until reconnection */
- not_yet = g_ptr_array_sized_new (g_hash_table_size (set) +
- g_strv_length ((gchar **) unset) + 1);
+ DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+ UpdateParametersData *data;
- if (!_mcd_account_set_parameters (account, set, unset, not_yet, &error))
+ if (error != NULL)
{
- g_ptr_array_free (not_yet, TRUE);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
+ dbus_g_method_return_error (context, (GError *) error);
return;
}
+ data = g_slice_new0 (UpdateParametersData);
+ data->not_yet = not_yet;
+ data->context = context;
+
/* emit the PropertiesChanged signal */
- parameters = _mcd_account_dup_parameters (account);
- g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP);
- g_value_take_boxed (&value, parameters);
- mcd_account_changed_property (account, "Parameters", &value);
- g_value_unset (&value);
+ _mcd_account_dup_parameters (account, update_parameters_dup_params_cb,
+ data);
+}
- mcd_account_manager_write_conf_async (priv->account_manager, NULL, NULL);
+static void
+account_update_parameters (TpSvcAccount *self, GHashTable *set,
+ const gchar **unset, DBusGMethodInvocation *context)
+{
+ McdAccount *account = MCD_ACCOUNT (self);
+ McdAccountPrivate *priv = account->priv;
- g_ptr_array_add (not_yet, NULL);
+ DEBUG ("called for %s", priv->unique_name);
- tp_svc_account_return_from_update_parameters (context,
- (const gchar **) not_yet->pdata);
- g_ptr_array_free (not_yet, TRUE);
+ _mcd_account_set_parameters (account, set, unset,
+ account_update_parameters_cb, context);
}
static void
@@ -2320,54 +2606,93 @@ mcd_account_get_object_path (McdAccount *account)
return account->priv->object_path;
}
-static inline void
-add_parameter (McdAccount *account, const TpConnectionManagerParam *param,
- GHashTable *params)
+typedef struct
{
- GValue *value;
- GType type;
-
- type = mc_param_type (param);
- if (G_UNLIKELY (type == G_TYPE_INVALID)) return;
-
- value = tp_g_value_slice_new (type);
+ GHashTable *params;
+ const TpConnectionManagerParam *param;
+ McdAccountDupParametersCb callback;
+ gpointer user_data;
+} DupParametersData;
- if (mcd_account_get_parameter (account, param->name, value))
- g_hash_table_insert (params, g_strdup (param->name), value);
- else
- tp_g_value_slice_free (value);
+static void
+dup_parameters_get_parameter_cb (McdAccount *account,
+ const GValue *value,
+ const GError *error,
+ gpointer user_data)
+{
+ DupParametersData *data = (DupParametersData *) user_data;
+
+ if (value != NULL)
+ {
+ g_hash_table_insert (data->params, g_strdup (data->param->name),
+ tp_g_value_slice_dup (value));
+ }
+
+ data->param++;
+
+ if (data->param->name != NULL)
+ {
+ mcd_account_get_parameter (account, data->param->name,
+ dup_parameters_get_parameter_cb, data);
+ }
+ else
+ {
+ if (data->callback != NULL)
+ data->callback (account, data->params, data->user_data);
+ g_slice_free (DupParametersData, data);
+ }
}
-/*
+/**
* _mcd_account_dup_parameters:
* @account: the #McdAccount.
+ * @callback: function to call with the result
+ * @user_data: data to pass to @callback
*
- * Get the parameters set for this account.
- *
- * Returns: a newly allocated #GHashTable containing the account parameters.
+ * Get the parameters set for this account. The resulting #GHashTable in the
+ * callback will be newly allocated and must be g_hash_table_unref() 'd after
+ * use.
*/
-GHashTable *
-_mcd_account_dup_parameters (McdAccount *account)
+void
+_mcd_account_dup_parameters (McdAccount *account,
+ McdAccountDupParametersCb callback,
+ gpointer user_data)
{
- McdAccountPrivate *priv = MCD_ACCOUNT_PRIV (account);
+ McdAccountPrivate *priv;
+ DupParametersData *data;
const TpConnectionManagerParam *param;
- GHashTable *params;
+
+ g_return_if_fail (MCD_IS_ACCOUNT (account));
+
+ priv = account->priv;
DEBUG ("called");
- if (!priv->manager && !load_manager (account)) return NULL;
+ if (!priv->manager && !load_manager (account))
+ {
+ callback (account, NULL, user_data);
+ return;
+ }
- params = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free,
- (GDestroyNotify)tp_g_value_slice_free);
- param = mcd_manager_get_parameters (priv->manager, priv->protocol_name);
- if (G_UNLIKELY (!param)) return params;
+ param = mcd_manager_get_parameters (priv->manager,
+ priv->protocol_name);
- while (param->name != NULL)
+ if (G_UNLIKELY (!param))
{
- add_parameter (account, param, params);
- param++;
+ callback (account, NULL, user_data);
+ return;
}
- return params;
+
+ data = g_slice_new0 (DupParametersData);
+ data->param = param;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ data->params = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+ mcd_account_get_parameter (account, param->name,
+ dup_parameters_get_parameter_cb, data);
}
/**
@@ -2840,25 +3165,31 @@ mcd_account_get_connection (McdAccount *account)
return priv->connection;
}
-gboolean
-mcd_account_check_validity (McdAccount *account)
+typedef struct
{
- McdAccountPrivate *priv = account->priv;
- gboolean valid;
+ McdAccountCheckValidityCb callback;
+ gpointer user_data;
+} CheckValidityData;
- valid = (priv->loaded && mcd_account_check_parameters (account));
+static void
+check_validity_check_parameters_cb (McdAccount *account,
+ gboolean valid,
+ gpointer user_data)
+{
+ CheckValidityData *data = (CheckValidityData *) user_data;
+ McdAccountPrivate *priv = account->priv;
if (valid != priv->valid)
{
- GValue value = { 0 };
+ GValue value = { 0 };
DEBUG ("Account validity changed (old: %d, new: %d)",
priv->valid, valid);
- priv->valid = valid;
- g_signal_emit (account, _mcd_account_signals[VALIDITY_CHANGED], 0,
- valid);
- g_value_init (&value, G_TYPE_BOOLEAN);
- g_value_set_boolean (&value, valid);
- mcd_account_changed_property (account, "Valid", &value);
+ priv->valid = valid;
+ g_signal_emit (account, _mcd_account_signals[VALIDITY_CHANGED], 0,
+ valid);
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, valid);
+ mcd_account_changed_property (account, "Valid", &value);
if (valid)
{
@@ -2869,7 +3200,28 @@ mcd_account_check_validity (McdAccount *account)
priv->req_presence_message);
}
}
- return valid;
+
+ if (data->callback != NULL)
+ data->callback (account, valid, data->user_data);
+
+ g_slice_free (CheckValidityData, data);
+}
+
+void
+mcd_account_check_validity (McdAccount *account,
+ McdAccountCheckValidityCb callback,
+ gpointer user_data)
+{
+ CheckValidityData *data;
+
+ g_return_if_fail (MCD_IS_ACCOUNT (account));
+
+ data = g_slice_new0 (CheckValidityData);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ mcd_account_check_parameters (account, check_validity_check_parameters_cb,
+ data);
}
/*
diff --git a/src/mcd-account.h b/src/mcd-account.h
index 16aa2297..85c2f285 100644
--- a/src/mcd-account.h
+++ b/src/mcd-account.h
@@ -57,12 +57,17 @@ typedef void (*McdAccountDeleteCb) (McdAccount *account,
typedef void (*McdAccountSetParameterCb) (McdAccount *account,
const GError *error,
gpointer user_data);
+typedef void (*McdAccountGetParameterCb) (McdAccount *account,
+ const GValue *value,
+ const GError *error,
+ gpointer user_data);
struct _McdAccountClass
{
GObjectClass parent_class;
- gboolean (*get_parameter) (McdAccount *account, const gchar *name,
- GValue *value);
+ void (*get_parameter) (McdAccount *account, const gchar *name,
+ McdAccountGetParameterCb callback,
+ gpointer user_data);
void (*set_parameter) (McdAccount *account, const gchar *name,
const GValue *value,
McdAccountSetParameterCb callback,
@@ -92,7 +97,13 @@ const gchar *mcd_account_get_unique_name (McdAccount *account);
const gchar *mcd_account_get_object_path (McdAccount *account);
gboolean mcd_account_is_valid (McdAccount *account);
-gboolean mcd_account_check_validity (McdAccount *account);
+
+typedef void (*McdAccountCheckValidityCb) (McdAccount *account,
+ gboolean valid,
+ gpointer user_data);
+void mcd_account_check_validity (McdAccount *account,
+ McdAccountCheckValidityCb callback,
+ gpointer user_data);
gboolean mcd_account_is_enabled (McdAccount *account);