thunderbolt: sync client bits from bolt

Import five commits that add methods to enroll and authorize multiple
devices at once; meant for authorizing a target device and all the
parents that need to be authorized.
Commits in bolt are:
  1ae5c8611fc21c21c8c63ba6933b63eb4c20ab87
  d993ca2f871e7e412b4e1f885b24e4f6622dfc55
  2689e5f77496ac7698744e582feb9afa3e55e0ac
  87762ce14650263ef35f97da5a3a5d122ac0b7d7
  5aa5548d6c7fa1fa26733ecd073097bc1b9d31fb
  00b3d8a35835b8c856e5de026a0c8316b2ceba90
This commit is contained in:
Christian Kellner 2019-02-01 17:46:15 +01:00
parent c722c6af47
commit 149837eeeb
2 changed files with 391 additions and 2 deletions

View file

@ -468,9 +468,8 @@ bolt_client_enroll_device_finish (BoltClient *client,
char **path,
GError **error)
{
GVariant *val = NULL;
g_autoptr(GError) err = NULL;
g_autoptr(GVariant) val = NULL;
g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
@ -487,6 +486,360 @@ bolt_client_enroll_device_finish (BoltClient *client,
return TRUE;
}
typedef struct OpData
{
const char *iface; /* Manager or Device */
const char *method; /* Enroll or Authorize */
char *path; /* object path */
GVariant *params; /* parameters */
} OpData;
static OpData *
op_data_new_enroll (const char *uid,
const char *policy,
const char *flags)
{
GVariant *params;
OpData *op;
params = g_variant_new ("(sss)", uid, policy, flags);
op = g_slice_new (OpData);
op->iface = BOLT_DBUS_INTERFACE;
op->method = "EnrollDevice";
op->params = g_variant_ref_sink (params);
op->path = g_strdup (BOLT_DBUS_PATH);
return op;
}
static OpData *
op_data_new_authorize (const char *uid,
const char *flags)
{
OpData *op = NULL;
GVariant *params;
char *path;
path = bolt_gen_object_path (BOLT_DBUS_PATH_DEVICES, uid);
params = g_variant_new ("(s)", flags);
op = g_slice_new (OpData);
op->iface = BOLT_DBUS_DEVICE_INTERFACE;
op->method = "Authorize";
op->params = g_variant_ref_sink (params);
op->path = path; /* takes ownership */
return op;
}
static void
op_data_free (OpData *op)
{
g_clear_pointer (&op->params, g_variant_unref);
g_clear_pointer (&op->path, g_free);
g_slice_free (OpData, op);
}
static void
op_queue_free (GQueue *queue)
{
g_queue_free_full (queue, (GDestroyNotify) op_data_free);
}
static void allop_one_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data);
static gboolean
allop_continue (BoltClient *client, GTask *task, GQueue *ops)
{
GDBusConnection *bus;
GCancellable *cancel;
OpData *op;
cancel = g_task_get_cancellable (task);
bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
op = g_queue_pop_head (ops);
if (op == NULL)
return TRUE;
g_dbus_connection_call (bus,
BOLT_DBUS_NAME,
op->path,
op->iface,
op->method,
op->params,
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
cancel,
allop_one_done,
task);
op_data_free (op);
return FALSE;
}
static void
allop_one_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GVariant) val = NULL;
BoltClient *client;
GDBusConnection *bus;
gboolean done;
GError *err = NULL;
GQueue *ops;
GTask *task;
task = G_TASK (user_data);
ops = g_task_get_task_data (task);
client = g_task_get_source_object (task);
bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
val = g_dbus_connection_call_finish (bus, res, &err);
if (val == NULL)
{
g_task_return_error (task, err); /* takes ownership */
g_object_unref (task);
/* we are done (albeit with an error) */
return;
}
done = allop_continue (client, task, ops);
if (done)
{
/* we are done */
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
}
void
bolt_client_enroll_all_async (BoltClient *client,
GPtrArray *uuids,
BoltPolicy policy,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autofree char *fstr = NULL;
GError *err = NULL;
const char *pstr;
GQueue *ops;
GTask *task;
g_return_if_fail (BOLT_IS_CLIENT (client));
g_return_if_fail (uuids != NULL && uuids->len > 0);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (callback != NULL);
pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
if (pstr == NULL)
{
g_task_report_error (client, callback, user_data, NULL, err);
return;
}
fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
if (fstr == NULL)
{
g_task_report_error (client, callback, user_data, NULL, err);
return;
}
task = g_task_new (client, cancellable, callback, user_data);
g_task_set_return_on_cancel (task, TRUE);
ops = g_queue_new ();
g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
for (guint i = 0; i < uuids->len; i++)
{
const char *uid = g_ptr_array_index (uuids, i);
OpData *op;
op = op_data_new_enroll (uid, pstr, fstr);
g_queue_push_tail (ops, op);
}
allop_continue (client, task, ops);
}
gboolean
bolt_client_enroll_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error)
{
g_autoptr(GError) err = NULL;
gboolean ok;
g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
ok = g_task_propagate_boolean (G_TASK (res), &err);
if (!ok)
bolt_error_propagate_stripped (error, &err);
return ok;
}
void
bolt_client_authorize_all_async (BoltClient *client,
GPtrArray *uuids,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autofree char *fstr = NULL;
GError *err = NULL;
GQueue *ops;
GTask *task;
g_return_if_fail (BOLT_IS_CLIENT (client));
g_return_if_fail (uuids != NULL && uuids->len > 0);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (callback != NULL);
fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
if (fstr == NULL)
{
g_task_report_error (client, callback, user_data, NULL, err);
return;
}
task = g_task_new (client, cancellable, callback, user_data);
g_task_set_return_on_cancel (task, TRUE);
ops = g_queue_new ();
g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
for (guint i = 0; i < uuids->len; i++)
{
const char *uid = g_ptr_array_index (uuids, i);
OpData *op;
op = op_data_new_authorize (uid, fstr);
g_queue_push_tail (ops, op);
}
allop_continue (client, task, ops);
}
gboolean
bolt_client_authorize_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error)
{
g_autoptr(GError) err = NULL;
gboolean ok;
g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
ok = g_task_propagate_boolean (G_TASK (res), &err);
if (!ok)
bolt_error_propagate_stripped (error, &err);
return ok;
}
void
bolt_client_connect_all_async (BoltClient *client,
GPtrArray *devices,
BoltPolicy policy,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autofree char *fstr = NULL;
GError *err = NULL;
const char *pstr;
GQueue *ops;
GTask *task;
g_return_if_fail (BOLT_IS_CLIENT (client));
g_return_if_fail (devices != NULL && devices->len > 0);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
g_return_if_fail (callback != NULL);
pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
if (pstr == NULL)
{
g_task_report_error (client, callback, user_data, NULL, err);
return;
}
fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
if (fstr == NULL)
{
g_task_report_error (client, callback, user_data, NULL, err);
return;
}
task = g_task_new (client, cancellable, callback, user_data);
g_task_set_return_on_cancel (task, TRUE);
ops = g_queue_new ();
g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
for (guint i = 0; i < devices->len; i++)
{
BoltDevice *dev = g_ptr_array_index (devices, i);
const char *uid = bolt_device_get_uid (dev);
OpData *op;
if (bolt_device_is_stored (dev))
op = op_data_new_authorize (uid, fstr);
else
op = op_data_new_enroll (uid, pstr, fstr);
g_queue_push_tail (ops, op);
}
allop_continue (client, task, ops);
}
gboolean
bolt_client_connect_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error)
{
g_autoptr(GError) err = NULL;
gboolean ok;
g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
ok = g_task_propagate_boolean (G_TASK (res), &err);
if (!ok)
bolt_error_propagate_stripped (error, &err);
return ok;
}
gboolean
bolt_client_forget_device (BoltClient *client,
const char *uid,

View file

@ -65,6 +65,42 @@ gboolean bolt_client_enroll_device_finish (BoltClient *client,
char **path,
GError **error);
void bolt_client_enroll_all_async (BoltClient *client,
GPtrArray *uuids,
BoltPolicy policy,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean bolt_client_enroll_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error);
void bolt_client_authorize_all_async (BoltClient *client,
GPtrArray *uuids,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean bolt_client_authorize_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error);
void bolt_client_connect_all_async (BoltClient *client,
GPtrArray *devices,
BoltPolicy policy,
BoltAuthCtrl flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean bolt_client_connect_all_finish (BoltClient *client,
GAsyncResult *res,
GError **error);
gboolean bolt_client_forget_device (BoltClient *client,
const char *uid,
GError **error);