Use tag dispatching to construct various types of Connection, refactor Connection unit tests

This commit is contained in:
sangelovic
2019-11-03 20:30:52 +01:00
parent 099bc857ad
commit 304b69dd8b
5 changed files with 153 additions and 148 deletions

View File

@@ -35,54 +35,33 @@
#include <poll.h>
#include <sys/eventfd.h>
namespace {
std::vector</*const */char*> to_strv(const std::vector<std::string>& strings)
{
std::vector</*const */char*> strv;
for (auto& str : strings)
strv.push_back(const_cast<char*>(str.c_str()));
strv.push_back(nullptr);
return strv;
}
}
namespace sdbus { namespace internal {
Connection::Connection(Connection::BusType type, std::unique_ptr<ISdBus>&& interface)
Connection::Connection(std::unique_ptr<ISdBus>&& interface, const BusFactory& busFactory)
: iface_(std::move(interface))
, busType_(type)
, bus_(openBus(busFactory))
{
assert(iface_ != nullptr);
auto bus = openBus(busType_);
bus_.reset(bus);
finishHandshake(bus);
loopExitFd_ = createProcessingLoopExitDescriptor();
}
Connection::Connection(const std::string& host, std::unique_ptr<ISdBus> &&interface)
: iface_(std::move(interface))
, busType_(BusType::eRemoteSystem)
, host_(host)
Connection::Connection(std::unique_ptr<ISdBus>&& interface, system_bus_t)
: Connection(std::move(interface), [this](sd_bus** bus){ return iface_->sd_bus_open_system(bus); })
{
assert(iface_ != nullptr);
}
auto bus = openBus(busType_);
bus_.reset(bus);
Connection::Connection(std::unique_ptr<ISdBus>&& interface, session_bus_t)
: Connection(std::move(interface), [this](sd_bus** bus){ return iface_->sd_bus_open_user(bus); })
{
}
finishHandshake(bus);
loopExitFd_ = createProcessingLoopExitDescriptor();
Connection::Connection(std::unique_ptr<ISdBus>&& interface, remote_system_bus_t, const std::string& host)
: Connection(std::move(interface), [this, &host](sd_bus** bus){ return iface_->sd_bus_open_system_remote(bus, host.c_str()); })
{
}
Connection::~Connection()
{
leaveProcessingLoop();
closeProcessingLoopExitDescriptor(loopExitFd_);
}
void Connection::requestName(const std::string& name)
@@ -301,23 +280,15 @@ SlotPtr Connection::registerSignalHandler( const std::string& objectPath
return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }};
}
sd_bus* Connection::openBus(Connection::BusType type)
Connection::BusPtr Connection::openBus(const BusFactory& busFactory)
{
sd_bus* bus{};
int r = 0;
if (type == BusType::eSystem)
r = iface_->sd_bus_open_system(&bus);
else if (type == BusType::eSession)
r = iface_->sd_bus_open_user(&bus);
else if (type == BusType::eRemoteSystem)
r = iface_->sd_bus_open_system_remote(&bus, host_.c_str());
else
assert(false);
int r = busFactory(&bus);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to open bus", -r);
assert(bus != nullptr);
return bus;
BusPtr busPtr{bus, [this](sd_bus* bus){ return iface_->sd_bus_flush_close_unref(bus); }};
finishHandshake(busPtr.get());
return busPtr;
}
void Connection::finishHandshake(sd_bus* bus)
@@ -333,33 +304,19 @@ void Connection::finishHandshake(sd_bus* bus)
SDBUS_THROW_ERROR_IF(r < 0, "Failed to flush bus on opening", -r);
}
int Connection::createProcessingLoopExitDescriptor()
{
auto r = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create event object", -errno);
return r;
}
void Connection::closeProcessingLoopExitDescriptor(int fd)
{
close(fd);
}
void Connection::notifyProcessingLoopToExit()
{
assert(loopExitFd_ >= 0);
assert(loopExitFd_.fd >= 0);
uint64_t value = 1;
auto r = write(loopExitFd_, &value, sizeof(value));
auto r = write(loopExitFd_.fd, &value, sizeof(value));
SDBUS_THROW_ERROR_IF(r < 0, "Failed to notify processing loop", -errno);
}
void Connection::clearExitNotification()
{
uint64_t value{};
auto r = read(loopExitFd_, &value, sizeof(value));
auto r = read(loopExitFd_.fd, &value, sizeof(value));
SDBUS_THROW_ERROR_IF(r < 0, "Failed to read from the event descriptor", -errno);
}
@@ -385,10 +342,10 @@ bool Connection::waitForNextRequest()
auto bus = bus_.get();
assert(bus != nullptr);
assert(loopExitFd_ != 0);
assert(loopExitFd_.fd != 0);
auto sdbusPollData = getProcessLoopPollData();
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_, POLLIN, 0}};
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_.fd, POLLIN, 0}};
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
auto timeout = sdbusPollData.timeout_usec == (uint64_t) -1 ? (uint64_t)-1 : (sdbusPollData.timeout_usec+999)/1000;
@@ -422,6 +379,27 @@ std::string Connection::composeSignalMatchFilter( const std::string& objectPath
return filter;
}
std::vector</*const */char*> Connection::to_strv(const std::vector<std::string>& strings)
{
std::vector</*const */char*> strv;
for (auto& str : strings)
strv.push_back(const_cast<char*>(str.c_str()));
strv.push_back(nullptr);
return strv;
}
Connection::LoopExitEventFd::LoopExitEventFd()
{
fd = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK);
SDBUS_THROW_ERROR_IF(fd < 0, "Failed to create event object", -errno);
}
Connection::LoopExitEventFd::~LoopExitEventFd()
{
assert(fd >= 0);
close(fd);
}
}}
namespace sdbus {
@@ -440,8 +418,8 @@ std::unique_ptr<sdbus::IConnection> createSystemBusConnection()
{
auto interface = std::make_unique<sdbus::internal::SdBus>();
assert(interface != nullptr);
return std::make_unique<sdbus::internal::Connection>( sdbus::internal::Connection::BusType::eSystem
, std::move(interface));
constexpr sdbus::internal::Connection::system_bus_t system_bus;
return std::make_unique<sdbus::internal::Connection>(std::move(interface), system_bus);
}
std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const std::string& name)
@@ -455,8 +433,8 @@ std::unique_ptr<sdbus::IConnection> createSessionBusConnection()
{
auto interface = std::make_unique<sdbus::internal::SdBus>();
assert(interface != nullptr);
return std::make_unique<sdbus::internal::Connection>( sdbus::internal::Connection::BusType::eSession
, std::move(interface));
constexpr sdbus::internal::Connection::session_bus_t session_bus;
return std::make_unique<sdbus::internal::Connection>(std::move(interface), session_bus);
}
std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const std::string& name)
@@ -470,8 +448,8 @@ std::unique_ptr<sdbus::IConnection> createRemoteSystemBusConnection(const std::s
{
auto interface = std::make_unique<sdbus::internal::SdBus>();
assert(interface != nullptr);
return std::make_unique<sdbus::internal::Connection>( host
, std::move(interface));
constexpr sdbus::internal::Connection::remote_system_bus_t remote_system_bus;
return std::make_unique<sdbus::internal::Connection>(std::move(interface), remote_system_bus, host);
}
}