Implemented connman Agent stub/placeholder.
authorOssama Othman <ossama.othman@intel.com>
Mon, 14 Oct 2013 23:03:52 +0000 (16:03 -0700)
committerOssama Othman <ossama.othman@intel.com>
Mon, 14 Oct 2013 23:03:52 +0000 (16:03 -0700)
Change-Id: I0f53f4eaade53d06b20f24b66d327e3592b8ba66
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
.gitignore
packaging/settingsd.spec
plugins/connman/Makefile.am
plugins/connman/agent.cpp [new file with mode: 0644]
plugins/connman/agent.hpp [new file with mode: 0644]
plugins/connman/connman_manager.cpp
plugins/connman/connman_manager.hpp
plugins/connman/settings-agent.conf.in [new file with mode: 0644]

index a1c8282..3d01d77 100644 (file)
@@ -28,6 +28,7 @@ src/settingsd
 tests/settings_test
 config.*
 !plugins/connman/config.h
+plugins/connman/settings-agent.conf
 !packaging/settingsd.socket
 *.tar.*
 doc/doxygen
index c3f0c32..f8aa216 100644 (file)
@@ -82,6 +82,7 @@ ln -sf ../settingsd.service %{buildroot}/%{_unitdir_user}/weston.target.wants/
 %{_libdir}/libsettings.so.*
 %{pkglibdir}/*.so
 %config %{_sysconfdir}/%{name}/*
+%config %{_sysconfdir}/dbus-1/system.d/settings-agent.conf
 %{_unitdir_user}/settingsd.service
 %{_unitdir_user}/weston.target.wants/settingsd.service
 
index e87ac62..6cf0481 100644 (file)
@@ -32,6 +32,11 @@ IVI_SETTINGS_PLUGIN_CPPFLAGS = \
 
 IVI_SETTINGS_PLUGIN_LIBRARY = $(top_builddir)/lib/libsettings.la
 
+## The D-Bus name that will be owned by the settings daemon's connman
+## Agent.
+IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME = \
+       "$(IVI_SETTINGS_DBUS_NAME).connman.Agent"
+
 connman_la_SOURCES =           \
        dbus_connection.cpp     \
        connman.cpp             \
@@ -42,6 +47,7 @@ connman_la_SOURCES =          \
        clock.cpp               \
        ethernet.cpp            \
        wifi.cpp                \
+       agent.cpp               \
        registration.cpp        \
        $(BUILT_SOURCES)
 connman_la_CXXFLAGS = \
@@ -51,7 +57,9 @@ connman_la_CXXFLAGS = \
 connman_la_CFLAGS =                    \
        $(IVI_SETTINGS_PLUGIN_CFLAGS)   \
        $(GIO_CFLAGS)
-connman_la_CPPFLAGS = $(IVI_SETTINGS_PLUGIN_CPPFLAGS) 
+connman_la_CPPFLAGS = \
+       $(IVI_SETTINGS_PLUGIN_CPPFLAGS) \
+       -DIVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME='$(IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME)'
 connman_la_LIBADD   = $(IVI_SETTINGS_PLUGIN_LIBRARY)
 connman_la_LDFLAGS  = -no-undefined   \
                       -module         \
@@ -70,7 +78,8 @@ noinst_HEADERS =              \
        bluetooth.hpp           \
        clock.hpp               \
        ethernet.hpp            \
-       wifi.hpp
+       wifi.hpp                \
+       agent.hpp
 
 dbus_codegen_verbose = $(dbus_codegen_verbose_$(V))
 dbus_codegen_verbose_ = $(dbus_codegen_verbose_$(AM_DEFAULT_VERBOSITY))
@@ -85,9 +94,32 @@ BUILT_SOURCES = \
        agent-glue.c \
        agent-glue.h
 
-CLEANFILES = $(BUILT_SOURCES)
+dbussystemconf_DATA = settings-agent.conf
+dbussystemconfdir = $(sysconfdir)/dbus-1/system.d/
+
+## Silent mode output for settingsd config file generation.
+config_verbose = $(config_verbose_$(V))
+config_verbose_ = $(config_verbose_$(AM_DEFAULT_VERBOSITY))
+config_verbose_0 = @echo CONFGEN $@;
+
+agent_name = $(IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME)
+
+## The configure script won't fully expand $libdir so leverage `make'
+## based variable expansion instead.
+settings-agent.conf: Makefile settings-agent.conf.in
+       $(config_verbose)rm -f $@ $@.tmp; \
+       srcdir=''; \
+               test -f ./$@.in || srcdir=$(srcdir)/; \
+               sed \
+                       -e 's,@agent_name[@],$(agent_name),g' \
+                       $${srcdir}$@.in >$@.tmp; \
+       chmod 644 $@.tmp; \
+       mv $@.tmp $@
+
+
+CLEANFILES = $(BUILT_SOURCES) settings-agent.conf
 
 dist-hook:
        cd $(distdir); rm -f $(BUILT_SOURCES)
 
-EXTRA_DIST = agent.xml
+EXTRA_DIST = agent.xml settings-agent.conf.in
diff --git a/plugins/connman/agent.cpp b/plugins/connman/agent.cpp
new file mode 100644 (file)
index 0000000..55bfb6d
--- /dev/null
@@ -0,0 +1,209 @@
+/**
+ * @file agent.cpp
+ *
+ * @brief Settings daemon D-Bus connection adapter.
+ *
+ * @author Michael Leibowitz @<michael.leibowitz@@intel.com@>
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ */
+
+#include "agent.hpp"
+#include "../../lib/config.hpp"
+
+#include <settingsd/glib_traits.hpp>
+#include <settingsd/unique_ptr.hpp>
+
+#include <string>
+#include <algorithm>
+#include <stdexcept>
+
+
+namespace
+{
+  // --------------------------------------------------------------
+  //                  D-Bus Name Acquisition
+  // --------------------------------------------------------------
+  /**
+   * @brief Callback function invoked when a D-Bus name is acquired.
+   *
+   * @param[in] connection The D-Bus connection on which the name was
+   *                       acquired.
+   * @param[in] name       The name being owned.
+   * @param[in] user_data  User-provided data.
+   */
+  void
+  on_name_acquired(GDBusConnection * /* connection */,
+                   gchar const * name,
+                   gpointer /* user_data */)
+  {
+    g_debug("Name \"%s\" acquired on D-Bus.\n", name);
+  }
+
+  /**
+   * @brief Callback function invoked when a D-Bus name is no longer
+   *        owned or the D-Bus connection has been closed.
+   *
+   * @param[in] connection The D-Bus connection on which the name was
+   *                       acquired.
+   * @param[in] name       The name being owned.
+   * @param[in] user_data  User-provided data.
+   *
+   */
+  void
+  on_name_lost(GDBusConnection * /* connection */,
+               gchar const * name,
+               gpointer /* user_data */)
+  {
+    // This can happen if the appropriate D-Bus policy is not
+    // installed, for example.
+    throw std::runtime_error(std::string("Lost name \"")
+                             + name + "\" on D-Bus!");
+  }
+
+  // --------------------------------------------------------------
+  //                   Connman Agent Handlers
+  // --------------------------------------------------------------
+  gboolean
+  on_handle_release(Agent * /* object */,
+                    GDBusMethodInvocation * /* invocation */)
+  {
+    return true;
+  }
+
+  gboolean
+  on_handle_report_error(Agent * /* object */,
+                         GDBusMethodInvocation * /* invocation */,
+                         gchar const * /* service */,
+                         gchar const * /* error */)
+  {
+    return true;
+  }
+
+  gboolean
+  on_handle_request_browser(Agent * /* object */,
+                            GDBusMethodInvocation * /* invocation */,
+                            gchar const * /* service */,
+                            gchar const * /* url */)
+  {
+    return true;
+  }
+
+  gboolean
+  on_handle_request_input(Agent * /* object */,
+                          GDBusMethodInvocation * /* invocation */,
+                          gchar const * /* service */,
+                          GVariant * /* fields */)
+  {
+    // The method return value will contain a dictionary of the
+    // requested input fields.
+
+    return true;
+  }
+
+  gboolean
+  on_handle_cancel(Agent * /* object */,
+                   GDBusMethodInvocation * /* invocation */)
+  {
+    return true;
+  }
+}
+
+// ----------------------------------------------------------------
+
+ivi::settings::agent::agent(GDBusConnection * connection)
+  : owner_id_(
+      // The bus name will be of the form:
+      //     "org.tizen.settingsd.connman.Agent"
+      g_bus_own_name_on_connection(connection,
+                                   IVI_SETTINGS_CONNMAN_AGENT_DBUS_NAME,
+                                   G_BUS_NAME_OWNER_FLAGS_NONE,
+                                   on_name_acquired,
+                                   on_name_lost,
+                                   nullptr, // user_data,
+                                   nullptr))
+  , interface_(agent_skeleton_new())
+  , object_path_("/" IVI_SETTINGS_DBUS_NAME "/connman/Agent")
+{
+  // Construct object path of the form:
+  //     /org/tizen/settingsd/connman/Agent"
+  std::replace(object_path_.begin(), object_path_.end(), '.', '/');
+
+  // Connect the signal handlers corresponding to the Agent
+  // interface.
+  g_signal_connect(interface_,
+                   "handle-release",
+                   G_CALLBACK(on_handle_release),
+                   nullptr);
+
+  g_signal_connect(interface_,
+                   "handle-report-error",
+                   G_CALLBACK(on_handle_report_error),
+                   nullptr);
+
+  g_signal_connect(interface_,
+                   "handle-request-browser",
+                   G_CALLBACK(on_handle_request_browser),
+                   nullptr);
+
+  g_signal_connect(interface_,
+                   "handle-request-input",
+                   G_CALLBACK(on_handle_request_input),
+                   nullptr);
+
+  g_signal_connect(interface_,
+                   "handle-cancel",
+                   G_CALLBACK(on_handle_cancel),
+                   nullptr);
+
+  GError * error = nullptr;
+  if (!g_dbus_interface_skeleton_export(
+        G_DBUS_INTERFACE_SKELETON(interface_),
+        connection,
+        object_path_.c_str(),
+        &error)) {
+    unique_ptr<GError> safe_error(error);
+    throw std::runtime_error(error->message);
+  }
+}
+
+ivi::settings::agent::~agent()
+{
+  if (interface_ != nullptr) {
+    g_dbus_interface_skeleton_unexport(
+      G_DBUS_INTERFACE_SKELETON(interface_));
+    g_object_unref(interface_);
+  }
+
+  g_bus_unown_name(owner_id_);
+}
+
+char const *
+ivi::settings::agent::object_path() const
+{
+  return object_path_.c_str();
+}
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
diff --git a/plugins/connman/agent.hpp b/plugins/connman/agent.hpp
new file mode 100644 (file)
index 0000000..dfb6e3b
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * @file agent.hpp
+ *
+ * @brief Connman agent implementation header.
+ *
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * @note This is an internal header.
+ */
+
+#ifndef IVI_SETTINGS_AGENT_HPP
+#define IVI_SETTINGS_AGENT_HPP
+
+#include "agent-glue.h"
+
+#include <string>
+
+#include <gio/gio.h>
+
+namespace ivi
+{
+  namespace settings
+  {
+    class agent
+    {
+    public:
+
+      /**
+       * Constructor.
+       *
+       * @param[in] connection D-Bus connection on which agent will be
+       *                       exported.
+       */
+      agent(GDBusConnection *connection);
+
+      /// Destructor.
+      ~agent();
+
+      /// Get D-Bus object path for this @c Agent.
+      char const * object_path() const;
+
+    private:
+
+      /**
+       * @name Prevent copying
+       */
+      //@{
+      agent(agent const &) = delete;
+      agent & operator=(agent const &) = delete;
+      //@}
+
+    private:
+
+      /// ID corresponding to owned name on D-Bus system bus.
+      guint const owner_id_;
+
+      /// GDBus Agent skeleton object.
+      Agent * const interface_;
+
+      /// D-Bus object path for this @c Agent.
+      std::string object_path_;
+
+    };
+  }
+}
+
+#endif  /* IVI_SETTINGS_AGENT_HPP */
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index f1c13a1..cb03c54 100644 (file)
  */
 
 #include "connman_manager.hpp"
-#include "dbus_connection.hpp"
 
 #include <settingsd/dbus_signal_callback.hpp>
 #include <settingsd/glib_traits.hpp>
 #include <settingsd/unique_ptr.hpp>
 
 #include <cstring>
+#include <stdexcept>
 
 
 ivi::settings::connman_manager::connman_manager(
@@ -41,6 +41,7 @@ ivi::settings::connman_manager::connman_manager(
              "/",                       // Object path
              connection,
              e)
+  , agent_(connection)
   , event_callback_(e)
   , subscription_id_(
       g_dbus_connection_signal_subscribe(
@@ -55,18 +56,49 @@ ivi::settings::connman_manager::connman_manager(
         &event_callback_,
         nullptr))
 {
-  // The ServicesChanged signal parameters are:
-  //
-  //   array{object, dict}, array{object})
-  //
-  // where "object" is the D-Bus object path, and "dict" is a
-  // dictionary of object-specific properties.  The first parameter is
-  // list of changed services.  The second is a list of removed
-  // services.
+  // Register the Agent implementation responsible for handling input
+  // requests for secure and hidden networks.
+  if (!g_variant_is_object_path(agent_.object_path())) {
+    throw std::runtime_error(std::string("Invalid Agent object path: ")
+                             + agent_.object_path());
+  }
+
+  GError * error = nullptr;
+
+  unique_ptr<GVariant> const ret(
+    call_method("RegisterAgent",
+                g_variant_new("(o)",
+                              agent_.object_path()),
+                error));
+
+  if (ret == nullptr) {
+    unique_ptr<GError> const safe_error(error);
+
+     throw std::runtime_error(
+       std::string("Unable to register agent: ") + error->message);
+  }
 }
 
 ivi::settings::connman_manager::~connman_manager()
 {
+  // Unregister agent.
+  if (g_variant_is_object_path(agent_.object_path())) {
+    GError * error = nullptr;
+
+    unique_ptr<GVariant> const ret(
+      call_method("UnregisterAgent",
+                  g_variant_new("(o)",
+                                agent_.object_path()),
+                  error));
+
+    if (ret == nullptr) {
+      unique_ptr<GError> const safe_error(error);
+
+      g_warning("Unable to unregister agent: %s\n", error->message);
+    }
+  }
+
+  // Unsubscribe from ServicesChanged signal.
   g_dbus_connection_signal_unsubscribe(connman_.connection(),
                                        subscription_id_);
 }
@@ -76,16 +108,10 @@ ivi::settings::connman_manager::get_properties(
   std::string const & technology,
   GError *& error) const
 {
-  constexpr gint const timeout = 5000;  // milliseconds
-
   unique_ptr<GVariant> const dictionary(
-    g_dbus_proxy_call_sync(connman_.proxy(),
-                           "GetTechnologies",
-                           nullptr,  // No parameters
-                           G_DBUS_CALL_FLAGS_NONE,
-                           timeout,
-                           nullptr,  // Not cancellable
-                           &error));
+    call_method("GetTechnologies",
+                nullptr,  // No parameters,
+                error));
 
   if (dictionary != nullptr) {
     GVariantIter * i = nullptr;
@@ -124,17 +150,32 @@ ivi::settings::connman_manager::get_properties(
 GVariant *
 ivi::settings::connman_manager::get_services(GError *& error) const
 {
+  return call_method("GetServices",
+                     nullptr,  // No parameters,
+                     error);
+}
+
+GVariant *
+ivi::settings::connman_manager::call_method(char const * name,
+                                            GVariant * parameters,
+                                            GError *& error) const
+{
   constexpr gint const timeout = 5000;  // milliseconds
 
-  return g_dbus_proxy_call_sync(connman_.proxy(),
-                                "GetServices",
-                                nullptr,  // No parameters
-                                G_DBUS_CALL_FLAGS_NONE,
-                                timeout,
-                                nullptr,  // Not cancellable
-                                &error);
-}
+  GVariant * const ret =
+    g_dbus_proxy_call_sync(connman_.proxy(),
+                           name,     // "GetTechnologies", ...
+                           parameters,
+                           G_DBUS_CALL_FLAGS_NONE,
+                           timeout,
+                           nullptr,  // Not cancellable
+                           &error);
+
+  if (ret == nullptr)
+    g_critical("THE ERROR: %s\n", error->message);
 
+  return ret;
+}
 
 // Local Variables:
 // mode:c++
index 27b5f64..48967f9 100644 (file)
@@ -28,6 +28,7 @@
 #define IVI_SETTINGS_CONNMAN_MANAGER_HPP
 
 #include "connman.hpp"
+#include "agent.hpp"
 
 #include <settingsd/event_callback.hpp>
 
@@ -88,9 +89,31 @@ namespace ivi
 
     private:
 
+      /**
+       * Call the method @a name on the connman Manager object.
+       *
+       * @param[in]    name       The connman Manager object method
+       *                          name.
+       * @param[in]    parameters Method parameters.
+       * @param[inout] error      Pointer to error object containing
+       *                          failure related information.  Caller
+       *                          must deallocate if it is not null.
+       */
+      GVariant * call_method(char const * name,
+                             GVariant * parameters,
+                             GError *& error) const;
+
+    private:
+
       /// The proxy used to access the connman Manager D-Bus API.
       connman connman_;
 
+      /**
+       * The connman Agent implemention that handles secure and
+       * hidden network related requests.
+       */
+      agent agent_;
+
       /// Callback through which events will be sent to clients.
       event_callback event_callback_;
 
diff --git a/plugins/connman/settings-agent.conf.in b/plugins/connman/settings-agent.conf.in
new file mode 100644 (file)
index 0000000..cf8651d
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!-- D-Bus policy for settingsd connman Agent implementation. -->
+<busconfig>
+  <policy context="default">
+    <allow own=@agent_name@/>
+    <allow send_destination=@agent_name@/>
+    <allow send_destination="net.connman"
+          send_interface="net.connman.Manager"/>
+  </policy>
+</busconfig>