// --------------------------------------------------------------
// Connman Agent Handlers
// --------------------------------------------------------------
+ /**
+ * @class agent_operation_handler
+ *
+ * @brief Handle agent operations through given callback.
+ *
+ * This class factors out common connection data retrieval code, and
+ * performs Agent operations through the given callback.
+ */
+ class agent_operation_handler
+ {
+ typedef ivi::settings::agent agent;
+ typedef agent::user_data data_type;
+
+ // Prevent copying.
+ agent_operation_handler(agent_operation_handler const &) = delete;
+ void operator=(agent_operation_handler const &) = delete;
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * @param[in] service D-Bus object path for connman service
+ * @param[in] user_data User/connection data
+ * @param[in] callback Callback that implements Agent operation
+ */
+ agent_operation_handler(
+ gchar const * service,
+ gpointer user_data,
+ std::function<void(ivi::settings::agent::connect_data const &)>
+ callback)
+ : data_(static_cast<data_type *>(user_data))
+ , guard_(data_->lock)
+ , iterator_(data_->info.find(service))
+ {
+ // data_ should never be null!
+
+ if (iterator_ != data_->info.end())
+ callback(iterator_->second);
+ }
+
+ /// Destructor
+ ~agent_operation_handler()
+ {
+ // Done with the connection data. Remove it from the map.
+ if (iterator_ != data_->info.end())
+ data_->info.erase(iterator_);
+ }
+
+ private:
+ /// User/connection data.
+ data_type * const data_;
+
+ /**
+ * Synchronize access to the user/connection data map.
+ *
+ * @note This lock will be held for the life of the
+ * @c agent_operation_handler object, i.e. for the duration
+ * of the operation. This is needed to synchronize the map
+ * @c erase() operation in the destructor. The erase()
+ * operation is performed in the destructor to ensure
+ * element removal occurs if an exception is thrown by the
+ * callback.
+ */
+ std::lock_guard<std::mutex> guard_;
+
+ /// Map iterator that points to the connection data.
+ agent::user_data::map_type::iterator const iterator_;
+ };
+
bool
on_handle_release(Agent * object,
GDBusMethodInvocation * invocation,
gchar const * error,
gpointer user_data)
{
- using namespace ivi::settings;
- typedef agent::user_data data_type;
+ using ivi::settings::agent;
- data_type * const data = static_cast<data_type *>(user_data);
-
- {
- std::lock_guard<std::mutex> guard(data->lock);
-
- auto const i = data->info.find(service);
- if (i != data->info.end()) {
- auto & response = i->second.response;
- response.send_error(error);
-
- /**
- * @todo Make sure map element removal occurs if exception is
- * thrown above.
- */
- // Done with the connection data.
- data->info.erase(i);
- }
- }
+ agent_operation_handler(service,
+ user_data,
+ [error](agent::connect_data const & d){
+ d.response.send_error(std::string(error));
+ });
agent_complete_report_error(object, invocation);
GVariant * fields,
gpointer user_data)
{
- using namespace ivi::settings;
- typedef agent::user_data data_type;
+ using ivi::settings::agent;
- data_type * const data = static_cast<data_type *>(user_data);
+ agent_operation_handler(
+ service,
+ user_data,
+ [fields](agent::connect_data const & /* d */){
+ using ivi::settings::unique_ptr;
- {
- std::lock_guard<std::mutex> guard(data->lock);
-
- auto const i = data->info.find(service);
- if (i != data->info.end()) {
// Extract requested mandatory and alternate fields.
GVariantIter * vi = nullptr;
g_variant_get(fields, "(a{sv})", &vi);
}
-
-
- auto & response = i->second.response;
-
- // Nothing to add to successful response.
- response.send_response(
- [](JsonBuilder * /* builder */) {});
-
- /**
- * @todo Make sure map element removal occurs if exception is
- * thrown above.
- */
- // Done with the connection data.
- data->info.erase(i);
- }
- }
-
-
+ });
GVariant * dictionary = nullptr;
-
-
// The method return value will contain a dictionary of the
// requested input fields.
agent_complete_request_input(object, invocation, dictionary);
JsonReader * reader,
response_callback const & response)
{
+ connect_data data(reader, response);
+
std::lock_guard<std::mutex> guard(data_.lock);
auto const result =
- data_.info.emplace(std::make_pair(service_path,
- connect_data(reader, response)));
+ data_.info.insert(
+ std::make_pair(service_path, std::move(data)));
return result.second;
}