incremental
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae75e5d..db4df43 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -153,6 +153,10 @@
# PAM
find_package(PAM REQUIRED)
+# Boost-dbus
+add_subdirectory(boost-dbus)
+include_directories(boost-dbus/include)
+
set(WEBSERVER_MAIN src/webserver_main.cpp)
set(HDR_FILES
@@ -221,21 +225,23 @@
add_subdirectory(googletest)
#find_package(GMock CONFIG REQUIRED)
- add_executable(unittest ${HDR_FILES} ${SRC_FILES} ${UT_FILES})
- target_link_libraries(unittest gmock gtest)
- target_link_libraries(unittest pthread)
- target_link_libraries(unittest g3logger)
+ add_executable(webtest ${HDR_FILES} ${SRC_FILES} ${UT_FILES})
+ target_link_libraries(webtest gmock gtest)
+ target_link_libraries(webtest pthread)
+ target_link_libraries(webtest g3logger)
- target_link_libraries(unittest ${OPENSSL_LIBRARIES})
- target_link_libraries(unittest ${ZLIB_LIBRARIES})
- target_link_libraries(unittest pam)
- add_dependencies(unittest packagestaticcpp)
-
+ target_link_libraries(webtest ${OPENSSL_LIBRARIES})
+ target_link_libraries(webtest ${ZLIB_LIBRARIES})
+ target_link_libraries(webtest pam)
+ add_dependencies(webtest packagestaticcpp)
+ add_test(webtest webtest "--gtest_output=xml:webtest.xml")
+
endif(${BUILD_UT})
# web static assets
add_subdirectory(static)
+
# bmcweb
add_executable(bmcweb ${WEBSERVER_MAIN} ${HDR_FILES} ${SRC_FILES})
target_link_libraries(bmcweb pthread)
@@ -247,14 +253,6 @@
add_dependencies(bmcweb packagestaticcpp)
install (TARGETS bmcweb DESTINATION bin)
-# dbus
-add_executable(dbus_test src/dbus_main.cpp)
-target_link_libraries(dbus_test ${DBUS_LIBRARIES})
-
-# udpclient
-#add_executable(udpclient src/udpclient.cpp)
-#target_link_libraries(udpclient pthread)
-
add_executable(getvideo src/getvideo_main.cpp)
target_link_libraries(getvideo pthread)
target_link_libraries(getvideo g3logger)
diff --git a/boost-dbus/.clang-format b/boost-dbus/.clang-format
new file mode 100644
index 0000000..6f1017f
--- /dev/null
+++ b/boost-dbus/.clang-format
@@ -0,0 +1,98 @@
+---
+BasedOnStyle: Google
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: true
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeCategories:
+
+ - Regex: '^[<"](crow)'
+ Priority: 5
+ - Regex: '^[<"](boost)'
+ Priority: 6
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 7
+ - Regex: '^<.*\.h>'
+ Priority: 1
+ - Regex: '^<.*\.hpp>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Auto
+TabWidth: 8
+UseTab: Never
+...
+
diff --git a/boost-dbus/.gitignore b/boost-dbus/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/boost-dbus/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/boost-dbus/CMakeLists.txt b/boost-dbus/CMakeLists.txt
new file mode 100644
index 0000000..9d07a5b
--- /dev/null
+++ b/boost-dbus/CMakeLists.txt
@@ -0,0 +1,50 @@
+# Copyright (c) Benjamin Kietzman (github.com/bkietz)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+project(boost-dbus CXX)
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+###############
+# CMake options
+cmake_minimum_required(VERSION 2.8)
+
+###############
+# C++ options
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")#-std=c++0x")
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/test)
+
+###############
+# import Boost
+find_package(Boost REQUIRED)
+include_directories(${Boost_INCLUDE_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+
+###############
+# import D-Bus
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(DBus dbus-1)
+include_directories(${DBus_INCLUDE_DIRS})
+link_directories(${DBus_LIBRARY_DIRS})
+
+##############
+# import GTest
+find_package(GTest REQUIRED)
+include_directories(${GTEST_INCLUDE_DIRS})
+
+##############
+# Tests
+enable_testing()
+
+
+add_executable(dbustests "test/avahi.cpp" "test/message.cpp")
+target_link_libraries(dbustests ${Boost_LIBRARIES})
+target_link_libraries(dbustests ${DBus_LIBRARIES})
+target_link_libraries(dbustests ${GTEST_BOTH_LIBRARIES} gmock)
+target_link_libraries(dbustests -pthread)
+add_test(dbustests dbustests "--gtest_output=xml:${test_name}.xml")
+
diff --git a/boost-dbus/LICENSE_1_0.txt b/boost-dbus/LICENSE_1_0.txt
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/boost-dbus/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/boost-dbus/README.md b/boost-dbus/README.md
new file mode 100644
index 0000000..0887854
--- /dev/null
+++ b/boost-dbus/README.md
@@ -0,0 +1,55 @@
+Boost D-Bus
+===========
+
+This is a simple D-Bus binding powered by Boost.Asio.
+As far as possible, I try to follow Asio's idioms.
+
+Code Sample
+-----------
+
+```c++
+#include <iostream>
+
+#include <boost/asio.hpp>
+#include <dbus.hpp>
+
+using namespace std;
+using namespace boost::asio;
+using boost::system::error_code;
+
+struct logger
+{
+ void operator()(error_code ec, message m)
+ {
+ cout << m << endl;
+ }
+};
+
+void main()
+{
+ io_service io;
+ dbus::proxy avahi(io,
+ dbus::endpoint(
+ "org.freedesktop.Avahi", // proxied object process
+ "/", // proxied object path
+ "org.freedesktop.Avahi.Server")); // interface
+
+ dbus::message browser_spec(-1, -1,
+ "_http._tcp", "local", unsigned(0));
+
+ dbus::message response =
+ avahi.call("ServiceBrowserNew", browser_spec);
+
+ dbus::proxy browser(io,
+ dbus::endpoint(
+ "org.freedesktop.Avahi",
+ response.get(0),
+ "org.freedesktop.Avahi.ServiceBrowser"));
+
+ browser.async_receive("ItemNew", logger());
+
+ io.run();
+}
+
+
+```
diff --git a/boost-dbus/include/dbus/connection.hpp b/boost-dbus/include/dbus/connection.hpp
new file mode 100644
index 0000000..a7185a5
--- /dev/null
+++ b/boost-dbus/include/dbus/connection.hpp
@@ -0,0 +1,130 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_CONNECTION_HPP
+#define DBUS_CONNECTION_HPP
+
+#include <dbus/connection_service.hpp>
+#include <dbus/element.hpp>
+#include <dbus/message.hpp>
+#include <chrono>
+#include <string>
+#include <boost/asio.hpp>
+
+namespace dbus {
+
+class filter;
+class match;
+
+/// Root D-Bus IO object
+/**
+ * A connection to a bus, through which messages may be sent or received.
+ */
+class connection : public boost::asio::basic_io_object<connection_service> {
+ public:
+ /// Open a connection to a specified address.
+ /**
+ * @param io_service The io_service object that the connection will use to
+ * wire D-Bus for asynchronous operation.
+ *
+ * @param address The address of the bus to connect to.
+ *
+ * @throws boost::system::system_error When opening the connection failed.
+ */
+ connection(boost::asio::io_service& io, const string& address)
+ : basic_io_object<connection_service>(io) {
+ this->get_service().open(this->get_implementation(), address);
+ }
+
+ /// Open a connection to a well-known bus.
+ /**
+ * D-Bus connections are usually opened to well-known buses like the
+ * system or session bus.
+ *
+ * @param bus The well-known bus to connect to.
+ *
+ * @throws boost::system::system_error When opening the connection failed.
+ */
+ // TODO: change this unsigned to an enumeration
+ connection(boost::asio::io_service& io, const int bus)
+ : basic_io_object<connection_service>(io) {
+ this->get_service().open(this->get_implementation(), bus);
+ }
+
+ /// Send a message.
+ /**
+ * @param m The message to send.
+ *
+ * @return The reply received.
+ *
+ * @throws boost::system::system_error When the response timed out or
+ * there was some other error.
+ */
+ message send(message& m) {
+ return this->get_service().send(this->get_implementation(), m);
+ }
+
+ /// Send a message.
+ /**
+ * @param m The message to send.
+ *
+ * @param t Time to wait for a reply. Passing 0 as the timeout means
+ * that you wish to ignore the reply. (Or catch it later somehow...)
+ *
+ * @return The reply received.
+ *
+ * @throws boost::system::system_error When the response timed out (if
+ * timeout was not 0), or there was some other error.
+ */
+ template <typename Duration>
+ message send(message& m, const Duration& t) {
+ return this->get_service().send(this->get_implementation(), m, t);
+ }
+
+ /// Send a message asynchronously.
+ /**
+ * @param m The message to send.
+ *
+ * @param handler Handler for the reply.
+ *
+ * @return Asynchronous result
+ */
+ template <typename MessageHandler>
+ inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
+ void(boost::system::error_code, message))
+ async_send(message& m, BOOST_ASIO_MOVE_ARG(MessageHandler) handler) {
+ return this->get_service().async_send(
+ this->get_implementation(), m,
+ BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
+ }
+
+ /// Create a new match.
+ void new_match(match& m) {
+ this->get_service().new_match(this->get_implementation(), m);
+ }
+
+ /// Destroy a match.
+ void delete_match(match& m) {
+ this->get_service().delete_match(this->get_implementation(), m);
+ }
+
+ /// Create a new filter.
+ void new_filter(filter& f) {
+ this->get_service().new_filter(this->get_implementation(), f);
+ }
+
+ /// Destroy a filter.
+ void delete_filter(filter& f) {
+ this->get_service().delete_filter(this->get_implementation(), f);
+ }
+
+ // FIXME the only way around this I see is to expose start() here, which seems
+ // ugly
+ friend class filter;
+};
+
+} // namespace dbus
+
+#endif // DBUS_CONNECTION_HPP
diff --git a/boost-dbus/include/dbus/connection_service.hpp b/boost-dbus/include/dbus/connection_service.hpp
new file mode 100644
index 0000000..28318c6
--- /dev/null
+++ b/boost-dbus/include/dbus/connection_service.hpp
@@ -0,0 +1,105 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_CONNECTION_SERVICE_HPP
+#define DBUS_CONNECTION_SERVICE_HPP
+
+#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
+
+#include <dbus/detail/async_send_op.hpp>
+#include <dbus/element.hpp>
+#include <dbus/error.hpp>
+#include <dbus/message.hpp>
+
+#include <dbus/impl/connection.ipp>
+
+namespace dbus {
+namespace bus {
+static const int session = DBUS_BUS_SESSION;
+static const int system = DBUS_BUS_SYSTEM;
+static const int starter = DBUS_BUS_STARTER;
+} // namespace bus
+
+class filter;
+class match;
+class connection;
+
+class connection_service : public boost::asio::detail::service_base<connection_service> {
+ public:
+ typedef impl::connection implementation_type;
+
+ inline explicit connection_service(boost::asio::io_service& io)
+ : boost::asio::detail::service_base<connection_service>(io) {}
+
+ inline void construct(implementation_type& impl) {}
+
+ inline void destroy(implementation_type& impl) {}
+
+ inline void shutdown_service() {
+ // TODO is there anything that needs shutting down?
+ }
+
+ inline void open(implementation_type& impl, const string& address) {
+ boost::asio::io_service& io = this->get_io_service();
+
+ impl.open(io, address);
+ }
+
+ inline void open(implementation_type& impl, const int bus = bus::system) {
+ boost::asio::io_service& io = this->get_io_service();
+
+ impl.open(io, bus);
+ }
+
+ inline message send(implementation_type& impl, message& m) {
+ return impl.send_with_reply_and_block(m);
+ }
+
+ template <typename Duration>
+ inline message send(implementation_type& impl, message& m, const Duration& timeout) {
+ if (timeout == Duration::zero()) {
+ // TODO this can return false if it failed
+ impl.send(m);
+ return message();
+ } else {
+ return impl.send_with_reply_and_block(
+ m, std::chrono::milliseconds(timeout).count());
+ }
+ }
+
+ template <typename MessageHandler>
+ inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
+ void(boost::system::error_code, message))
+ async_send(implementation_type& impl, message& m,
+ BOOST_ASIO_MOVE_ARG(MessageHandler) handler) {
+ // begin asynchronous operation
+ impl.start(this->get_io_service());
+
+ boost::asio::detail::async_result_init<
+ MessageHandler, void(boost::system::error_code, message)>
+ init(BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
+ detail::async_send_op<typename boost::asio::handler_type<
+ MessageHandler, void(boost::system::error_code, message)>::type>(
+ this->get_io_service(),
+ BOOST_ASIO_MOVE_CAST(MessageHandler)(init.handler))(impl, m);
+
+ return init.result.get();
+ }
+
+ private:
+ friend connection;
+ inline void new_match(implementation_type& impl, match& m);
+
+ inline void delete_match(implementation_type& impl, match& m);
+
+ inline void new_filter(implementation_type& impl, filter& f);
+
+ inline void delete_filter(implementation_type& impl, filter& f);
+};
+
+} // namespace dbus
+
+#endif // DBUS_CONNECTION_SERVICE_HPP
diff --git a/boost-dbus/include/dbus/detail/async_send_op.hpp b/boost-dbus/include/dbus/detail/async_send_op.hpp
new file mode 100644
index 0000000..996a4e7
--- /dev/null
+++ b/boost-dbus/include/dbus/detail/async_send_op.hpp
@@ -0,0 +1,78 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_ASYNC_SEND_OP_HPP
+#define DBUS_ASYNC_SEND_OP_HPP
+
+#include <boost/scoped_ptr.hpp>
+
+#include <dbus/dbus.h>
+#include <dbus/error.hpp>
+#include <dbus/message.hpp>
+
+#include <dbus/impl/connection.ipp>
+
+namespace dbus {
+namespace detail {
+
+template <typename MessageHandler>
+struct async_send_op {
+ boost::asio::io_service& io_;
+ message message_;
+ MessageHandler handler_;
+ async_send_op(boost::asio::io_service& io,BOOST_ASIO_MOVE_ARG(MessageHandler) handler);
+ static void callback(DBusPendingCall* p, void* userdata); // for C API
+ void operator()(impl::connection& c, message& m); // initiate operation
+ void operator()(); // bound completion handler form
+};
+
+template <typename MessageHandler>
+async_send_op<MessageHandler>::async_send_op(boost::asio::io_service& io,BOOST_ASIO_MOVE_ARG(MessageHandler)handler)
+ : io_(io), handler_(BOOST_ASIO_MOVE_CAST(MessageHandler)(handler)) {}
+
+template <typename MessageHandler>
+void async_send_op<MessageHandler>::operator()(impl::connection& c,
+ message& m) {
+ DBusPendingCall* p;
+ c.send_with_reply(m, &p, -1);
+
+ // We have to throw this onto the heap so that the
+ // C API can store it as `void *userdata`
+ async_send_op* op =
+ new async_send_op(BOOST_ASIO_MOVE_CAST(async_send_op)(*this));
+
+ dbus_pending_call_set_notify(p, &callback, op, NULL);
+
+ // FIXME Race condition: another thread might have
+ // processed the pending call's reply before a notify
+ // function could be set. If so, the notify function
+ // will never trigger, so it must be called manually:
+ if (dbus_pending_call_get_completed(p)) {
+ // TODO: does this work, or might it call the notify
+ // function too many times? Might have to use steal_reply
+ // callback(p, op);
+ }
+}
+
+template <typename MessageHandler>
+void async_send_op<MessageHandler>::callback(DBusPendingCall* p,
+ void* userdata) {
+ boost::scoped_ptr<async_send_op> op(static_cast<async_send_op*>(userdata));
+
+ op->message_ = dbus_pending_call_steal_reply(p);
+ dbus_pending_call_unref(p);
+
+ op->io_.post(BOOST_ASIO_MOVE_CAST(async_send_op)(*op));
+}
+
+template <typename MessageHandler>
+void async_send_op<MessageHandler>::operator()() {
+ handler_(error(message_).error_code(), message_);
+}
+
+} // namespace detail
+} // namespace dbus
+
+#endif // DBUS_ASYNC_SEND_OP_HPP
diff --git a/boost-dbus/include/dbus/detail/queue.hpp b/boost-dbus/include/dbus/detail/queue.hpp
new file mode 100644
index 0000000..c435af3
--- /dev/null
+++ b/boost-dbus/include/dbus/detail/queue.hpp
@@ -0,0 +1,98 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_QUEUE_HPP
+#define DBUS_QUEUE_HPP
+
+#include <deque>
+#include <functional>
+#include <boost/asio.hpp>
+#include <boost/asio/detail/mutex.hpp>
+
+namespace dbus {
+namespace detail {
+
+template <typename Message>
+class queue {
+ public:
+ typedef ::boost::asio::detail::mutex mutex_type;
+ typedef Message message_type;
+ typedef std::function<void(boost::system::error_code, Message)> handler_type;
+
+ private:
+ boost::asio::io_service& io;
+ mutex_type mutex;
+ std::deque<message_type> messages;
+ std::deque<handler_type> handlers;
+
+ public:
+ queue(boost::asio::io_service& io_service) : io(io_service) {}
+
+ private:
+ class closure {
+ handler_type handler_;
+ message_type message_;
+ boost::system::error_code error_;
+
+ public:
+ void operator()() { handler_(error_, message_); }
+ closure(BOOST_ASIO_MOVE_ARG(handler_type) h, Message m,
+ boost::system::error_code e = boost::system::error_code())
+ : handler_(h), message_(m), error_(e) {}
+ };
+
+ public:
+ void push(message_type m) {
+ mutex_type::scoped_lock lock(mutex);
+ if (handlers.empty())
+ messages.push_back(m);
+ else {
+ handler_type h = handlers.front();
+ handlers.pop_front();
+
+ lock.unlock();
+
+ io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(h), m));
+ }
+ }
+
+ template <typename MessageHandler>
+ inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
+ void(boost::system::error_code,
+ message_type))
+ async_pop(BOOST_ASIO_MOVE_ARG(MessageHandler) h) {
+ typedef ::boost::asio::detail::async_result_init<
+ MessageHandler, void(boost::system::error_code, message_type)>
+ init_type;
+
+ mutex_type::scoped_lock lock(mutex);
+ if (messages.empty()) {
+ init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
+
+ handlers.push_back(init.handler);
+
+ lock.unlock();
+
+ return init.result.get();
+
+ } else {
+ message_type m = messages.front();
+ messages.pop_front();
+
+ lock.unlock();
+
+ init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
+
+ io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(init.handler), m));
+
+ return init.result.get();
+ }
+ }
+};
+
+} // namespace detail
+} // namespace dbus
+
+#endif // DBUS_QUEUE_HPP
diff --git a/boost-dbus/include/dbus/detail/watch_timeout.hpp b/boost-dbus/include/dbus/detail/watch_timeout.hpp
new file mode 100644
index 0000000..ef2e708
--- /dev/null
+++ b/boost-dbus/include/dbus/detail/watch_timeout.hpp
@@ -0,0 +1,151 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_WATCH_TIMEOUT_HPP
+#define DBUS_WATCH_TIMEOUT_HPP
+
+#include <dbus/dbus.h>
+#include <boost/asio/generic/stream_protocol.hpp>
+#include <boost/asio/steady_timer.hpp>
+
+#include <chrono>
+
+namespace dbus {
+namespace detail {
+
+static void watch_toggled(DBusWatch *dbus_watch, void *data);
+struct watch_handler {
+ DBusWatchFlags flags;
+ DBusWatch *dbus_watch;
+ watch_handler(DBusWatchFlags f, DBusWatch *w) : flags(f), dbus_watch(w) {}
+ void operator()(boost::system::error_code ec, size_t) {
+ if (ec) return;
+ dbus_watch_handle(dbus_watch, flags);
+
+ boost::asio::generic::stream_protocol::socket &socket = *static_cast<boost::asio::generic::stream_protocol::socket *>(
+ dbus_watch_get_data(dbus_watch));
+
+ watch_toggled(dbus_watch, &socket.get_io_service());
+ }
+};
+static void watch_toggled(DBusWatch *dbus_watch, void *data) {
+ boost::asio::generic::stream_protocol::socket &socket =
+ *static_cast<boost::asio::generic::stream_protocol::socket *>(dbus_watch_get_data(dbus_watch));
+
+ if (dbus_watch_get_enabled(dbus_watch)) {
+ if (dbus_watch_get_flags(dbus_watch) & DBUS_WATCH_READABLE)
+ socket.async_read_some(boost::asio::null_buffers(),
+ watch_handler(DBUS_WATCH_READABLE, dbus_watch));
+
+ if (dbus_watch_get_flags(dbus_watch) & DBUS_WATCH_WRITABLE)
+ socket.async_write_some(boost::asio::null_buffers(),
+ watch_handler(DBUS_WATCH_WRITABLE, dbus_watch));
+
+ } else {
+ socket.cancel();
+ }
+}
+
+static dbus_bool_t add_watch(DBusWatch *dbus_watch, void *data) {
+ if (!dbus_watch_get_enabled(dbus_watch)) return TRUE;
+
+ boost::asio::io_service &io = *static_cast<boost::asio::io_service *>(data);
+
+ int fd = dbus_watch_get_unix_fd(dbus_watch);
+
+ if (fd == -1)
+ // socket based watches
+ fd = dbus_watch_get_socket(dbus_watch);
+
+ boost::asio::generic::stream_protocol::socket &socket = *new boost::asio::generic::stream_protocol::socket(io);
+
+ socket.assign(boost::asio::generic::stream_protocol(0, 0), fd);
+
+ dbus_watch_set_data(dbus_watch, &socket, NULL);
+
+ watch_toggled(dbus_watch, &io);
+ return TRUE;
+}
+
+static void remove_watch(DBusWatch *dbus_watch, void *data) {
+ delete static_cast<boost::asio::generic::stream_protocol::socket *>(
+ dbus_watch_get_data(dbus_watch));
+}
+
+struct timeout_handler {
+ DBusTimeout *dbus_timeout;
+ timeout_handler(DBusTimeout *t) : dbus_timeout(t) {}
+ void operator()(boost::system::error_code ec) {
+ if (ec) return;
+ dbus_timeout_handle(dbus_timeout);
+ }
+};
+
+static void timeout_toggled(DBusTimeout *dbus_timeout, void *data) {
+ boost::asio::steady_timer &timer =
+ *static_cast<boost::asio::steady_timer *>(dbus_timeout_get_data(dbus_timeout));
+
+ if (dbus_timeout_get_enabled(dbus_timeout)) {
+ boost::asio::steady_timer::duration interval =
+ std::chrono::milliseconds(dbus_timeout_get_interval(dbus_timeout));
+ timer.expires_from_now(interval);
+ timer.cancel();
+ timer.async_wait(timeout_handler(dbus_timeout));
+ } else {
+ timer.cancel();
+ }
+}
+
+static dbus_bool_t add_timeout(DBusTimeout *dbus_timeout, void *data) {
+ if (!dbus_timeout_get_enabled(dbus_timeout)) return TRUE;
+
+ boost::asio::io_service &io = *static_cast<boost::asio::io_service *>(data);
+
+ boost::asio::steady_timer &timer = *new boost::asio::steady_timer(io);
+
+ dbus_timeout_set_data(dbus_timeout, &timer, NULL);
+
+ timeout_toggled(dbus_timeout, &io);
+ return TRUE;
+}
+
+static void remove_timeout(DBusTimeout *dbus_timeout, void *data) {
+ delete static_cast<boost::asio::steady_timer *>(dbus_timeout_get_data(dbus_timeout));
+}
+
+struct dispatch_handler {
+ boost::asio::io_service &io;
+ DBusConnection *conn;
+ dispatch_handler(boost::asio::io_service &i, DBusConnection *c)
+ : io(i), conn(c) {}
+ void operator()() {
+ if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS)
+ io.post(dispatch_handler(io, conn));
+ }
+};
+
+static void dispatch_status(DBusConnection *conn, DBusDispatchStatus new_status,
+ void *data) {
+ boost::asio::io_service &io = *static_cast<boost::asio::io_service *>(data);
+ if (new_status == DBUS_DISPATCH_DATA_REMAINS)
+ io.post(dispatch_handler(io, conn));
+}
+
+static void set_watch_timeout_dispatch_functions(DBusConnection *conn,
+ boost::asio::io_service &io) {
+ dbus_connection_set_watch_functions(conn, &add_watch, &remove_watch,
+ &watch_toggled, &io, NULL);
+
+ dbus_connection_set_timeout_functions(conn, &add_timeout, &remove_timeout,
+ &timeout_toggled, &io, NULL);
+
+ dbus_connection_set_dispatch_status_function(conn, &dispatch_status, &io,
+ NULL);
+}
+
+} // namespace detail
+} // namespace dbus
+
+#endif // DBUS_WATCH_TIMEOUT_HPP
diff --git a/boost-dbus/include/dbus/element.hpp b/boost-dbus/include/dbus/element.hpp
new file mode 100644
index 0000000..276b593
--- /dev/null
+++ b/boost-dbus/include/dbus/element.hpp
@@ -0,0 +1,182 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_ELEMENT_HPP
+#define DBUS_ELEMENT_HPP
+
+#include <dbus/dbus.h>
+#include <string>
+#include <boost/cstdint.hpp>
+
+namespace dbus {
+
+/// Message elements
+/**
+ * D-Bus Messages are composed of simple elements of one of these types
+ */
+// bool // is this simply valid? It might pack wrong...
+// http://maemo.org/api_refs/5.0/5.0-final/dbus/api/group__DBusTypes.html
+typedef boost::uint8_t byte;
+
+typedef boost::int16_t int16;
+typedef boost::uint16_t uint16;
+typedef boost::int32_t int32;
+typedef boost::uint32_t uint32;
+
+typedef boost::int64_t int64;
+typedef boost::uint64_t uint64;
+// double
+// unix_fd
+
+typedef std::string string;
+struct object_path {
+ string value;
+};
+struct signature {
+ string value;
+};
+
+/// Traits template for message elements
+/**
+ * D-Bus Message elements are identified by unique integer type codes.
+ */
+template <typename InvalidType>
+struct element {
+ static const int code = DBUS_TYPE_INVALID;
+};
+
+template <>
+struct element<bool> {
+ static const int code = DBUS_TYPE_BOOLEAN;
+};
+
+template <>
+struct element<byte> {
+ static const int code = DBUS_TYPE_BYTE;
+};
+
+template <>
+struct element<int16> {
+ static const int code = DBUS_TYPE_INT16;
+};
+
+template <>
+struct element<uint16> {
+ static const int code = DBUS_TYPE_UINT16;
+};
+
+template <>
+struct element<int32> {
+ static const int code = DBUS_TYPE_INT32;
+};
+
+template <>
+struct element<uint32> {
+ static const int code = DBUS_TYPE_UINT32;
+};
+
+template <>
+struct element<int64> {
+ static const int code = DBUS_TYPE_INT64;
+};
+
+template <>
+struct element<uint64> {
+ static const int code = DBUS_TYPE_UINT64;
+};
+
+template <>
+struct element<double> {
+ static const int code = DBUS_TYPE_DOUBLE;
+};
+
+template <>
+struct element<string> {
+ static const int code = DBUS_TYPE_STRING;
+};
+
+template <>
+struct element<object_path> {
+ static const int code = DBUS_TYPE_OBJECT_PATH;
+};
+
+template <>
+struct element<signature> {
+ static const int code = DBUS_TYPE_SIGNATURE;
+};
+
+template <typename InvalidType>
+struct is_fixed_type {
+ static const int value = false;
+};
+
+template <>
+struct is_fixed_type<bool> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<byte> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<int16> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<uint16> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<int32> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<uint32> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<int64> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<uint64> {
+ static const int value = true;
+};
+
+template <>
+struct is_fixed_type<double> {
+ static const int value = true;
+};
+
+template <typename InvalidType>
+struct is_string_type {
+ static const bool value = false;
+};
+
+template <>
+struct is_string_type<string> {
+ static const bool value = true;
+};
+
+template <>
+struct is_string_type<object_path> {
+ static const bool value = true;
+};
+
+template <>
+struct is_string_type<signature> {
+ static const bool value = true;
+};
+
+} // namespace dbus
+
+#endif // DBUS_ELEMENT_HPP
diff --git a/boost-dbus/include/dbus/endpoint.hpp b/boost-dbus/include/dbus/endpoint.hpp
new file mode 100644
index 0000000..a574e8f
--- /dev/null
+++ b/boost-dbus/include/dbus/endpoint.hpp
@@ -0,0 +1,34 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_ENDPOINT_HPP
+#define DBUS_ENDPOINT_HPP
+
+#include <dbus/dbus.h>
+#include <dbus/element.hpp>
+#include <dbus/message.hpp>
+
+namespace dbus {
+
+class endpoint {
+ string process_name_;
+ string path_;
+ string interface_;
+
+ public:
+ endpoint(const string& process_name, const string& path,
+ const string& interface)
+ : process_name_(process_name), path_(path), interface_(interface) {}
+
+ const string& get_path() const { return path_; }
+
+ const string& get_interface() const { return interface_; }
+
+ const string& get_process_name() const { return process_name_; }
+};
+
+} // namespace dbus
+
+#endif // DBUS_ENDPOINT_HPP
diff --git a/boost-dbus/include/dbus/error.hpp b/boost-dbus/include/dbus/error.hpp
new file mode 100644
index 0000000..3b07c9f
--- /dev/null
+++ b/boost-dbus/include/dbus/error.hpp
@@ -0,0 +1,64 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_ERROR_HPP
+#define DBUS_ERROR_HPP
+
+#include <dbus/dbus.h>
+#include <dbus/element.hpp>
+#include <dbus/message.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+
+namespace dbus {
+
+class error : public boost::system::error_category {
+ DBusError error_;
+
+ public:
+ error() { dbus_error_init(&error_); }
+
+ error(DBusError *src) {
+ dbus_error_init(&error_);
+ dbus_move_error(src, &error_);
+ }
+
+ error(dbus::message &m) {
+ dbus_error_init(&error_);
+ dbus_set_error_from_message(&error_, m);
+ }
+
+ ~error() { dbus_error_free(&error_); }
+
+ const char *name() const BOOST_SYSTEM_NOEXCEPT { return error_.name; }
+
+ string message(int value) const { return error_.message; }
+
+ bool is_set() const { return dbus_error_is_set(&error_); }
+
+ operator const DBusError *() const { return &error_; }
+
+ operator DBusError *() { return &error_; }
+
+ boost::system::error_code error_code() const;
+ boost::system::system_error system_error() const;
+ void throw_if_set() const;
+};
+
+inline boost::system::error_code error::error_code() const {
+ return boost::system::error_code(is_set(), *this);
+}
+
+inline boost::system::system_error error::system_error() const {
+ return boost::system::system_error(error_code());
+}
+
+inline void error::throw_if_set() const {
+ if (is_set()) throw system_error();
+}
+
+} // namespace dbus
+
+#endif // DBUS_ERROR_HPP
diff --git a/boost-dbus/include/dbus/filter.hpp b/boost-dbus/include/dbus/filter.hpp
new file mode 100644
index 0000000..5d60d33
--- /dev/null
+++ b/boost-dbus/include/dbus/filter.hpp
@@ -0,0 +1,56 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_FILTER_HPP
+#define DBUS_FILTER_HPP
+
+#include <dbus/connection.hpp>
+#include <dbus/detail/queue.hpp>
+#include <dbus/message.hpp>
+#include <functional>
+#include <boost/asio.hpp>
+
+namespace dbus {
+
+/// Represents a filter of incoming messages.
+/**
+ * Filters examine incoming messages, demuxing them to multiple queues.
+ */
+class filter {
+ connection& connection_;
+ std::function<bool(message&)> predicate_;
+ detail::queue<message> queue_;
+
+ public:
+ bool offer(message& m) {
+ bool filtered = predicate_(m);
+ if (filtered) queue_.push(m);
+ return filtered;
+ }
+
+ template <typename MessagePredicate>
+ filter(connection& c, BOOST_ASIO_MOVE_ARG(MessagePredicate) p)
+ : connection_(c),
+ predicate_(BOOST_ASIO_MOVE_CAST(MessagePredicate)(p)),
+ queue_(connection_.get_io_service()) {
+ connection_.new_filter(*this);
+ }
+
+ ~filter() { connection_.delete_filter(*this); }
+
+ template <typename MessageHandler>
+ inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
+ void(boost::system::error_code, message))
+ async_dispatch(BOOST_ASIO_MOVE_ARG(MessageHandler) handler) {
+ // begin asynchronous operation
+ connection_.get_implementation().start(connection_.get_io_service());
+
+ return queue_.async_pop(BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
+ }
+};
+} // namespace dbus
+
+#include <dbus/impl/filter.ipp>
+#endif // DBUS_FILTER_HPP
diff --git a/boost-dbus/include/dbus/impl/connection.ipp b/boost-dbus/include/dbus/impl/connection.ipp
new file mode 100644
index 0000000..24a257d
--- /dev/null
+++ b/boost-dbus/include/dbus/impl/connection.ipp
@@ -0,0 +1,102 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_CONNECTION_IPP
+#define DBUS_CONNECTION_IPP
+
+#include <dbus/dbus.h>
+#include <dbus/detail/watch_timeout.hpp>
+
+#include <boost/atomic.hpp>
+
+namespace dbus {
+namespace impl {
+
+class connection {
+ public:
+ boost::atomic<bool> is_paused;
+ DBusConnection* conn;
+
+ connection() : is_paused(true), conn(NULL) {}
+
+ void open(boost::asio::io_service& io, int bus) {
+ error e;
+ conn = dbus_bus_get_private((DBusBusType)bus, e);
+ e.throw_if_set();
+
+ dbus_connection_set_exit_on_disconnect(conn, false);
+
+ detail::set_watch_timeout_dispatch_functions(conn, io);
+ }
+
+ void open(boost::asio::io_service& io, const string& address) {
+ error e;
+ conn = dbus_connection_open_private(address.c_str(), e);
+ e.throw_if_set();
+
+ dbus_bus_register(conn, e);
+ e.throw_if_set();
+
+ dbus_connection_set_exit_on_disconnect(conn, false);
+
+ detail::set_watch_timeout_dispatch_functions(conn, io);
+ }
+
+ ~connection() {
+ if (conn != NULL) {
+ dbus_connection_close(conn);
+ dbus_connection_unref(conn);
+ }
+ }
+
+ operator DBusConnection*() { return conn; }
+ operator const DBusConnection*() const { return conn; }
+
+ message send_with_reply_and_block(message& m,
+ int timeout_in_milliseconds = -1) {
+ error e;
+ DBusMessage* out = dbus_connection_send_with_reply_and_block(
+ conn, m, timeout_in_milliseconds, e);
+ e.throw_if_set();
+ message reply(out);
+
+ return reply;
+ }
+
+ void send(message& m) {
+ // ignoring message serial for now
+ dbus_connection_send(conn, m, NULL);
+ }
+
+ void send_with_reply(message& m, DBusPendingCall** p,
+ int timeout_in_milliseconds = -1) {
+ dbus_connection_send_with_reply(conn, m, p, timeout_in_milliseconds);
+ }
+
+ // begin asynchronous operation
+ // FIXME should not get io from an argument
+ void start(boost::asio::io_service& io) {
+ bool old_value(true);
+ if (is_paused.compare_exchange_strong(old_value, false)) {
+ // If two threads call connection::async_send()
+ // simultaneously on a paused connection, then
+ // only one will pass the CAS instruction and
+ // only one dispatch_handler will be injected.
+ io.post(detail::dispatch_handler(io, conn));
+ }
+ }
+
+ void cancel(boost::asio::io_service& io) {
+ bool old_value(false);
+ if (is_paused.compare_exchange_strong(old_value, true)) {
+ // TODO
+ }
+ }
+};
+
+} // namespace impl
+} // namespace dbus
+
+#endif // DBUS_CONNECTION_IPP
diff --git a/boost-dbus/include/dbus/impl/filter.ipp b/boost-dbus/include/dbus/impl/filter.ipp
new file mode 100644
index 0000000..a64d6fd
--- /dev/null
+++ b/boost-dbus/include/dbus/impl/filter.ipp
@@ -0,0 +1,39 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_FILTER_IPP
+#define DBUS_FILTER_IPP
+
+namespace dbus {
+namespace impl {
+
+inline DBusHandlerResult filter_callback(DBusConnection* c, DBusMessage* m,
+ void* userdata) {
+ try {
+ filter& f = *static_cast<filter*>(userdata);
+ message m_(m);
+ if (f.offer(m_)) {
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ } catch (...) {
+ // do not throw in C callbacks. Just don't.
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+} // namespace impl
+
+void connection_service::new_filter(implementation_type& impl, filter& f) {
+ dbus_connection_add_filter(impl, &impl::filter_callback, &f, NULL);
+}
+
+void connection_service::delete_filter(implementation_type& impl, filter& f) {
+ dbus_connection_remove_filter(impl, &impl::filter_callback, &f);
+}
+
+} // namespace dbus
+
+#endif // DBUS_FILTER_IPP
diff --git a/boost-dbus/include/dbus/impl/match.ipp b/boost-dbus/include/dbus/impl/match.ipp
new file mode 100644
index 0000000..9f6a5da
--- /dev/null
+++ b/boost-dbus/include/dbus/impl/match.ipp
@@ -0,0 +1,26 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_MATCH_IPP
+#define DBUS_MATCH_IPP
+
+namespace dbus {
+void connection_service::new_match(implementation_type& impl, match& m) {
+ error e;
+ dbus_bus_add_match(impl, m.get_expression().c_str(), e);
+ e.throw_if_set();
+ // eventually, for complete asynchronicity, this should connect to
+ // org.freedesktop.DBus and call AddMatch
+}
+
+void connection_service::delete_match(implementation_type& impl, match& m) {
+ error e;
+ dbus_bus_remove_match(impl, m.get_expression().c_str(), e);
+ e.throw_if_set();
+}
+
+} // namespace dbus
+
+#endif // DBUS_MATCH_IPP
diff --git a/boost-dbus/include/dbus/impl/message_iterator.hpp b/boost-dbus/include/dbus/impl/message_iterator.hpp
new file mode 100644
index 0000000..44bcf2e
--- /dev/null
+++ b/boost-dbus/include/dbus/impl/message_iterator.hpp
@@ -0,0 +1,50 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_IMPL_MESSAGE_ITERATOR_HPP
+#define DBUS_IMPL_MESSAGE_ITERATOR_HPP
+
+#include <dbus/dbus.h>
+
+namespace dbus {
+
+class message;
+
+namespace impl {
+
+class message_iterator {
+ DBusMessageIter DBusMessageIter_;
+
+ public:
+ // writing
+ static void init_append(message &m, message_iterator &i);
+
+ void append_basic(int code, const void *value);
+
+ void open_container(int code, const char *signature, message_iterator &);
+ void close_container(message_iterator &);
+ void abandon_container(message_iterator &);
+
+ void append_fixed_array(int code, const void *value, int n_elements);
+
+ // reading
+ static bool init(message &m, message_iterator &i);
+
+ bool next();
+ bool has_next();
+ int get_arg_type();
+
+ void get_basic(void *value);
+
+ void recurse(message_iterator &);
+
+ int get_element_type();
+ void get_fixed_array(void *value, int *n_elements);
+};
+
+} // namespace impl
+} // namespace dbus
+
+#endif // DBUS_IMPL_MESSAGE_ITERATOR_HPP
diff --git a/boost-dbus/include/dbus/impl/message_iterator.ipp b/boost-dbus/include/dbus/impl/message_iterator.ipp
new file mode 100644
index 0000000..eb2584f
--- /dev/null
+++ b/boost-dbus/include/dbus/impl/message_iterator.ipp
@@ -0,0 +1,89 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_IMPL_MESSAGE_ITERATOR_IPP
+#define DBUS_IMPL_MESSAGE_ITERATOR_IPP
+
+#include <dbus/impl/message_iterator.hpp>
+
+namespace dbus {
+namespace impl {
+
+inline void message_iterator::init_append(message& m, message_iterator& i)
+{
+ dbus_message_iter_init_append(m, &i.DBusMessageIter_);
+}
+inline void message_iterator::append_basic(int code, const void *value)
+{
+ // returns false if not enough memory- throw bad_alloc
+ dbus_message_iter_append_basic(&DBusMessageIter_, code, value);
+}
+inline void message_iterator::open_container(int code, const char *signature, message_iterator& sub)
+{
+ // returns false if not enough memory- throw bad_alloc
+ dbus_message_iter_open_container(&DBusMessageIter_, code, signature, &sub.DBusMessageIter_);
+}
+
+inline void message_iterator::close_container(message_iterator& sub)
+{
+ // returns false if not enough memory- throw bad_alloc
+ dbus_message_iter_close_container(&DBusMessageIter_, &sub.DBusMessageIter_);
+}
+
+inline void message_iterator::abandon_container(message_iterator& sub)
+{
+ dbus_message_iter_abandon_container(&DBusMessageIter_, &sub.DBusMessageIter_);
+}
+
+inline void message_iterator::append_fixed_array(int code, const void *value, int n_elements)
+{
+ // returns false if not enough memory- throw bad_alloc
+ dbus_message_iter_append_fixed_array(&DBusMessageIter_, code, value, n_elements);
+}
+
+inline bool message_iterator::init(message& m, message_iterator& i)
+{
+ return dbus_message_iter_init(m, &i.DBusMessageIter_);
+}
+
+inline bool message_iterator::next()
+{
+ return dbus_message_iter_next(&DBusMessageIter_);
+}
+
+inline bool message_iterator::has_next()
+{
+ return dbus_message_iter_has_next(&DBusMessageIter_);
+}
+
+inline int message_iterator::get_arg_type()
+{
+ return dbus_message_iter_get_arg_type(&DBusMessageIter_);
+}
+
+inline void message_iterator::get_basic(void *value)
+{
+ dbus_message_iter_get_basic(&DBusMessageIter_, value);
+}
+
+inline void message_iterator::recurse(message_iterator& sub)
+{
+ dbus_message_iter_recurse(&DBusMessageIter_, &sub.DBusMessageIter_);
+}
+
+inline int message_iterator::get_element_type()
+{
+ return dbus_message_iter_get_element_type(&DBusMessageIter_);
+}
+
+inline void message_iterator::get_fixed_array(void *value, int *n_elements)
+{
+ dbus_message_iter_get_fixed_array(&DBusMessageIter_, value, n_elements);
+}
+
+} // namespace impl
+} // namespace dbus
+
+#endif // DBUS_IMPL_MESSAGE_ITERATOR_IPP
diff --git a/boost-dbus/include/dbus/match.hpp b/boost-dbus/include/dbus/match.hpp
new file mode 100644
index 0000000..0488aa0
--- /dev/null
+++ b/boost-dbus/include/dbus/match.hpp
@@ -0,0 +1,46 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_MATCH_HPP
+#define DBUS_MATCH_HPP
+
+#include <string>
+#include <boost/asio.hpp>
+
+#include <dbus/connection.hpp>
+#include <dbus/error.hpp>
+
+namespace dbus {
+
+/// Simple placeholder object for a match rule.
+/**
+ * A match rule determines what messages will be received by this application.
+ *
+ * Each rule will be represented by an instance of match. To remove that rule,
+ * dispose of the object.
+ */
+class match {
+ connection& connection_;
+ std::string expression_;
+
+ public:
+ match(connection& c, BOOST_ASIO_MOVE_ARG(std::string) e)
+ : connection_(c), expression_(BOOST_ASIO_MOVE_CAST(std::string)(e)) {
+ connection_.new_match(*this);
+ }
+
+ ~match() { connection_.delete_match(*this); }
+
+ const std::string& get_expression() const { return expression_; }
+
+ match(match&&) = delete;
+ match& operator=(match&&) = delete;
+};
+
+} // namespace dbus
+
+#include <dbus/impl/match.ipp>
+
+#endif // DBUS_MATCH_HPP
diff --git a/boost-dbus/include/dbus/message.hpp b/boost-dbus/include/dbus/message.hpp
new file mode 100644
index 0000000..aa5e89c
--- /dev/null
+++ b/boost-dbus/include/dbus/message.hpp
@@ -0,0 +1,224 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_MESSAGE_HPP
+#define DBUS_MESSAGE_HPP
+
+#include <dbus/dbus.h>
+#include <dbus/element.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/impl/message_iterator.hpp>
+#include <iostream>
+#include <vector>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/utility/enable_if.hpp>
+
+inline void intrusive_ptr_add_ref(DBusMessage* m) { dbus_message_ref(m); }
+
+inline void intrusive_ptr_release(DBusMessage* m) { dbus_message_unref(m); }
+
+namespace dbus {
+
+class message {
+ boost::intrusive_ptr<DBusMessage> message_;
+
+ public:
+ /// Create a method call message
+ static message new_call(const endpoint& destination,
+ const string& method_name) {
+ return dbus_message_new_method_call(
+ destination.get_process_name().c_str(), destination.get_path().c_str(),
+ destination.get_interface().c_str(), method_name.c_str());
+ }
+
+ /// Create a method return message
+ static message new_return(message& call) {
+ return dbus_message_new_method_return(call);
+ }
+
+ /// Create an error message
+ static message new_error(message& call, const string& error_name,
+ const string& error_message) {
+ return dbus_message_new_error(call, error_name.c_str(),
+ error_message.c_str());
+ }
+
+ /// Create a signal message
+ static message new_signal(const endpoint& origin, const string& signal_name) {
+ return dbus_message_new_signal(origin.get_path().c_str(),
+ origin.get_interface().c_str(),
+ signal_name.c_str());
+ }
+
+ message() {}
+
+ message(DBusMessage* m) : message_(dbus_message_ref(m)) {}
+
+ operator DBusMessage*() { return message_.get(); }
+
+ operator const DBusMessage*() const { return message_.get(); }
+
+ string get_path() const {
+ return sanitize(dbus_message_get_path(message_.get()));
+ }
+
+ string get_interface() const {
+ return sanitize(dbus_message_get_interface(message_.get()));
+ }
+
+ string get_member() const {
+ return sanitize(dbus_message_get_member(message_.get()));
+ }
+
+ string get_type() const {
+ return sanitize(
+ dbus_message_type_to_string(dbus_message_get_type(message_.get())));
+ }
+
+ string get_sender() const {
+ return sanitize(dbus_message_get_sender(message_.get()));
+ }
+
+ string get_destination() const {
+ return sanitize(dbus_message_get_destination(message_.get()));
+ }
+
+ uint32 get_serial() { return dbus_message_get_serial(message_.get()); }
+
+ message& set_serial(uint32 serial) {
+ dbus_message_set_serial(message_.get(), serial);
+ return *this;
+ }
+
+ uint32 get_reply_serial() {
+ return dbus_message_get_reply_serial(message_.get());
+ }
+
+ message& set_reply_serial(uint32 reply_serial) {
+ dbus_message_set_reply_serial(message_.get(), reply_serial);
+ return *this;
+ }
+
+ struct packer {
+ impl::message_iterator iter_;
+ packer(message& m) { impl::message_iterator::init_append(m, iter_); }
+ template <typename Element>
+ packer& pack(const Element& e) {
+ return *this << e;
+ }
+ };
+ struct unpacker {
+ impl::message_iterator iter_;
+ unpacker(message& m) { impl::message_iterator::init(m, iter_); }
+
+ template <typename Element>
+ unpacker& unpack(Element& e) {
+ return *this >> e;
+ }
+ };
+
+ template <typename Element>
+ packer pack(const Element& e) {
+ return packer(*this).pack(e);
+ }
+
+ template <typename Element>
+ unpacker unpack(Element& e) {
+ return unpacker(*this).unpack(e);
+ }
+
+ private:
+ static std::string sanitize(const char* str) {
+ return (str == NULL) ? "(null)" : str;
+ }
+};
+
+template <typename Element>
+message::packer operator<<(message m, const Element& e) {
+ return message::packer(m).pack(e);
+}
+
+template <typename Element>
+typename boost::enable_if<is_fixed_type<Element>, message::packer&>::type
+operator<<(message::packer& p, const Element& e) {
+ p.iter_.append_basic(element<Element>::code, &e);
+ return p;
+}
+
+inline message::packer& operator<<(message::packer& p, const char* c) {
+ p.iter_.append_basic(element<string>::code, &c);
+ return p;
+}
+
+inline message::packer& operator<<(message::packer& p, const string& e) {
+ const char* c = e.c_str();
+ return p << c;
+}
+
+template <typename Element>
+message::unpacker operator>>(message m, Element& e) {
+ return message::unpacker(m).unpack(e);
+}
+
+template <typename Element>
+typename boost::enable_if<is_fixed_type<Element>, message::unpacker&>::type
+operator>>(message::unpacker& u, Element& e) {
+ u.iter_.get_basic(&e);
+ u.iter_.next();
+ return u;
+}
+
+inline message::unpacker& operator>>(message::unpacker& u, string& s) {
+ const char* c;
+ u.iter_.get_basic(&c);
+ s.assign(c);
+ u.iter_.next();
+ return u;
+}
+
+template <typename Element>
+inline message::unpacker& operator>>(message::unpacker& u,
+ std::vector<Element>& s) {
+ static_assert(std::is_same<Element, std::string>::value,
+ "only std::vector<std::string> is implemented for now");
+ impl::message_iterator sub;
+ u.iter_.recurse(sub);
+
+ const char* c;
+ while (sub.has_next()) {
+ sub.get_basic(&c);
+ s.emplace_back(c);
+ sub.next();
+ }
+
+ // TODO(ed)
+ // Make this generic for all types. The below code is close, but there's
+ // template issues and things I don't understand;
+ /*
+ auto e = message::unpacker(sub);
+ while (sub.has_next()) {
+ s.emplace_back();
+ Element& element = s.back();
+ e.unpack(element);
+ }
+*/
+ return u;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const message& m) {
+ os << "type='" << m.get_type() << "',"
+ << "sender='" << m.get_sender() << "',"
+ << "interface='" << m.get_interface() << "',"
+ << "member='" << m.get_member() << "',"
+ << "path='" << m.get_path() << "',"
+ << "destination='" << m.get_destination() << "'";
+ return os;
+}
+
+} // namespace dbus
+
+#include <dbus/impl/message_iterator.ipp>
+
+#endif // DBUS_MESSAGE_HPP
diff --git a/boost-dbus/include/dbus/utility.hpp b/boost-dbus/include/dbus/utility.hpp
new file mode 100644
index 0000000..47fad1c
--- /dev/null
+++ b/boost-dbus/include/dbus/utility.hpp
@@ -0,0 +1,39 @@
+// Copyright (c) Ed Tanous
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef DBUS_UTILITY_HPP
+#define DBUS_UTILITY_HPP
+
+#include <boost/iostreams/stream.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+
+namespace dbus {
+
+inline void read_dbus_xml_names(std::string& xml_data_in,
+ std::vector<std::string>& values_out) {
+ // populate tree structure pt
+ using boost::property_tree::ptree;
+ ptree pt;
+ std::cout << xml_data_in;
+ std::stringstream ss;
+ ss << xml_data_in;
+ read_xml(ss, pt);
+
+ // traverse node to find other nodes
+ for (const auto& interface : pt.get_child("node")) {
+ if (interface.first == "node") {
+ auto t = interface.second.get<std::string>("<xmlattr>", "default");
+ for (const auto& subnode : interface.second.get_child("<xmlattr>")) {
+ if (subnode.first == "name") {
+ std::string t = subnode.second.get("", "unknown");
+ values_out.push_back(t);
+ }
+ }
+ }
+ }
+}
+}
+#endif // DBUS_UTILITY_HPP
\ No newline at end of file
diff --git a/boost-dbus/test/avahi.cpp b/boost-dbus/test/avahi.cpp
new file mode 100644
index 0000000..debbff3
--- /dev/null
+++ b/boost-dbus/test/avahi.cpp
@@ -0,0 +1,176 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <dbus/connection.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/filter.hpp>
+#include <dbus/match.hpp>
+#include <dbus/message.hpp>
+#include <dbus/utility.hpp>
+#include <functional>
+
+#include <unistd.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+TEST(AvahiTest, GetHostName) {
+ dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
+ "org.freedesktop.Avahi.Server");
+ boost::asio::io_service io;
+ dbus::connection system_bus(io, dbus::bus::system);
+
+ dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
+
+ system_bus.async_send(
+ m, [&](const boost::system::error_code ec, dbus::message r) {
+
+ std::string avahi_hostname;
+ std::string hostname;
+
+ // get hostname from a system call
+ char c[1024];
+ gethostname(c, 1024);
+ hostname = c;
+
+ r.unpack(avahi_hostname);
+
+ // Get only the host name, not the fqdn
+ auto unix_hostname = hostname.substr(0, hostname.find("."));
+ EXPECT_EQ(unix_hostname, avahi_hostname);
+
+ io.stop();
+ });
+ boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
+ t.async_wait([&](const boost::system::error_code& /*e*/) {
+ io.stop();
+ FAIL() << "Callback was never called\n";
+ });
+ io.run();
+}
+
+TEST(AvahiTest, ServiceBrowser) {
+ boost::asio::io_service io;
+ dbus::connection system_bus(io, dbus::bus::system);
+
+ dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
+ "org.freedesktop.Avahi.Server");
+ // create new service browser
+ dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew");
+ m1.pack<int32_t>(-1)
+ .pack<int32_t>(-1)
+ .pack<std::string>("_http._tcp")
+ .pack<std::string>("local")
+ .pack<uint32_t>(0);
+
+ dbus::message r = system_bus.send(m1);
+ std::string browser_path;
+ r.unpack(browser_path);
+ testing::Test::RecordProperty("browserPath", browser_path);
+
+ dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'");
+ dbus::filter f(system_bus, [](dbus::message& m) {
+ auto member = m.get_member();
+ return member == "NameAcquired";
+ });
+
+ std::function<void(boost::system::error_code, dbus::message)> event_handler =
+ [&](boost::system::error_code ec, dbus::message s) {
+ testing::Test::RecordProperty("firstSignal", s.get_member());
+ std::string a = s.get_member();
+ std::string dude;
+ s.unpack(dude);
+ f.async_dispatch(event_handler);
+ io.stop();
+ };
+ f.async_dispatch(event_handler);
+
+ boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
+ t.async_wait([&](const boost::system::error_code& /*e*/) {
+ io.stop();
+ FAIL() << "Callback was never called\n";
+ });
+ io.run();
+}
+
+TEST(BOOST_DBUS, ListServices) {
+ boost::asio::io_service io;
+ boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
+ t.async_wait([&](const boost::system::error_code& /*e*/) {
+ io.stop();
+ FAIL() << "Callback was never called\n";
+ });
+
+ dbus::connection system_bus(io, dbus::bus::system);
+
+ dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
+ "org.freedesktop.DBus");
+ // create new service browser
+ dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
+ system_bus.async_send(
+ m, [&](const boost::system::error_code ec, dbus::message r) {
+ io.stop();
+ std::vector<std::string> services;
+ r.unpack(services);
+ // Test a couple things that should always be present.... adapt if
+ // neccesary
+ EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
+ EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
+
+ });
+
+ io.run();
+}
+
+void query_interfaces(dbus::connection& system_bus, std::string& service_name,
+ std::string& object_name) {
+ dbus::endpoint service_daemon(service_name, object_name,
+ "org.freedestop.DBus.Introspectable");
+ dbus::message m = dbus::message::new_call(service_daemon, "Introspect");
+ try {
+ auto r = system_bus.send(m);
+ std::vector<std::string> names;
+ // Todo(ed) figure out why we're occassionally getting access
+ // denied errors
+ // EXPECT_EQ(ec, boost::system::errc::success);
+
+ std::string xml;
+ r.unpack(xml);
+ // TODO(ed) names needs lock for multithreaded access
+ dbus::read_dbus_xml_names(xml, names);
+ // loop over the newly added items
+ for (auto name : names) {
+ std::cout << name << "\n";
+ auto new_service_string = object_name + "/" + name;
+ query_interfaces(system_bus, service_name, new_service_string);
+ }
+ } catch (boost::system::error_code e) {
+ std::cout << e;
+ }
+}
+
+TEST(BOOST_DBUS, ListObjects) {
+ boost::asio::io_service io;
+ dbus::connection system_bus(io, dbus::bus::system);
+
+ dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
+ "org.freedesktop.DBus");
+
+ // create new service browser
+ dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
+ auto r = system_bus.send(m);
+
+ std::vector<std::string> services;
+ r.unpack(services);
+ // todo(ed) find out why this needs to be static
+ static std::atomic<int> dbus_count(0);
+ std::cout << dbus_count << " Callers\n";
+ auto names = std::make_shared<std::vector<std::string>>();
+ for (auto& service : services) {
+ std::string name = "/";
+ query_interfaces(system_bus, service, name);
+ }
+
+ io.run();
+}
diff --git a/boost-dbus/test/avahi.py b/boost-dbus/test/avahi.py
new file mode 100644
index 0000000..1bcd24d
--- /dev/null
+++ b/boost-dbus/test/avahi.py
@@ -0,0 +1,42 @@
+# Copyright (c) Benjamin Kietzman (github.com/bkietz)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import unittest
+import dbus
+from dbus.mainloop.glib import DBusGMainLoop
+from gobject import MainLoop
+from socket import gethostname
+
+class AvahiTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(c):
+ c.system_bus = dbus.SystemBus(mainloop=DBusGMainLoop())
+
+ def setUp(self):
+ None
+
+ def testAvahi(self):
+ # Connect to Avahi Daemon's interface:
+ avahi_remote = AvahiTest.system_bus.get_object('org.freedesktop.Avahi', '/')
+ avahi = dbus.Interface(avahi_remote, 'org.freedesktop.Avahi.Server')
+ self.assertEqual(gethostname(), avahi.GetHostName())
+
+ # Use the Avahi Daemon to produce a new
+ # ServiceBrowser and connect to its interface:
+ browser_path = avahi.ServiceBrowserNew(-1, -1, "_http._tcp", "local", dbus.UInt32(0))
+ browser_remote = AvahiTest.system_bus.get_object('org.freedesktop.Avahi', browser_path)
+
+ browser = dbus.Interface(browser_remote, 'org.freedesktop.Avahi.ServiceBrowser')
+
+ # Connect to the ItemNew signal from the browser:
+ def new_item_handler(interface, protocol, instance_name, instance_type, domain, flags):
+ print "Found service '%s'" % instance_name
+
+ browser.connect_to_signal("ItemNew", new_item_handler)
+
+if __name__ == '__main__':
+ unittest.main()
+ MainLoop().run()
diff --git a/boost-dbus/test/export_sample.py b/boost-dbus/test/export_sample.py
new file mode 100644
index 0000000..be8a04b
--- /dev/null
+++ b/boost-dbus/test/export_sample.py
@@ -0,0 +1,39 @@
+# Copyright (c) Benjamin Kietzman (github.com/bkietz)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import dbus
+import dbus.service
+from dbus.mainloop.glib import DBusGMainLoop
+from gobject import MainLoop
+
+bus_name = 'com.example.Sample'
+
+class Example(dbus.service.Object):
+ def __init__(self, connection, path):
+ dbus.service.Object.__init__(self, connection, path)
+ self._last_input = None
+
+ @dbus.service.method(bus_name+'.Iface', in_signature='v', out_signature='s')
+ def StringifyVariant(self, var):
+ self.LastInputChanged(var) # emits the signal
+ return str(var)
+
+ @dbus.service.signal(bus_name+'.Iface', signature='v')
+ def LastInputChanged(self, var):
+ # run just before the signal is actually emitted
+ # just put "pass" if nothing should happen
+ self._last_input = var
+
+ @dbus.service.method(bus_name+'.Iface', in_signature='', out_signature='v')
+ def GetLastInput(self):
+ return self._last_input
+
+bus = dbus.SessionBus(mainloop=DBusGMainLoop())
+bus.request_name(bus_name)
+
+example = Example(bus, '/path/to/obj')
+
+print bus.get_name_owner(bus_name)
+MainLoop().run()
diff --git a/boost-dbus/test/message.cpp b/boost-dbus/test/message.cpp
new file mode 100644
index 0000000..d591f61
--- /dev/null
+++ b/boost-dbus/test/message.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) Benjamin Kietzman (github.com/bkietz)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <dbus/error.hpp>
+#include <dbus/connection.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/filter.hpp>
+#include <dbus/match.hpp>
+#include <dbus/message.hpp>
+#include <gtest/gtest.h>
+
+TEST(MessageTest, CallMessage) {
+ const dbus::message m =
+ dbus::message::new_call(dbus::endpoint("org.freedesktop.Avahi", "/",
+ "org.freedesktop.Avahi.Server"),
+ "GetHostName");
+
+ ASSERT_EQ("org.freedesktop.Avahi", m.get_destination());
+ ASSERT_EQ("/", m.get_path());
+ ASSERT_EQ("org.freedesktop.Avahi.Server", m.get_interface());
+ ASSERT_EQ("GetHostName", m.get_member());
+
+ dbus::message m2 =
+ dbus::message::new_call(dbus::endpoint("org.freedesktop.Avahi", "/",
+ "org.freedesktop.Avahi.Server"),
+ "GetHostName");
+
+ m2 << 1;
+ int i;
+ m2 >> i;
+ ASSERT_EQ(i, 1);
+
+ // m.get_sender();
+}
+
+// I actually don't know what to do with these yet.
+/*
+TEST(MessageTest, ErrorMessage)
+{
+
+ dbus::message m = dbus::message::new_call(
+ dbus::endpoint(
+ "org.freedesktop.Avahi",
+ "/",
+ "org.freedesktop.Avahi.Server"),
+ "GetHostName");
+
+ m.set_reply_serial(42);
+ m.set_serial(43);
+
+ dbus::message em = dbus::message::new_error(
+ m,
+ "com.skizizo.NoHostname",
+ "No hostname for you!");
+
+ const error e(em);
+
+ e.throw_if_set();
+}
+*/
diff --git a/boost-dbus/test/proxy_sample.py b/boost-dbus/test/proxy_sample.py
new file mode 100644
index 0000000..a467410
--- /dev/null
+++ b/boost-dbus/test/proxy_sample.py
@@ -0,0 +1,19 @@
+# Copyright (c) Benjamin Kietzman (github.com/bkietz)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+import dbus
+from dbus.mainloop.glib import DBusGMainLoop
+from gobject import MainLoop
+
+bus_name = 'com.example.Sample'
+session_bus = dbus.SessionBus(mainloop=DBusGMainLoop())
+
+example_remote = session_bus.get_object(bus_name, '/path/to/obj')
+example = dbus.Interface(example_remote, bus_name+'.Iface')
+
+example.StringifyVariant(123)
+print example.GetLastInput()
+
+MainLoop().run()
diff --git a/crow/include/crow/http_server.h b/crow/include/crow/http_server.h
index 03bfb97..2ead557 100644
--- a/crow/include/crow/http_server.h
+++ b/crow/include/crow/http_server.h
@@ -113,7 +113,7 @@
timer.async_wait(handler);
};
timer.async_wait(handler);
-
+ CROW_LOG_INFO << init_count;
init_count++;
try {
io_service_pool_[i]->run();
diff --git a/src/dbus_main.cpp b/src/dbus_main.cpp
deleted file mode 100644
index 6cee92e..0000000
--- a/src/dbus_main.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-#define DBUS_API_SUBJECT_TO_CHANGE
-#include <dbus/dbus.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <iostream>
-#include <string>
-#include <vector>
-#include <boost/iostreams/stream.hpp>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/xml_parser.hpp>
-
-/**
- * Connect to the DBUS bus and send a broadcast signal
- */
-void sendsignal(char* sigvalue) {
- DBusMessage* msg;
- DBusMessageIter args;
- DBusConnection* conn;
- DBusError err;
- int ret;
- dbus_uint32_t serial = 0;
-
- printf("Sending signal with value %s\n", sigvalue);
-
- // initialise the error value
- dbus_error_init(&err);
-
- // connect to the DBUS system bus, and check for errors
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Connection Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (NULL == conn) {
- exit(1);
- }
-
- // register our name on the bus, and check for errors
- ret = dbus_bus_request_name(conn, "test.signal.source",
- DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Name Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
- exit(1);
- }
-
- // create a signal & check for errors
- msg = dbus_message_new_signal(
- "/test/signal/Object", // object name of the signal
- "test.signal.Type", // interface name of the signal
- "Test"); // name of the signal
- if (NULL == msg) {
- fprintf(stderr, "Message Null\n");
- exit(1);
- }
-
- // append arguments onto signal
- dbus_message_iter_init_append(msg, &args);
- if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
-
- // send the message and flush the connection
- if (!dbus_connection_send(conn, msg, &serial)) {
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- dbus_connection_flush(conn);
-
- printf("Signal Sent\n");
-
- // free the message and close the connection
- dbus_message_unref(msg);
- dbus_connection_close(conn);
-}
-
-/**
- * Call a method on a remote object
- */
-void query(const char* param) {
- DBusMessage* msg;
- DBusMessageIter args;
- DBusConnection* conn;
- DBusError err;
- DBusPendingCall* pending;
- int ret;
- bool stat;
- dbus_uint32_t level;
-
- printf("Calling remote method with %s\n", param);
-
- // initialiset the errors
- dbus_error_init(&err);
-
- // connect to the system bus and check for errors
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Connection Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (NULL == conn) {
- exit(1);
- }
- /*
- // request our name on the bus
- ret = dbus_bus_request_name(conn, "test.method.caller",
- DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Name Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
- exit(1);
- }
- */
-
- // create a new method call and check for errors
- msg = dbus_message_new_method_call(
- "org.freedesktop.Avahi", // target for the method call
- "/", // object to call on
- "org.freedesktop.Avahi.Server", // interface to call on
- "GetHostName"); // method name
- if (NULL == msg) {
- fprintf(stderr, "Message Null\n");
- exit(1);
- }
-
- // append arguments
- /*
- dbus_message_iter_init_append(msg, &args);
- if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) {
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- */
- // send message and get a handle for a reply
- if (!dbus_connection_send_with_reply(conn, msg, &pending,
- -1)) { // -1 is default timeout
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- if (NULL == pending) {
- fprintf(stderr, "Pending Call Null\n");
- exit(1);
- }
- dbus_connection_flush(conn);
-
- printf("Request Sent\n");
-
- // free message
- dbus_message_unref(msg);
-
- // block until we recieve a reply
- dbus_pending_call_block(pending);
-
- // get the reply message
- msg = dbus_pending_call_steal_reply(pending);
- if (NULL == msg) {
- fprintf(stderr, "Reply Null\n");
- exit(1);
- }
- // free the pending message handle
- dbus_pending_call_unref(pending);
-
- // read the parameters
- char* str = NULL;
- if (!dbus_message_iter_init(msg, &args))
- fprintf(stderr, "Message has no arguments!\n");
- else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
- fprintf(stderr, "Argument is not boolean!\n");
- else
- dbus_message_iter_get_basic(&args, &str);
-
- printf("Got Reply: %s\n", str);
-
- // free reply and close connection
- dbus_message_unref(msg);
- dbus_connection_close(conn);
-}
-
-void list_names() {
- DBusError err;
-
- int ret;
- bool stat;
- dbus_uint32_t level;
-
- // initialiset the errors
- dbus_error_init(&err);
-
- // connect to the system bus and check for errors
- DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Connection Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (NULL == conn) {
- exit(1);
- }
-
- // create a new method call and check for errors
- DBusMessage* msg = dbus_message_new_method_call(
- "org.freedesktop.DBus", // target for the method call
- "/", // object to call on
- "org.freedesktop.DBus", // interface to call on
- "ListNames"); // method name
- if (NULL == msg) {
- fprintf(stderr, "Message Null\n");
- exit(1);
- }
-
- DBusPendingCall* pending;
- // send message and get a handle for a reply
- if (!dbus_connection_send_with_reply(conn, msg, &pending,
- -1)) { // -1 is default timeout
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- if (NULL == pending) {
- fprintf(stderr, "Pending Call Null\n");
- exit(1);
- }
- dbus_connection_flush(conn);
-
- // free message
- dbus_message_unref(msg);
-
- // block until we recieve a reply
- dbus_pending_call_block(pending);
-
- // get the reply message
- msg = dbus_pending_call_steal_reply(pending);
- if (NULL == msg) {
- fprintf(stderr, "Reply Null\n");
- exit(1);
- }
- // free the pending message handle
- dbus_pending_call_unref(pending);
-
- // read the parameters
- DBusMessageIter args;
- DBusMessageIter strings;
- char* paths = NULL;
- if (!dbus_message_iter_init(msg, &args)) {
- fprintf(stderr, "Message has no arguments!\n");
- }
- std::vector<std::string> names;
- do {
- dbus_message_iter_recurse(&args, &strings);
- do {
- dbus_message_iter_get_basic(&strings, &paths);
- names.emplace_back(paths);
- } while (dbus_message_iter_next(&strings));
- } while (dbus_message_iter_next(&args));
-
- // free reply and close connection
- dbus_message_unref(msg);
- dbus_connection_close(conn);
-}
-
-std::vector<std::string> read_dbus_xml_names(std::string& xml_data) {
- std::vector<std::string> values;
- // populate tree structure pt
- using boost::property_tree::ptree;
- ptree pt;
- boost::iostreams::stream<boost::iostreams::array_source> stream(
- xml_data.c_str(), xml_data.size());
- read_xml(stream, pt);
-
- // traverse node to find other nodes
- for (const auto& interface : pt.get_child("node")) {
- if (interface.first == "node") {
- auto t = interface.second.get<std::string>("<xmlattr>", "default");
- for (const auto& subnode : interface.second.get_child("<xmlattr>")) {
- if (subnode.first == "name") {
- auto t = subnode.second.get("", "unknown");
- values.emplace_back(std::move(t));
- }
- }
- }
- }
- return values;
-}
-
-using sensor_values=std::vector<std::pair<std::string, int32_t>>;
-
-sensor_values read_sensor_values() {
- sensor_values values;
- DBusError err;
-
- int ret;
- bool stat;
- dbus_uint32_t level;
-
- // initialiset the errors
- dbus_error_init(&err);
-
- // connect to the system bus and check for errors
- DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
- if (dbus_error_is_set(&err)) {
- fprintf(stderr, "Connection Error (%s)\n", err.message);
- dbus_error_free(&err);
- }
- if (NULL == conn) {
- exit(1);
- }
-
- // create a new method call and check for errors
- DBusMessage* msg = dbus_message_new_method_call(
- "org.openbmc.Sensors", // target for the method call
- "/org/openbmc/sensors/tach", // object to call on
- "org.freedesktop.DBus.Introspectable", // interface to call on
- "Introspect"); // method name
- if (NULL == msg) {
- fprintf(stderr, "Message Null\n");
- exit(1);
- }
-
- DBusPendingCall* pending;
- // send message and get a handle for a reply
- if (!dbus_connection_send_with_reply(conn, msg, &pending,
- -1)) { // -1 is default timeout
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- if (NULL == pending) {
- fprintf(stderr, "Pending Call Null\n");
- exit(1);
- }
- dbus_connection_flush(conn);
-
- // free message
- dbus_message_unref(msg);
-
- // block until we recieve a reply
- dbus_pending_call_block(pending);
-
- // get the reply message
- msg = dbus_pending_call_steal_reply(pending);
- if (NULL == msg) {
- fprintf(stderr, "Reply Null\n");
- exit(1);
- }
- // free the pending message handle
- dbus_pending_call_unref(pending);
-
- // read the parameters
- DBusMessageIter args;
- char* xml_struct = NULL;
- if (!dbus_message_iter_init(msg, &args)) {
- fprintf(stderr, "Message has no arguments!\n");
- }
-
- // read the arguments
- if (!dbus_message_iter_init(msg, &args)) {
- fprintf(stderr, "Message has no arguments!\n");
- } else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
- fprintf(stderr, "Argument is not string!\n");
- } else {
- dbus_message_iter_get_basic(&args, &xml_struct);
- }
- std::vector<std::string> methods;
- if (xml_struct != NULL) {
- std::string xml_data(xml_struct);
- methods = read_dbus_xml_names(xml_data);
- }
-
- fprintf(stdout, "Found %ld sensors \n", methods.size());
-
- for (auto& method : methods) {
- // TODO(Ed) make sure sensor exposes SensorValue interface
- // create a new method call and check for errors
- DBusMessage* msg = dbus_message_new_method_call(
- "org.openbmc.Sensors", // target for the method call
- ("/org/openbmc/sensors/tach/" + method).c_str(), // object to call on
- "org.openbmc.SensorValue", // interface to call on
- "getValue"); // method name
- if (NULL == msg) {
- fprintf(stderr, "Message Null\n");
- exit(1);
- }
-
- DBusPendingCall* pending;
- // send message and get a handle for a reply
- if (!dbus_connection_send_with_reply(conn, msg, &pending,
- -1)) { // -1 is default timeout
- fprintf(stderr, "Out Of Memory!\n");
- exit(1);
- }
- if (NULL == pending) {
- fprintf(stderr, "Pending Call Null\n");
- exit(1);
- }
- dbus_connection_flush(conn);
-
- // free message
- dbus_message_unref(msg);
-
- // block until we recieve a reply
- dbus_pending_call_block(pending);
-
- // get the reply message
- msg = dbus_pending_call_steal_reply(pending);
- if (NULL == msg) {
- fprintf(stderr, "Reply Null\n");
- exit(1);
- }
- // free the pending message handle
- dbus_pending_call_unref(pending);
-
- // read the parameters
- DBusMessageIter args;
- int32_t value;
- if (!dbus_message_iter_init(msg, &args)) {
- fprintf(stderr, "Message has no arguments!\n");
- }
-
- // read the arguments
- if (!dbus_message_iter_init(msg, &args)) {
- fprintf(stderr, "Message has no arguments!\n");
- } else if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&args)) {
- fprintf(stderr, "Argument is not string!\n");
- } else {
- DBusMessageIter sub;
- dbus_message_iter_recurse(&args, &sub);
- auto type = dbus_message_iter_get_arg_type(&sub);
- if (DBUS_TYPE_INT32 != type) {
- fprintf(stderr, "Variant subType is not int32 it is %d\n", type);
- } else {
- dbus_message_iter_get_basic(&sub, &value);
- values.emplace_back(method.c_str(), value);
- }
- }
- }
-
- // free reply and close connection
- dbus_message_unref(msg);
- return values;
-}
-
-
-int main(int argc, char** argv) {
- auto values = read_sensor_values();
-
- for (auto value: values){
- std::cout << value.first << ": " << value.second << "\n";
- }
-
- return 0;
-}
\ No newline at end of file
diff --git a/src/udpclient.cpp b/src/udpclient.cpp
deleted file mode 100644
index 9bebd6e..0000000
--- a/src/udpclient.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// client.cpp
-// ~~~~~~~~~~
-//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-#include <array>
-#include <iostream>
-#include <boost/asio.hpp>
-
-using boost::asio::ip::udp;
-
-int main(int argc, char* argv[]) {
- try {
- boost::asio::io_service io_service;
-
- udp::resolver resolver(io_service);
- udp::resolver::query query(udp::v4(), "10.243.48.31", "623");
- udp::endpoint receiver_endpoint = *resolver.resolve(query);
-
- udp::socket socket(io_service);
- socket.open(udp::v4());
-
- std::string username = "root";
- std::string password = "two";
- uint8_t privilege_level = 4;
- uint8_t seq_number = 1;
- uint8_t command = 0x38; // AUTH_CAP_CMD
- // std::array<uint8_t> ChannelAuthCap{0x80 | (0x0f & channel),
- // privilege_level&0x0f};
-
- uint8_t srcaddr = 0x81; // 0xC8?
- uint8_t dstaddr = 0x20;
-
- uint8_t net_function = 0x06;
- uint8_t lun = 0;
-
- uint8_t netfn_lun = static_cast<uint8_t>((net_function << 2) + lun);
- uint8_t channel_number =
- 0x0E + 0x80; // E is defined in spec as this channel
- // 0x80 is requesting IPMI 2.0
- uint8_t byte1 = static_cast<uint8_t>(channel_number | 0x80);
- std::array<uint8_t, 2> payload{byte1, privilege_level};
-
- int payload_sum = 0;
- for (auto element : payload) {
- payload_sum += element;
- }
-
- uint8_t chk1 = (1 + ((~(dstaddr + netfn_lun)) & 0xff)) & 0xff;
- uint8_t chk2 = srcaddr + (seq_number << 2) + command + payload_sum;
- chk2 = (1 + ((~chk2) & 0xff)) & 0xff;
-
- uint8_t ptype = 0;
- uint8_t session_id = 0;
-
- uint8_t seq_number2 = 0;
- uint8_t seq_number_lun = (seq_number << 2) + lun;
-
- uint8_t seq2 = 0xff; //????
- uint8_t rmcp_class = 0x07;
-
- std::vector<uint8_t> send_buf = {
- 0x06, 0x00, seq2,
- rmcp_class, 0x06, ptype,
- session_id, seq_number2, 0x00,
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x09,
- 0x00, dstaddr, netfn_lun,
- chk1, srcaddr, seq_number_lun,
- command, channel_number, privilege_level,
- chk2};
-
- for (auto character : send_buf) {
- std::cout << std::hex << static_cast<unsigned>(character) << " ";
- }
- std::cout << std::endl;
- socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);
-
- boost::array<unsigned char, 32> recv_buf;
- udp::endpoint sender_endpoint;
- size_t len =
- socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);
- std::cout << len;
- for (auto character : recv_buf) {
- std::cout << std::hex << static_cast<unsigned>(character) << " ";
- }
-
- std::cout << std::endl;
- } catch (std::exception& e) {
- std::cerr << e.what() << std::endl;
- }
-
- return 0;
-}
\ No newline at end of file
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 404e15c..0c173dd 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -30,10 +30,12 @@
#include <boost/asio.hpp>
#include <boost/endian/arithmetic.hpp>
-#include <dbus/dbus.h>
-#include <boost/iostreams/stream.hpp>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/xml_parser.hpp>
+#include <dbus/connection.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/filter.hpp>
+#include <dbus/match.hpp>
+#include <dbus/message.hpp>
+#include <dbus/utility.hpp>
#include <iostream>
#include <memory>
@@ -42,30 +44,6 @@
using sensor_values = std::vector<std::pair<std::string, int32_t>>;
-std::vector<std::string> read_dbus_xml_names(std::string& xml_data) {
- std::vector<std::string> values;
- // populate tree structure pt
- using boost::property_tree::ptree;
- ptree pt;
- boost::iostreams::stream<boost::iostreams::array_source> stream(
- xml_data.c_str(), xml_data.size());
- read_xml(stream, pt);
-
- // traverse node to find other nodes
- for (const auto& interface : pt.get_child("node")) {
- if (interface.first == "node") {
- auto t = interface.second.get<std::string>("<xmlattr>", "default");
- for (const auto& subnode : interface.second.get_child("<xmlattr>")) {
- if (subnode.first == "name") {
- auto t = subnode.second.get("", "unknown");
- values.emplace_back(std::move(t));
- }
- }
- }
- }
- return values;
-}
-
sensor_values read_sensor_values() {
sensor_values values;
DBusError err;
@@ -144,7 +122,8 @@
std::vector<std::string> methods;
if (xml_struct != NULL) {
std::string xml_data(xml_struct);
- methods = read_dbus_xml_names(xml_data);
+ std::vector<std::string> names;
+ dbus::read_dbus_xml_names(xml_data, methods);
}
fprintf(stdout, "Found %zd sensors \n", methods.size());
@@ -235,8 +214,7 @@
ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file);
}
- crow::App<
- crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware>
+ crow::App<crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware>
app;
crow::webassets::request_routes(app);
@@ -304,22 +282,41 @@
});
CROW_ROUTE(app, "/sensortest")
- ([]() {
- crow::json::wvalue j;
- auto values = read_sensor_values();
- for (auto& pair : values) {
- j[pair.first] = pair.second;
- }
+ ([](const crow::request& req, crow::response& res) {
+ dbus::connection system_bus(*req.io_service, dbus::bus::system);
- return j;
+ dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
+ "org.freedesktop.DBus");
+ dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
+ system_bus.async_send(m, [&](const boost::system::error_code ec,
+ dbus::message r) {
+ std::vector<std::string> services;
+ //r.unpack(services);
+ for (auto& service : services) {
+ dbus::endpoint service_daemon(service, "/",
+ "org.freedesktop.DBus.Introspectable");
+ dbus::message m = dbus::message::new_call(service_daemon, "Introspect");
+ system_bus.async_send(
+ m, [&](const boost::system::error_code ec, dbus::message r) {
+ std::string xml;
+ r.unpack(xml);
+ std::vector<std::string> dbus_objects;
+ dbus::read_dbus_xml_names(xml, dbus_objects);
+
+
+ });
+ }
+
+ });
+
});
CROW_ROUTE(app, "/intel/firmwareupload")
.methods("POST"_method)([](const crow::request& req) {
// TODO(ed) handle errors here (file exists already and is locked, ect)
- std::ofstream out(
- "/tmp/fw_update_image",
- std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
+ std::ofstream out("/tmp/fw_update_image", std::ofstream::out |
+ std::ofstream::binary |
+ std::ofstream::trunc);
out << req.body;
out.close();
diff --git a/static/CMakeLists.txt b/static/CMakeLists.txt
index 29d5921..8011e6e 100644
--- a/static/CMakeLists.txt
+++ b/static/CMakeLists.txt
@@ -95,26 +95,35 @@
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
endforeach(JAVASCRIPT_ASSET)
+
+find_program(CSS_MINIFIER cssnano)
+if(NOT CSS_MINIFIER)
+ message("cssnano not found")
+endif()
# for now CSS is included as is
foreach(CSS_ASSET ${CSS_ASSETS})
set(MINIFIED_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/${CSS_ASSET})
get_filename_component(FOLDERNAME ${MINIFIED_FILENAME} DIRECTORY)
file(MAKE_DIRECTORY "${FOLDERNAME}")
- add_custom_command(OUTPUT ${MINIFIED_FILENAME}
- COMMAND cssnano
- "${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET}"
- "${CMAKE_CURRENT_BINARY_DIR}/${CSS_ASSET}"
+ if(CSS_MINIFIER)
+ message(FATAL_ERROR "cssnano not found!")
+
+ add_custom_command(OUTPUT ${MINIFIED_FILENAME}
+ COMMAND cssnano
+ "${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET}"
+ "${CMAKE_CURRENT_BINARY_DIR}/${CSS_ASSET}"
- DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET}"
- COMMENT "Minifying ${CSS_ASSET}"
- )
- list(APPEND MINIFIED_ASSETS_OUT ${MINIFIED_FILENAME})
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET}"
+ COMMENT "Minifying ${CSS_ASSET}"
+ )
+ list(APPEND MINIFIED_ASSETS_OUT ${MINIFIED_FILENAME})
+ endif()
# if it's a debug build, use the unminified version
- if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CSS_MINIFIER)
list(APPEND STATIC_ASSETS_OUT ${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET})
else()
list(APPEND STATIC_ASSETS_OUT ${MINIFIED_FILENAME})
- endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ endif (CMAKE_BUILD_TYPE STREQUAL "Debug" OR NOT CSS_MINIFIER)
endforeach(CSS_ASSET)