Initial support for event reporting.
authorOssama Othman <ossama.othman@intel.com>
Fri, 4 Oct 2013 20:40:24 +0000 (13:40 -0700)
committerOssama Othman <ossama.othman@intel.com>
Fri, 4 Oct 2013 20:40:24 +0000 (13:40 -0700)
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
include/settingsd/Makefile.am
include/settingsd/event_callback.hpp [new file with mode: 0644]
include/settingsd/response_callback.hpp
include/settingsd/send_callback.hpp [new file with mode: 0644]
lib/Makefile.am
lib/event_callback.cpp [new file with mode: 0644]
lib/manager.cpp
lib/response_callback.cpp
lib/send_callback.cpp [new file with mode: 0644]
src/websocket_server.cpp

index c81f8a1..eb43239 100644 (file)
@@ -22,6 +22,8 @@ pkginclude_HEADERS =          \
        settings_api.hpp        \
        plugin.hpp              \
        registrar.hpp           \
+       send_callback.hpp       \
+       event_callback.hpp      \
        response_callback.hpp   \
        glib_traits.hpp         \
        json_glib_traits.hpp    \
diff --git a/include/settingsd/event_callback.hpp b/include/settingsd/event_callback.hpp
new file mode 100644 (file)
index 0000000..8c02918
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * @file event_callback.hpp
+ *
+ * @brief Settings event callback 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;
+ * 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
+ */
+
+
+#ifndef IVI_SETTINGS_EVENT_CALLBACK_HPP
+#define IVI_SETTINGS_EVENT_CALLBACK_HPP
+
+#include <settingsd/settings_api.hpp>
+#include <settingsd/send_callback.hpp>
+
+#include <string>
+#include <functional>
+
+
+namespace ivi
+{
+  namespace settings
+  {
+    template<typename T> class smart_ptr;
+
+    /**
+     * @class event_callback event_callback.hpp <settingsd/event_callback.hpp>
+     *
+     * @brief Callback that handles sending event to Settings app.
+     *
+     * A @c event_callback sends a JSON formatted event string
+     * to the Settings app.  It is up to the specific settings plugin
+     * to decide what goes in to the event.
+    */
+    class SETTINGS_API event_callback
+    {
+    public:
+
+      /// Constructor
+      event_callback(libwebsocket * wsi);
+
+      /**
+       * Send event to Settings app.
+       *
+       * The settings daemon requires that plugins use the json-glib
+       * library to build JSON event strings.  Plugins will pass a
+       * callback function @a event_builder that uses to the
+       * json-glib high level "builder" API to append the event to the
+       * JSON event string.  Plugins should take care to only use the
+       * builder functions that add members and their corresponding
+       * values.  They should not attempt to start or end the top
+       * level JSON object.  That will be automatically handled by
+       * this class.
+       *
+       * @param[in] type          Setting type, e.g. @c "wifi".
+       * @param[in] event_builder Callback function that appends JSON
+       *                          formatted event data.
+       */
+      bool send_event(
+        std::string const & type,
+        std::function<void(JsonBuilder *)> event_builder);
+
+    private:
+
+      /**
+       * Begin the JSON formatted event to the Settings app
+       * request.
+       *
+       * The appropriate "header" information will be prepended to the
+       * event.
+       *
+       * @param[in] result @c "succeeded" or @c "failed"
+       */
+      smart_ptr<JsonBuilder> begin_event(std::string const & type);
+
+      /**
+       * End the JSON formatted event to the Settings app request.
+       */
+      void end_event(smart_ptr<JsonBuilder> const & builder);
+
+    private:
+
+      /// Object used to send event to client over WebSocket.
+      send_callback writer_;
+
+    };
+
+  }
+}
+
+#endif  /* IVI_SETTINGS_EVENT_CALLBACK_HPP */
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index 3c59a79..083bd54 100644 (file)
@@ -6,7 +6,7 @@
  * @author Ossama Othman @<ossama.othman@@intel.com@>
  *
  * @copyright @par
- * Copyright 2012, 2013 Intel Corporation All Rights Reserved.
+ * 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
 #define IVI_SETTINGS_RESPONSE_CALLBACK_HPP
 
 #include <settingsd/settings_api.hpp>
+#include <settingsd/send_callback.hpp>
 
-#include <libwebsockets.h>
-#include <json-glib/json-glib.h>
-
-#include <functional>
 #include <string>
+#include <functional>
 
 
 namespace ivi
@@ -57,26 +55,22 @@ namespace ivi
     public:
 
       /// Constructor
-      response_callback(struct libwebsocket * wsi,
+      response_callback(libwebsocket * wsi,
                         std::string type,
                         std::string transaction_id);
 
-      /// Destructor.
-      ~response_callback();
-
       /**
        * Send (successful) response to Settings app.
        *
        * The settings daemon requires that plugins use the json-glib
-       * library to build JSON respons strings.  Plugins will pass a
+       * library to build JSON response strings.  Plugins will pass a
        * callback function @a response_builder that uses to the
        * json-glib high level "builder" API to append the results of
        * the successful Settings app request to the JSON response
        * string.  Plugins should take care to only use the builder
-       * functions that add members and their corresponding to
-       * values.  They should not attempt to start or end the top
-       * level JSON object.  That will be automatically handled by
-       * this class.
+       * functions that add members and their corresponding values.
+       * They should not attempt to start or end the top level JSON
+       * object.  That will be automatically handled by this class.
        *
        * @param[in] response_builder Callback function that appends
        *                             JSON formatted response data.
@@ -127,19 +121,10 @@ namespace ivi
        */
       void end_response(smart_ptr<JsonBuilder> const & builder);
 
-      /**
-       * Send the JSON formatted response to the Settings app
-       * request over the corresponding websocket.
-       */
-      bool send_payload(smart_ptr<JsonBuilder> const & builder);
-
     private:
 
-      /**
-       * Pointer to the websocket through which the response will be
-       * sent to the Settings app.
-       */
-      struct libwebsocket * const wsi_;
+      /// Object used to send response to client over WebSocket.
+      send_callback writer_;
 
       /**
        * Settings type (e.g. "bluetooth", "wifi", etc).
diff --git a/include/settingsd/send_callback.hpp b/include/settingsd/send_callback.hpp
new file mode 100644 (file)
index 0000000..599358d
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * @file send_callback.hpp
+ *
+ * @brief Core send functionality for responses and events.
+ *
+ * @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
+ *
+ * @note This header is internal.
+ */
+
+
+#ifndef IVI_SETTINGS_SEND_CALLBACK_HPP
+#define IVI_SETTINGS_SEND_CALLBACK_HPP
+
+#include <libwebsockets.h>
+#include <json-glib/json-glib.h>
+
+
+namespace ivi
+{
+  namespace settings
+  {
+    template<typename T> class smart_ptr;
+
+    /**
+     * @class send_callback
+     *
+     * @brief Callback that handles sending response to Settings app.
+     *
+     * A @c send_callback sends a JSON formatted response string
+     * to the Settings app.  It is up to the specific settings plugin
+     * to decide what goes in to the response.
+     */
+    class send_callback
+    {
+    public:
+
+      /// Constructor
+      send_callback(libwebsocket * wsi);
+
+      /**
+       * Send the JSON formatted payload to the Settings app
+       * over the corresponding websocket.
+       *
+       * @param[in] send_type Type of payload, e.g. @c "response" or
+       *                      @c "event".
+       * @param[in] builder   JSON-GLib object containing the
+       *                      pre-marshalled (in-memory) payload.
+       */
+      bool send_payload(char const * send_type,
+                        smart_ptr<JsonBuilder> const & builder);
+
+    private:
+
+      /**
+       * Pointer to the websocket through which the payload will be
+       * sent to the Settings app.
+       */
+      libwebsocket * const wsi_;
+
+    };
+
+  }
+}
+
+#endif  /* IVI_SETTINGS_SEND_CALLBACK_HPP */
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index 276a61f..940386c 100644 (file)
@@ -25,6 +25,8 @@ libsettings_la_SOURCES =      \
        manager.cpp             \
        plugin.cpp              \
        registrar.cpp           \
+       send_callback.cpp       \
+       event_callback.cpp      \
        response_callback.cpp
 
 libsettings_la_CPPFLAGS = -DSETTINGS_BUILDING_DLL -I$(top_srcdir)/include
diff --git a/lib/event_callback.cpp b/lib/event_callback.cpp
new file mode 100644 (file)
index 0000000..f07a77f
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * @file event_callback.cpp
+ *
+ * @brief Settings plugin event_callback implementation.
+ *
+ * @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 <settingsd/event_callback.hpp>
+#include <settingsd/json_glib_traits.hpp>
+#include <settingsd/smart_ptr.hpp>
+
+
+ivi::settings::event_callback::event_callback(libwebsocket * wsi)
+  : writer_(wsi)
+{
+}
+
+bool
+ivi::settings::event_callback::send_event(
+  std::string const & type,
+  std::function<void(JsonBuilder *)> event_builder)
+{
+  smart_ptr<JsonBuilder> const builder = begin_event(type);
+
+  // Append settings type-specific JSON formatted events.
+  event_builder(builder.get());
+
+  end_event(builder);
+
+  bool const success = writer_.send_payload("event", builder);
+
+  if (!success)
+    g_critical("Unable to send %s event", type.c_str());
+
+  return success;
+}
+
+ivi::settings::smart_ptr<JsonBuilder>
+ivi::settings::event_callback::begin_event(std::string const & type)
+{
+  // Construct JSON event string.
+  smart_ptr<JsonBuilder> safe_builder(json_builder_new());
+  JsonBuilder * const builder = safe_builder.get();
+
+  json_builder_begin_object(builder);
+
+  json_builder_set_member_name(builder, "type");
+  if (type.empty())
+    json_builder_add_null_value(builder);
+  else
+    json_builder_add_string_value(builder, type.c_str());
+
+  return safe_builder;
+}
+
+void
+ivi::settings::event_callback::end_event(
+  ivi::settings::smart_ptr<JsonBuilder> const & builder)
+{
+  json_builder_end_object(builder.get());
+}
+
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index 0b497c9..c8d4357 100644 (file)
@@ -105,7 +105,8 @@ ivi::settings::manager::load_settings(std::string const & dir)
          * @todo I really hate catching an exception like this, but I
          *       really don't want to resort to a construct/init()
          *       style of object initialization.  Fix.
-         */std::cerr << "Error loading plugin: " << e.what() << "\n";
+         */
+        std::cerr << "Error loading plugin: " << e.what() << "\n";
       }
     }
 
index 6eb3eaa..0d56aa8 100644 (file)
@@ -6,7 +6,7 @@
  * @author Ossama Othman @<ossama.othman@@intel.com@>
  *
  * @copyright @par
- * Copyright 2012, 2013 Intel Corporation All Rights Reserved.
+ * 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
  */
 
 #include <settingsd/response_callback.hpp>
-#include <settingsd/glib_traits.hpp>
 #include <settingsd/json_glib_traits.hpp>
 #include <settingsd/smart_ptr.hpp>
 
-#include <cstring>
-#include <algorithm>
-#include <iostream>
-
 
 ivi::settings::response_callback::response_callback(
-  struct libwebsocket * wsi,
+  libwebsocket * wsi,
   std::string type,
   std::string transaction_id)
-  : wsi_(wsi)
+  : writer_(wsi)
   , type_(type)
   , transaction_id_(transaction_id)
 {
 }
 
-ivi::settings::response_callback::~response_callback()
-{
-}
-
 bool
 ivi::settings::response_callback::send_response(
   std::function<void(JsonBuilder *)> response_builder)
@@ -60,7 +51,16 @@ ivi::settings::response_callback::send_response(
 
   end_response(builder);
 
-  return send_payload(builder);
+  bool const success = writer_.send_payload("response", builder);
+
+  if (!success)
+    g_critical("Unable to send response for:\n"
+               "    type:          %s\n"
+               "    transactionid: %s\n",
+               type_.c_str(),
+               transaction_id_.c_str());
+
+  return success;
 }
 
 bool
@@ -73,7 +73,16 @@ ivi::settings::response_callback::send_error(std::string error_message)
 
   end_response(builder);
 
-  return send_payload(builder);
+  bool const success = writer_.send_payload("error", builder);
+
+  if (!success)
+    g_critical("Unable to send error for:\n"
+               "    type:          %s\n"
+               "    transactionid: %s\n",
+               type_.c_str(),
+               transaction_id_.c_str());
+
+  return success;
 }
 
 void
@@ -114,60 +123,6 @@ ivi::settings::response_callback::end_response(
   json_builder_end_object(builder.get());
 }
 
-bool
-ivi::settings::response_callback::send_payload(
-  ivi::settings::smart_ptr<JsonBuilder> const & builder)
-{
-  smart_ptr<JsonGenerator> const generator(json_generator_new());
-  smart_ptr<JsonNode> const root(json_builder_get_root(builder.get()));
-  json_generator_set_root(generator.get(), root.get());
-
-  gchar * const response =
-    json_generator_to_data(generator.get(), nullptr);
-
-  smart_ptr<gchar> safe_response(response);
-
-  if (response == nullptr) {
-    g_critical("Unable to generate JSON response for:\n"
-               "    type:          %s\n"
-               "    transactionid: %s\n",
-               type_.c_str(),
-               transaction_id_.c_str());
-
-    return false;
-  }
-
-  g_debug("Sending response: %s\n", response);
-
-  size_t const payload_len = strlen(response);
-
-  // libwebsockets wants a sequence of octets (unsigned char *) rather
-  // than characters.
-  typedef std::vector<unsigned char> vector_type;
-
-  vector_type::size_type const buf_len =
-    LWS_SEND_BUFFER_PRE_PADDING
-    + payload_len
-    + LWS_SEND_BUFFER_POST_PADDING;
-
-  vector_type buf(buf_len);
-  unsigned char * const payload =
-    buf.data() + LWS_SEND_BUFFER_PRE_PADDING;
-
-  // Copy the string into the buffer after libwebsockets pre-padding.
-  std::copy(response,
-            response + payload_len,
-            payload);
-
-  int const count = libwebsocket_write(wsi_,
-                                       payload,
-                                       payload_len,
-                                       LWS_WRITE_TEXT);
-
-  return count >= 0;
-}
-
-
 
 // Local Variables:
 // mode:c++
diff --git a/lib/send_callback.cpp b/lib/send_callback.cpp
new file mode 100644 (file)
index 0000000..878f3ac
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * @file send_callback.cpp
+ *
+ * @brief Core send functionality for responses and events.
+ *
+ * @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 <settingsd/send_callback.hpp>
+#include <settingsd/glib_traits.hpp>
+#include <settingsd/json_glib_traits.hpp>
+#include <settingsd/smart_ptr.hpp>
+
+#include <cstring>
+#include <vector>
+#include <algorithm>
+
+
+ivi::settings::send_callback::send_callback(libwebsocket * wsi)
+  : wsi_(wsi)
+{
+}
+
+bool
+ivi::settings::send_callback::send_payload(
+  char const * send_type,
+  ivi::settings::smart_ptr<JsonBuilder> const & builder)
+{
+  smart_ptr<JsonGenerator> const generator(json_generator_new());
+  smart_ptr<JsonNode> const root(json_builder_get_root(builder.get()));
+  json_generator_set_root(generator.get(), root.get());
+
+  gchar * const data =
+    json_generator_to_data(generator.get(), nullptr);
+
+  smart_ptr<gchar> safe_data(data);
+
+  if (data == nullptr) {
+    g_critical("Unable to generate JSON formatted %s payload:\n",
+               send_type);
+
+    return false;
+  }
+
+  g_debug("Sending %s: %s\n", send_type, data);
+
+  size_t const payload_len = strlen(data);
+
+  // libwebsockets wants a sequence of octets (unsigned char *) rather
+  // than characters.
+  typedef std::vector<unsigned char> vector_type;
+
+  vector_type::size_type const buf_len =
+    LWS_SEND_BUFFER_PRE_PADDING
+    + payload_len
+    + LWS_SEND_BUFFER_POST_PADDING;
+
+  vector_type buf(buf_len);
+  unsigned char * const payload =
+    buf.data() + LWS_SEND_BUFFER_PRE_PADDING;
+
+  // Copy the string into the buffer after libwebsockets pre-padding.
+  std::copy(data,
+            data + payload_len,
+            payload);
+
+  int const count = libwebsocket_write(wsi_,
+                                       payload,
+                                       payload_len,
+                                       LWS_WRITE_TEXT);
+
+  return count >= 0;
+}
+
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
index e454839..69fbfeb 100644 (file)
@@ -53,6 +53,10 @@ namespace
         libwebsocket_context_user(context));
 
     switch(reason) {
+    case LWS_CALLBACK_ESTABLISHED:
+      // Enable event dispatching to client.
+      
+      break;
     case LWS_CALLBACK_RECEIVE:
       // Request has come in from Settings app.  Pass it on to the
       // settings manager.