forked from Kistler-Group/sdbus-cpp
refactor: use pseudo D-Bus connection for plain messages
This commit is contained in:
committed by
Stanislav Angelovič
parent
0f2362d8c3
commit
2991fa4960
@ -70,6 +70,13 @@ Connection::Connection(std::unique_ptr<ISdBus>&& interface, remote_system_bus_t,
|
||||
{
|
||||
}
|
||||
|
||||
Connection::Connection(std::unique_ptr<ISdBus>&& interface, pseudo_bus_t)
|
||||
: iface_(std::move(interface))
|
||||
, bus_(openPseudoBus())
|
||||
{
|
||||
assert(iface_ != nullptr);
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
Connection::leaveEventLoop();
|
||||
@ -394,6 +401,23 @@ Connection::BusPtr Connection::openBus(const BusFactory& busFactory)
|
||||
return busPtr;
|
||||
}
|
||||
|
||||
Connection::BusPtr Connection::openPseudoBus()
|
||||
{
|
||||
sd_bus* bus{};
|
||||
|
||||
int r = iface_->sd_bus_new(&bus);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to open pseudo bus", -r);
|
||||
|
||||
(void)iface_->sd_bus_start(bus);
|
||||
// It is expected that sd_bus_start has failed here, returning -EINVAL, due to having
|
||||
// not set a bus address, but it will leave the bus in an OPENING state, which enables
|
||||
// us to create plain D-Bus messages as a local data storage (for Variant, for example),
|
||||
// without dependency on real IPC communication with the D-Bus broker daemon.
|
||||
SDBUS_THROW_ERROR_IF(r < 0 && r != -EINVAL, "Failed to start pseudo bus", -r);
|
||||
|
||||
return {bus, [this](sd_bus* bus){ return iface_->sd_bus_close_unref(bus); }};
|
||||
}
|
||||
|
||||
void Connection::finishHandshake(sd_bus* bus)
|
||||
{
|
||||
// Process all requests that are part of the initial handshake,
|
||||
@ -573,6 +597,12 @@ std::unique_ptr<sdbus::internal::IConnection> createConnection()
|
||||
return std::unique_ptr<sdbus::internal::IConnection>(connectionInternal);
|
||||
}
|
||||
|
||||
std::unique_ptr<sdbus::internal::IConnection> createPseudoConnection()
|
||||
{
|
||||
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
||||
return std::make_unique<sdbus::internal::Connection>(std::move(interface), Connection::pseudo_bus);
|
||||
}
|
||||
|
||||
} // namespace sdbus::internal
|
||||
|
||||
namespace sdbus {
|
||||
|
@ -57,12 +57,15 @@ namespace sdbus::internal {
|
||||
inline static constexpr custom_session_bus_t custom_session_bus{};
|
||||
struct remote_system_bus_t{};
|
||||
inline static constexpr remote_system_bus_t remote_system_bus{};
|
||||
struct pseudo_bus_t{}; // A bus connection that is not really established with D-Bus daemon
|
||||
inline static constexpr pseudo_bus_t pseudo_bus{};
|
||||
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, default_bus_t);
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, system_bus_t);
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, session_bus_t);
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, custom_session_bus_t, const std::string& address);
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, remote_system_bus_t, const std::string& host);
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, pseudo_bus_t);
|
||||
~Connection() override;
|
||||
|
||||
void requestName(const std::string& name) override;
|
||||
@ -126,6 +129,7 @@ namespace sdbus::internal {
|
||||
Connection(std::unique_ptr<ISdBus>&& interface, const BusFactory& busFactory);
|
||||
|
||||
BusPtr openBus(const std::function<int(sd_bus**)>& busFactory);
|
||||
BusPtr openPseudoBus();
|
||||
void finishHandshake(sd_bus* bus);
|
||||
bool waitForNextRequest();
|
||||
static std::string composeSignalMatchFilter( const std::string &sender
|
||||
|
@ -95,6 +95,7 @@ namespace sdbus::internal {
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<sdbus::internal::IConnection> createConnection();
|
||||
[[nodiscard]] std::unique_ptr<sdbus::internal::IConnection> createPseudoConnection();
|
||||
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,15 @@ namespace sdbus::internal {
|
||||
virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata) = 0;
|
||||
virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) = 0;
|
||||
|
||||
virtual int sd_bus_new(sd_bus **ret) = 0;
|
||||
virtual int sd_bus_start(sd_bus *bus) = 0;
|
||||
|
||||
virtual int sd_bus_process(sd_bus *bus, sd_bus_message **r) = 0;
|
||||
virtual int sd_bus_get_poll_data(sd_bus *bus, PollData* data) = 0;
|
||||
|
||||
virtual int sd_bus_flush(sd_bus *bus) = 0;
|
||||
virtual sd_bus *sd_bus_flush_close_unref(sd_bus *bus) = 0;
|
||||
virtual sd_bus *sd_bus_close_unref(sd_bus *bus) = 0;
|
||||
|
||||
virtual int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) = 0;
|
||||
|
||||
|
@ -864,9 +864,13 @@ void Signal::setDestination(const std::string& destination)
|
||||
|
||||
PlainMessage createPlainMessage()
|
||||
{
|
||||
static auto connection = internal::createConnection();
|
||||
//static auto connection = internal::createConnection();
|
||||
// Let's create a pseudo connection -- one that does not really connect to the real bus.
|
||||
// This is a bit of a hack, but it enables use to work with D-Bus message locally without
|
||||
// the need of D-Bus daemon. This is especially useful in unit tests of both sdbus-c++ and client code.
|
||||
// Additionally, it's light-weight and fast solution.
|
||||
static auto connection = internal::createPseudoConnection();
|
||||
return connection->createPlainMessage();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -261,6 +261,16 @@ sd_bus_slot* SdBus::sd_bus_slot_unref(sd_bus_slot *slot)
|
||||
return ::sd_bus_slot_unref(slot);
|
||||
}
|
||||
|
||||
int SdBus::sd_bus_new(sd_bus **ret)
|
||||
{
|
||||
return ::sd_bus_new(ret);
|
||||
}
|
||||
|
||||
int SdBus::sd_bus_start(sd_bus *bus)
|
||||
{
|
||||
return ::sd_bus_start(bus);
|
||||
}
|
||||
|
||||
int SdBus::sd_bus_process(sd_bus *bus, sd_bus_message **r)
|
||||
{
|
||||
std::lock_guard lock(sdbusMutex_);
|
||||
@ -297,6 +307,16 @@ sd_bus* SdBus::sd_bus_flush_close_unref(sd_bus *bus)
|
||||
return ::sd_bus_flush_close_unref(bus);
|
||||
}
|
||||
|
||||
sd_bus* SdBus::sd_bus_close_unref(sd_bus *bus)
|
||||
{
|
||||
#if LIBSYSTEMD_VERSION>=241
|
||||
return ::sd_bus_close_unref(bus);
|
||||
#else
|
||||
::sd_bus_close(bus);
|
||||
return ::sd_bus_unref(bus);
|
||||
#endif
|
||||
}
|
||||
|
||||
int SdBus::sd_bus_message_set_destination(sd_bus_message *m, const char *destination)
|
||||
{
|
||||
std::lock_guard lock(sdbusMutex_);
|
||||
|
@ -71,11 +71,15 @@ public:
|
||||
virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata) override;
|
||||
virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) override;
|
||||
|
||||
virtual int sd_bus_new(sd_bus **ret) override;
|
||||
virtual int sd_bus_start(sd_bus *bus) override;
|
||||
|
||||
virtual int sd_bus_process(sd_bus *bus, sd_bus_message **r) override;
|
||||
virtual int sd_bus_get_poll_data(sd_bus *bus, PollData* data) override;
|
||||
|
||||
virtual int sd_bus_flush(sd_bus *bus) override;
|
||||
virtual sd_bus *sd_bus_flush_close_unref(sd_bus *bus) override;
|
||||
virtual sd_bus *sd_bus_close_unref(sd_bus *bus) override;
|
||||
|
||||
virtual int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) override;
|
||||
|
||||
|
@ -173,6 +173,12 @@ template<> void AConnectionNameRequest<Connection::remote_system_bus_t>::setUpBu
|
||||
{
|
||||
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system_remote(_, _)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||
}
|
||||
template<> void AConnectionNameRequest<Connection::pseudo_bus_t>::setUpBusOpenExpectation()
|
||||
{
|
||||
EXPECT_CALL(*sdBusIntfMock_, sd_bus_new(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||
// `sd_bus_start` for pseudo connection shall return an error value, remember this is a fake connection...
|
||||
EXPECT_CALL(*sdBusIntfMock_, sd_bus_start(fakeBusPtr_)).WillOnce(Return(-EINVAL));
|
||||
}
|
||||
template <typename _BusTypeTag>
|
||||
std::unique_ptr<Connection> AConnectionNameRequest<_BusTypeTag>::makeConnection()
|
||||
{
|
||||
@ -192,6 +198,7 @@ typedef ::testing::Types< Connection::default_bus_t
|
||||
, Connection::session_bus_t
|
||||
, Connection::custom_session_bus_t
|
||||
, Connection::remote_system_bus_t
|
||||
, Connection::pseudo_bus_t
|
||||
> BusTypeTags;
|
||||
|
||||
TYPED_TEST_SUITE(AConnectionNameRequest, BusTypeTags);
|
||||
|
@ -70,11 +70,15 @@ public:
|
||||
MOCK_METHOD5(sd_bus_add_match, int(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata));
|
||||
MOCK_METHOD1(sd_bus_slot_unref, sd_bus_slot*(sd_bus_slot *slot));
|
||||
|
||||
MOCK_METHOD1(sd_bus_new, int(sd_bus **ret));
|
||||
MOCK_METHOD1(sd_bus_start, int(sd_bus *bus));
|
||||
|
||||
MOCK_METHOD2(sd_bus_process, int(sd_bus *bus, sd_bus_message **r));
|
||||
MOCK_METHOD2(sd_bus_get_poll_data, int(sd_bus *bus, PollData* data));
|
||||
|
||||
MOCK_METHOD1(sd_bus_flush, int(sd_bus *bus));
|
||||
MOCK_METHOD1(sd_bus_flush_close_unref, sd_bus *(sd_bus *bus));
|
||||
MOCK_METHOD1(sd_bus_close_unref, sd_bus *(sd_bus *bus));
|
||||
|
||||
MOCK_METHOD2(sd_bus_message_set_destination, int(sd_bus_message *m, const char *destination));
|
||||
|
||||
|
Reference in New Issue
Block a user