Expanded connman agent implementation.
authorOssama Othman <ossama.othman@intel.com>
Mon, 21 Oct 2013 06:28:44 +0000 (23:28 -0700)
committerOssama Othman <ossama.othman@intel.com>
Mon, 21 Oct 2013 06:28:44 +0000 (23:28 -0700)
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
plugins/connman/agent.cpp
plugins/connman/agent.hpp
plugins/connman/agent.xml
plugins/connman/connman_manager.cpp
plugins/connman/connman_manager.hpp
plugins/connman/technology.cpp

index 55bfb6d..cde53ab 100644 (file)
@@ -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<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);
+      }
+    }
+
+    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<std::mutex> guard(data_.lock);
+
+  auto const result =
+    data_.info.emplace(std::make_pair(service_path,
+                                      connect_data(reader, response)));
+
+  return result.second;
 }
 
 
index dfb6e3b..4931942 100644 (file)
 
 #include "agent-glue.h"
 
+#include <settingsd/response_callback.hpp>
+
+
 #include <string>
+#include <map>
+#include <mutex>
 
-#include <gio/gio.h>
 
 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<JsonReader *>(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<JsonReader> 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<std::string, connect_data> 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_;
+
     };
   }
 }
index 1ba7ae2..2435573 100644 (file)
@@ -49,6 +49,7 @@
     <method name="RequestInput">
       <arg name="service" direction="in" type="o"/>
       <arg name="fields" direction="in" type="a{sv}"/>
+      <arg name="response" direction="out" type="a{sv}"/>
     </method>
 
     <method name="Cancel"/>
index cb03c54..ffb361a 100644 (file)
@@ -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<GVariant> 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,
index 48967f9..2845d6b 100644 (file)
@@ -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
index 2deaf5a..4a62cd3 100644 (file)
@@ -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.");