Lots of updates to webserver.
Make ssl keys consistent (and write to the correct location)
Make sessions keyed by connection id
Clean up logging frameworks
Add new static files, and make firmware update work
Make sensors work again
Add better json handling
Change-Id: I531a0fd7d583e049949cf27aa71544808fd7642d
diff --git a/boost-dbus/CMakeLists.txt b/boost-dbus/CMakeLists.txt
index 57bd8bd..c504ff0 100644
--- a/boost-dbus/CMakeLists.txt
+++ b/boost-dbus/CMakeLists.txt
@@ -45,10 +45,16 @@
enable_testing()
-add_executable(dbustests "test/avahi.cpp" "test/message.cpp")
+add_executable(dbustests "test/avahi.cpp" "test/message.cpp" "test/error.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")
+##############
+# Install
+Add_library(boost-dbus INTERFACE)
+target_include_directories(boost-dbus INTERFACE include/)
+install(DIRECTORY include/ DESTINATION include)
+
diff --git a/boost-dbus/include/dbus/connection.hpp b/boost-dbus/include/dbus/connection.hpp
index 50e0207..788a2c7 100644
--- a/boost-dbus/include/dbus/connection.hpp
+++ b/boost-dbus/include/dbus/connection.hpp
@@ -67,6 +67,11 @@
this->get_implementation().request_name(name);
}
+
+ std::string get_unique_name(){
+ return this->get_implementation().get_unique_name();
+ }
+
/// Reply to a message.
/**
* @param m The message from which to create the reply
@@ -106,7 +111,7 @@
* timeout was not 0), or there was some other error.
*/
template <typename Duration>
- message send(message& m, const Duration& t) {
+ message send(message& m, const Duration& t = std::chrono::seconds(0)) {
return this->get_service().send(this->get_implementation(), m, t);
}
diff --git a/boost-dbus/include/dbus/detail/queue.hpp b/boost-dbus/include/dbus/detail/queue.hpp
index c435af3..a1ca563 100644
--- a/boost-dbus/include/dbus/detail/queue.hpp
+++ b/boost-dbus/include/dbus/detail/queue.hpp
@@ -30,6 +30,11 @@
public:
queue(boost::asio::io_service& io_service) : io(io_service) {}
+ queue(const queue<Message>& m)
+ : io(m.io), messages(m.messages), handlers(m.handlers) {
+ //TODO(ed) acquire the lock before copying messages and handlers
+ }
+
private:
class closure {
handler_type handler_;
@@ -38,7 +43,7 @@
public:
void operator()() { handler_(error_, message_); }
- closure(BOOST_ASIO_MOVE_ARG(handler_type) h, Message m,
+ closure(handler_type h, Message m,
boost::system::error_code e = boost::system::error_code())
: handler_(h), message_(m), error_(e) {}
};
@@ -54,7 +59,7 @@
lock.unlock();
- io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(h), m));
+ io.post(closure(h, m));
}
}
@@ -85,7 +90,7 @@
init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
- io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(init.handler), m));
+ io.post(closure(init.handler, m));
return init.result.get();
}
diff --git a/boost-dbus/include/dbus/element.hpp b/boost-dbus/include/dbus/element.hpp
index 32cdcdc..e0118be 100644
--- a/boost-dbus/include/dbus/element.hpp
+++ b/boost-dbus/include/dbus/element.hpp
@@ -34,8 +34,8 @@
typedef std::string string;
-typedef boost::variant<std::string, bool, byte, int16, uint16, int32, uint32, int64,
- uint64, double>
+typedef boost::variant<std::string, bool, byte, int16, uint16, int32, uint32,
+ int64, uint64, double>
dbus_variant;
struct object_path {
diff --git a/boost-dbus/include/dbus/error.hpp b/boost-dbus/include/dbus/error.hpp
index 3b07c9f..63563da 100644
--- a/boost-dbus/include/dbus/error.hpp
+++ b/boost-dbus/include/dbus/error.hpp
@@ -14,7 +14,27 @@
namespace dbus {
-class error : public boost::system::error_category {
+namespace detail {
+
+class error_category : public boost::system::error_category {
+ const char *name() const BOOST_SYSTEM_NOEXCEPT { return "dbus.error"; }
+
+ string message(int value) const {
+ if (value)
+ return "DBus error";
+ else
+ return "no error";
+ }
+};
+
+} // namespace detail
+
+inline const boost::system::error_category &get_dbus_category() {
+ static detail::error_category instance;
+ return instance;
+}
+
+class error {
DBusError error_;
public:
@@ -32,10 +52,6 @@
~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_; }
@@ -48,11 +64,12 @@
};
inline boost::system::error_code error::error_code() const {
- return boost::system::error_code(is_set(), *this);
+ return boost::system::error_code(is_set(), get_dbus_category());
}
inline boost::system::system_error error::system_error() const {
- return boost::system::system_error(error_code());
+ return boost::system::system_error(
+ error_code(), string(error_.name) + ":" + error_.message);
}
inline void error::throw_if_set() const {
@@ -61,4 +78,4 @@
} // namespace dbus
-#endif // DBUS_ERROR_HPP
+#endif // DBUS_ERROR_HPP
\ No newline at end of file
diff --git a/boost-dbus/include/dbus/impl/connection.ipp b/boost-dbus/include/dbus/impl/connection.ipp
index c4c0605..41c8f92 100644
--- a/boost-dbus/include/dbus/impl/connection.ipp
+++ b/boost-dbus/include/dbus/impl/connection.ipp
@@ -51,6 +51,13 @@
e.throw_if_set();
}
+ std::string get_unique_name() {
+ error e;
+ auto name = dbus_bus_get_unique_name (conn);
+ e.throw_if_set();
+ return std::string(name);
+ }
+
~connection() {
if (conn != NULL) {
dbus_connection_close(conn);
diff --git a/boost-dbus/include/dbus/match.hpp b/boost-dbus/include/dbus/match.hpp
index cdcd169..17bc970 100644
--- a/boost-dbus/include/dbus/match.hpp
+++ b/boost-dbus/include/dbus/match.hpp
@@ -35,8 +35,6 @@
const std::string& get_expression() const { return expression_; }
- match(match&&) = delete;
- match& operator=(match&&) = delete;
};
} // namespace dbus
diff --git a/boost-dbus/include/dbus/message.hpp b/boost-dbus/include/dbus/message.hpp
index e4b0255..3829feb 100644
--- a/boost-dbus/include/dbus/message.hpp
+++ b/boost-dbus/include/dbus/message.hpp
@@ -14,6 +14,7 @@
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/for_each.hpp>
inline void intrusive_ptr_add_ref(DBusMessage* m) { dbus_message_ref(m); }
@@ -114,6 +115,17 @@
return *this << e;
}
};
+
+ template <typename Element>
+ packer pack(const Element& e) {
+ return packer(*this).pack(e);
+ }
+
+ template <typename Element, typename... Args>
+ packer pack(const Element& e, Args&... args) {
+ return packer(*this).pack(e).pack(args...);
+ }
+
struct unpacker {
impl::message_iterator iter_;
unpacker(message& m) { impl::message_iterator::init(m, iter_); }
@@ -126,15 +138,15 @@
};
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);
}
+ template <typename Element, typename... Args>
+ unpacker& unpack(Element& e, Args&... args) {
+ return unpack(e).unpack(args...);
+ }
+
private:
static std::string sanitize(const char* str) {
return (str == NULL) ? "(null)" : str;
@@ -204,50 +216,15 @@
}
inline message::packer& operator<<(message::packer& p, const dbus_variant& v) {
- message::packer sub;
- char type = 0;
- // TODO(ed) there must be a better (more typesafe) way to do this
- switch (v.which()) {
- case 0:
- type = element<std::string>::code;
- break;
- case 1:
- type = element<bool>::code;
- break;
- case 2:
- type = element<byte>::code;
- break;
- case 3:
- type = element<int16>::code;
- break;
- case 4:
- type = element<uint16>::code;
- break;
- case 5:
- type = element<int32>::code;
- break;
- case 6:
- type = element<uint32>::code;
- break;
- case 7:
- type = element<int64>::code;
- break;
- case 8:
- type = element<uint64>::code;
- break;
- case 9:
- type = element<double>::code;
- break;
-
- default:
- // TODO(ed) throw exception
- break;
- }
+ // Get the dbus typecode of the variant being packed
+ char type = boost::apply_visitor([&](auto val) {
+ return element<decltype(val)>::code;
+ }, v);
char signature[] = {type, 0};
+ message::packer sub;
p.iter_.open_container(element<dbus_variant>::code, signature, sub.iter_);
boost::apply_visitor([&](auto val) { sub << val; }, v);
- // sub << element;
p.iter_.close_container(sub.iter_);
return p;
@@ -274,69 +251,24 @@
return u;
}
+inline message::unpacker& operator>>(message::unpacker& u, object_path& o) {
+ return u >> o.value;
+}
+
inline message::unpacker& operator>>(message::unpacker& u, dbus_variant& v) {
message::unpacker sub;
u.iter_.recurse(sub.iter_);
- auto arg_type = sub.iter_.get_arg_type();
- // sub.iter_.get_basic(&c);
- // Todo(ed) find a better way to do this lookup table
- switch (arg_type) {
- case element<std::string>::code: {
- std::string s;
- sub >> s;
- v = s;
- } break;
- case element<bool>::code: {
- bool b;
- sub >> b;
- v = b;
- } break;
- case element<byte>::code: {
- byte b;
- sub >> b;
- v = b;
- } break;
- case element<int16>::code: {
- int16 b;
- sub >> b;
- v = b;
- } break;
- case element<uint16>::code: {
- uint16 b;
- sub >> b;
- v = b;
- } break;
- case element<int32>::code: {
- int32 b;
- sub >> b;
- v = b;
- } break;
- case element<uint32>::code: {
- uint32 b;
- sub >> b;
- v = b;
- } break;
- case element<int64>::code: {
- int64 b;
- sub >> b;
- v = b;
- } break;
- case element<uint64>::code: {
- uint64 b;
- sub >> b;
- v = b;
- } break;
- case element<double>::code: {
- double b;
- sub >> b;
- v = b;
- } break;
+ char arg_type = sub.iter_.get_arg_type();
- default:
- // TODO(ed) throw exception
- break;
- }
+ boost::mpl::for_each<dbus_variant::types>([&](auto t) {
+ if (arg_type == element<decltype(t)>::code){
+ decltype(t) val_to_fill;
+ sub >> val_to_fill;
+ v = val_to_fill;
+ }
+ });
+
u.iter_.next();
return u;
}
diff --git a/boost-dbus/include/dbus/utility.hpp b/boost-dbus/include/dbus/utility.hpp
deleted file mode 100644
index 47fad1c..0000000
--- a/boost-dbus/include/dbus/utility.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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
index 5d2deb8..1b46c02 100644
--- a/boost-dbus/test/avahi.cpp
+++ b/boost-dbus/test/avahi.cpp
@@ -8,7 +8,6 @@
#include <dbus/filter.hpp>
#include <dbus/match.hpp>
#include <dbus/message.hpp>
-#include <dbus/utility.hpp>
#include <functional>
#include <unistd.h>
@@ -123,57 +122,25 @@
io.run();
}
-void query_interfaces(dbus::connection_ptr 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, SingleSensorChanged) {
boost::asio::io_service io;
auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
- dbus::match ma(system_bus,
- "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
+ dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
dbus::filter f(system_bus, [](dbus::message& m) {
auto member = m.get_member();
return member == "PropertiesChanged";
});
- // std::function<void(boost::system::error_code, dbus::message)> event_handler
- // =
-
f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
std::string object_name;
EXPECT_EQ(s.get_path(),
"/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
std::vector<std::pair<std::string, dbus::dbus_variant>> values;
- s.unpack(object_name).unpack(values);
-
+ s.unpack(object_name, values);
EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
EXPECT_EQ(values.size(), 1);
@@ -226,8 +193,7 @@
"/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
std::vector<std::pair<std::string, dbus::dbus_variant>> values;
- s.unpack(object_name).unpack(values);
-
+ s.unpack(object_name, values);
EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
EXPECT_EQ(values.size(), 1);
@@ -239,6 +205,7 @@
} else {
f.async_dispatch(callback);
}
+ s.unpack(object_name, values);
};
f.async_dispatch(callback);
@@ -275,18 +242,11 @@
io.stop();
FAIL() << "Callback was never called\n";
});
- std::string requested_name = "xyz.openbmc_project.fwupdate1.server";
- auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
- //system_bus->request_name(requested_name);
- /* not sure we even need to add a match for method calls,
- * but this is how you might do it .... */
- dbus::match ma(
- system_bus,
- "type='method_call',path_namespace='/xyz/openbmc_project/fwupdate1'");
+ auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
+ std::string requested_name = system_bus->get_unique_name();
dbus::filter f(system_bus, [](dbus::message& m) {
- // std::cerr << "filter called: " << m << std::endl;
return (m.get_member() == "Get" &&
m.get_interface() == "org.freedesktop.DBus.Properties" &&
m.get_signature() == "ss");
@@ -298,7 +258,7 @@
FAIL() << ec;
} else {
std::string intf_name, prop_name;
- s.unpack(intf_name).unpack(prop_name);
+ s.unpack(intf_name, prop_name);
EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
EXPECT_EQ(prop_name, "State");
@@ -306,25 +266,26 @@
// send a reply so dbus doesn't get angry?
auto r = system_bus->reply(s);
r.pack("IDLE");
- system_bus->async_send(
- r, [&](boost::system::error_code ec, dbus::message s) {});
- io.stop();
+ system_bus->async_send(r, [&](boost::system::error_code ec,
+ dbus::message s) { });
+ io.stop();
}
- };
+ };
f.async_dispatch(method_handler);
- dbus::endpoint test_endpoint(requested_name, "/xyz/openbmc_project/fwupdate1",
- "org.freedesktop.DBus.Properties");
+ dbus::endpoint test_endpoint(
+ requested_name,
+ "/xyz/openbmc_project/fwupdate1",
+ "org.freedesktop.DBus.Properties");
auto method_name = std::string("Get");
auto m = dbus::message::new_call(test_endpoint, method_name);
- m.pack("xyz.openbmc_project.fwupdate1");
- m.pack("State");
-
- system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {
- std::cerr << "received s: " << s << std::endl;
- });
+ m.pack("xyz.openbmc_project.fwupdate1", "State");
+ system_bus->async_send(m,
+ [&](boost::system::error_code ec, dbus::message s) {
+ std::cerr <<"received s: " << s << std::endl;
+ });
io.run();
}
diff --git a/boost-dbus/test/error.cpp b/boost-dbus/test/error.cpp
new file mode 100644
index 0000000..0c0cf60
--- /dev/null
+++ b/boost-dbus/test/error.cpp
@@ -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)
+
+#include <dbus/connection.hpp>
+#include <dbus/endpoint.hpp>
+#include <dbus/filter.hpp>
+#include <dbus/match.hpp>
+#include <dbus/message.hpp>
+#include <functional>
+
+#include <unistd.h>
+#include <gtest/gtest.h>
+
+using namespace boost::asio;
+using namespace dbus;
+using boost::system::error_code;
+
+TEST(ErrorTest, GetHostName) {
+ io_service io;
+ EXPECT_THROW(connection system_bus(io, "unix:path=/foo/bar/baz_socket"),
+ boost::system::system_error);
+
+ io.run();
+}
\ No newline at end of file
diff --git a/boost-dbus/test/message.cpp b/boost-dbus/test/message.cpp
index 8c8169f..aaf49c6 100644
--- a/boost-dbus/test/message.cpp
+++ b/boost-dbus/test/message.cpp
@@ -47,7 +47,21 @@
m.pack(v);
std::vector<dbus::dbus_variant> av{{std::string("hello world"), 1, 42}};
- m.pack(av);
+ m.pack(v, av);
+}
+
+
+TEST(MessageTest, VariadicCallback) {
+ auto signal_name = std::string("PropertiesChanged");
+ dbus::endpoint test_endpoint(
+ "org.freedesktop.Avahi",
+ "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
+ "org.freedesktop.DBus.Properties");
+ auto m = dbus::message::new_signal(test_endpoint, signal_name);
+
+ dbus::dbus_variant v(std::string("hello world"));
+ std::vector<dbus::dbus_variant> av{{std::string("hello world"), 1, 42}};
+ m.pack(v, av);
}
// I actually don't know what to do with these yet.