+struct report_error_data {
+ void *user_context;
+ report_error_cb_t callback;
+ void *user_data;
+};
+
+static void report_error_reply(DBusMessage *reply, void *user_data)
+{
+ struct report_error_data *report_error = user_data;
+ bool retry = false;
+ const char *dbus_err;
+
+ if (!reply)
+ goto out;
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ dbus_err = dbus_message_get_error_name(reply);
+ if (dbus_err &&
+ strcmp(dbus_err,
+ CONNMAN_AGENT_INTERFACE ".Error.Retry") == 0)
+ retry = true;
+ }
+
+ report_error->callback(report_error->user_context, retry,
+ report_error->user_data);
+out:
+ g_free(report_error);
+}
+
+int connman_agent_report_error_full(void *user_context, const char *path,
+ const char *method, const char *error,
+ report_error_cb_t callback,
+ const char *dbus_sender, void *user_data)
+{
+ DBusMessage *message;
+ DBusMessageIter iter;
+ struct report_error_data *report_error;
+ struct connman_agent *agent;
+ int err;
+
+ agent = connman_agent_get_info(dbus_sender, NULL, NULL);
+
+ DBG("agent %p sender %s context %p path %s", agent,
+ dbus_sender, user_context, agent ? agent->path : "-");
+
+ if (!user_context || !agent || !agent->path || !error || !callback)
+ return -ESRCH;
+
+ message = dbus_message_new_method_call(agent->owner, agent->path,
+ CONNMAN_AGENT_INTERFACE, method);
+ if (!message)
+ return -ENOMEM;
+
+ dbus_message_iter_init_append(message, &iter);
+
+ dbus_message_iter_append_basic(&iter,
+ DBUS_TYPE_OBJECT_PATH, &path);
+ dbus_message_iter_append_basic(&iter,
+ DBUS_TYPE_STRING, &error);
+
+ report_error = g_try_new0(struct report_error_data, 1);
+ if (!report_error) {
+ dbus_message_unref(message);
+ return -ENOMEM;
+ }
+
+ report_error->user_context = user_context;
+ report_error->callback = callback;
+ report_error->user_data = user_data;
+
+ err = connman_agent_queue_message(user_context, message,
+ connman_timeout_input_request(),
+ report_error_reply, report_error,
+ agent);
+ if (err < 0 && err != -EBUSY) {
+ DBG("error %d sending error request", err);
+ g_free(report_error);
+ dbus_message_unref(message);
+ return -ESRCH;
+ }
+
+ dbus_message_unref(message);
+
+ return -EINPROGRESS;
+}
+
+int connman_agent_report_error(void *user_context, const char *path,
+ const char *error,
+ report_error_cb_t callback,
+ const char *dbus_sender, void *user_data)
+{
+ return connman_agent_report_error_full(user_context, path,
+ "ReportError", error, callback, dbus_sender,
+ user_data);
+}
+
+static gint compare_priority(gconstpointer a, gconstpointer b)