From c8e84ea0a07fd57a6a8d8d748b6cfc5fe7560bc9 Mon Sep 17 00:00:00 2001 From: Ossama Othman Date: Sun, 20 Oct 2013 23:28:44 -0700 Subject: [PATCH] Expanded connman agent implementation. Signed-off-by: Ossama Othman --- plugins/connman/agent.cpp | 93 ++++++++++++++++++++++++++----------- plugins/connman/agent.hpp | 70 +++++++++++++++++++++++++++- plugins/connman/agent.xml | 1 + plugins/connman/connman_manager.cpp | 13 +++++- plugins/connman/connman_manager.hpp | 8 ++++ plugins/connman/technology.cpp | 17 +++++-- 6 files changed, 168 insertions(+), 34 deletions(-) diff --git a/plugins/connman/agent.cpp b/plugins/connman/agent.cpp index 55bfb6d..cde53ab 100644 --- a/plugins/connman/agent.cpp +++ b/plugins/connman/agent.cpp @@ -81,47 +81,75 @@ namespace // -------------------------------------------------------------- // Connman Agent Handlers // -------------------------------------------------------------- - gboolean - on_handle_release(Agent * /* object */, - GDBusMethodInvocation * /* invocation */) + bool + on_handle_release(Agent * object, + GDBusMethodInvocation * invocation, + gpointer /* user_data */) { + agent_complete_release(object, invocation); return true; } - gboolean - on_handle_report_error(Agent * /* object */, - GDBusMethodInvocation * /* invocation */, - gchar const * /* service */, - gchar const * /* error */) + bool + on_handle_report_error(Agent * object, + GDBusMethodInvocation * invocation, + gchar const * service, + gchar const * error, + gpointer user_data) { + using namespace ivi::settings; + typedef agent::user_data data_type; + + data_type * const data = static_cast(user_data); + + { + std::lock_guard guard(data->lock); + + auto const i = data->info.find(service); + if (i != data->info.end()) { + auto & response = i->second.response; + response.send_error(error); + } + } + + agent_complete_report_error(object, invocation); + return true; } - gboolean - on_handle_request_browser(Agent * /* object */, - GDBusMethodInvocation * /* invocation */, + bool + on_handle_request_browser(Agent * object, + GDBusMethodInvocation * invocation, gchar const * /* service */, - gchar const * /* url */) + gchar const * /* url */, + gpointer /* user_data */) { + agent_complete_request_browser(object, invocation); return true; } - gboolean - on_handle_request_input(Agent * /* object */, - GDBusMethodInvocation * /* invocation */, + bool + on_handle_request_input(Agent * object, + GDBusMethodInvocation * invocation, gchar const * /* service */, - GVariant * /* fields */) + GVariant * /* fields */, + gpointer /* user_data */) { + GVariant * response = nullptr; + // The method return value will contain a dictionary of the // requested input fields. + agent_complete_request_input(object, invocation, response); return true; } - gboolean - on_handle_cancel(Agent * /* object */, - GDBusMethodInvocation * /* invocation */) + bool + on_handle_cancel(Agent * object, + GDBusMethodInvocation * invocation, + gpointer /* user_data */) { + agent_complete_cancel(object, invocation); return true; } } @@ -141,6 +169,7 @@ ivi::settings::agent::agent(GDBusConnection * connection) nullptr)) , interface_(agent_skeleton_new()) , object_path_("/" IVI_SETTINGS_DBUS_NAME "/connman/Agent") + , data_() { // Construct object path of the form: // /org/tizen/settingsd/connman/Agent" @@ -151,28 +180,29 @@ ivi::settings::agent::agent(GDBusConnection * connection) g_signal_connect(interface_, "handle-release", G_CALLBACK(on_handle_release), - nullptr); + &data_); g_signal_connect(interface_, "handle-report-error", G_CALLBACK(on_handle_report_error), - nullptr); + &data_); g_signal_connect(interface_, "handle-request-browser", G_CALLBACK(on_handle_request_browser), - nullptr); + &data_); g_signal_connect(interface_, "handle-request-input", G_CALLBACK(on_handle_request_input), - nullptr); + &data_); g_signal_connect(interface_, "handle-cancel", G_CALLBACK(on_handle_cancel), - nullptr); + &data_); + // Export the interface on the bus. GError * error = nullptr; if (!g_dbus_interface_skeleton_export( G_DBUS_INTERFACE_SKELETON(interface_), @@ -195,10 +225,19 @@ ivi::settings::agent::~agent() g_bus_unown_name(owner_id_); } -char const * -ivi::settings::agent::object_path() const +bool +ivi::settings::agent::register_connect_data( + char const * service_path, + JsonReader * reader, + response_callback const & response) { - return object_path_.c_str(); + std::lock_guard guard(data_.lock); + + auto const result = + data_.info.emplace(std::make_pair(service_path, + connect_data(reader, response))); + + return result.second; } diff --git a/plugins/connman/agent.hpp b/plugins/connman/agent.hpp index dfb6e3b..4931942 100644 --- a/plugins/connman/agent.hpp +++ b/plugins/connman/agent.hpp @@ -31,9 +31,13 @@ #include "agent-glue.h" +#include + + #include +#include +#include -#include namespace ivi { @@ -54,8 +58,67 @@ namespace ivi /// Destructor. ~agent(); + /** + * Register data that may be needed when handling Connman Agent + * method calls. + */ + bool register_connect_data(char const * service_path, + JsonReader * reader, + response_callback const & response); + /// Get D-Bus object path for this @c Agent. - char const * object_path() const; + char const * + object_path() const + { + return object_path_.c_str(); + } + + /** + * @struct connect_data + * + * @brief Connman Service object-specific connect data. + */ + struct connect_data + { + connect_data(JsonReader * rd, + response_callback const & resp) + : reader(static_cast(g_object_ref(rd))) + , response(resp) + { + } + + connect_data(connect_data && other) + : reader(std::move(other.reader)) + , response(other.response) + { + other.reader.reset(); + + // Nothing to do with response field. + } + + connect_data(connect_data const &) = delete; + + unique_ptr reader; + response_callback response; + }; + + /** + * @struct user_data + * + * @brief Wrapper for data passed to Connman Agent method + * handlers. + */ + struct user_data + { + /// Synchronize access to the response/request data map. + std::mutex lock; + + /** + * Map of service D-Bus object path to request/response + * data. + */ + std::map info; + }; private: @@ -78,6 +141,9 @@ namespace ivi /// D-Bus object path for this @c Agent. std::string object_path_; + /// Service connect map, data, etc. + user_data data_; + }; } } diff --git a/plugins/connman/agent.xml b/plugins/connman/agent.xml index 1ba7ae2..2435573 100644 --- a/plugins/connman/agent.xml +++ b/plugins/connman/agent.xml @@ -49,6 +49,7 @@ + diff --git a/plugins/connman/connman_manager.cpp b/plugins/connman/connman_manager.cpp index cb03c54..ffb361a 100644 --- a/plugins/connman/connman_manager.cpp +++ b/plugins/connman/connman_manager.cpp @@ -103,6 +103,17 @@ ivi::settings::connman_manager::~connman_manager() subscription_id_); } +bool +ivi::settings::connman_manager::register_connect_data( + char const * service_path, + JsonReader * reader, + response_callback const & response) +{ + return agent_.register_connect_data(service_path, + reader, + response); +} + GVariant * ivi::settings::connman_manager::get_properties( std::string const & technology, @@ -126,7 +137,7 @@ ivi::settings::connman_manager::get_properties( unique_ptr const tmp( g_variant_get_child_value(child.get(), 0)); - char const * object = + char const * const object = g_variant_get_string(tmp.get(), nullptr); // The technology is found at end the object path, diff --git a/plugins/connman/connman_manager.hpp b/plugins/connman/connman_manager.hpp index 48967f9..2845d6b 100644 --- a/plugins/connman/connman_manager.hpp +++ b/plugins/connman/connman_manager.hpp @@ -61,6 +61,14 @@ namespace ivi ~connman_manager(); /** + * Register data that may be needed when handling Connman Agent + * method calls. + */ + bool register_connect_data(char const * service_path, + JsonReader * reader, + response_callback const & response); + + /** * Get the properties for a specific technology. * * @param[in] technology Connman technology for which properties diff --git a/plugins/connman/technology.cpp b/plugins/connman/technology.cpp index 2deaf5a..4a62cd3 100644 --- a/plugins/connman/technology.cpp +++ b/plugins/connman/technology.cpp @@ -217,10 +217,19 @@ ivi::settings::technology::connect(JsonReader * reader, /// @todo Refactor malformed JSON request handling code. if (service_path != nullptr) { - service s(service_path, - connman_.connection(), - event_callback_); - s.connect(response); + // This call must bump the ref count on the reader! + // The response_callback should be copied, too! + if (manager_.register_connect_data(service_path, + reader, + response)) { + service s(service_path, + connman_.connection(), + event_callback_); + s.connect(response); + } else { + response.send_error(std::string("Connection already pending: ") + + service_path); + } } else { response.send_error( "Malformed " + technology_ + " connect request value."); -- 2.7.4