diff options
author | Dirk Huss <dirk_huss@mentor.com> | 2015-11-25 14:59:52 +0100 |
---|---|---|
committer | Dirk Huss <dirk_huss@mentor.com> | 2015-11-25 14:59:52 +0100 |
commit | faea5f299525500093843da72215d279c3eb483d (patch) | |
tree | 559a22a4f9844a4f8d04d8e39f37d04da797d1a0 /src/CommonAPI/DBus | |
parent | db96446ece67ba1f495811e29838e8c7bc7984ff (diff) | |
download | genivi-common-api-dbus-runtime-faea5f299525500093843da72215d279c3eb483d.tar.gz |
CommonAPI-D-Bus 3.1.43.1.4
Diffstat (limited to 'src/CommonAPI/DBus')
21 files changed, 2232 insertions, 1103 deletions
diff --git a/src/CommonAPI/DBus/DBusAddress.cpp b/src/CommonAPI/DBus/DBusAddress.cpp index f317e57..d73cfc0 100644 --- a/src/CommonAPI/DBus/DBusAddress.cpp +++ b/src/CommonAPI/DBus/DBusAddress.cpp @@ -11,17 +11,17 @@ namespace CommonAPI { namespace DBus { DBusAddress::DBusAddress(const std::string &_service, - const std::string &_objectPath, - const std::string &_interface) - : service_(_service), - objectPath_(_objectPath), - interface_(_interface) { + const std::string &_objectPath, + const std::string &_interface) + : service_(_service), + objectPath_(_objectPath), + interface_(_interface) { } DBusAddress::DBusAddress(const DBusAddress &_source) - : service_(_source.service_), - objectPath_(_source.objectPath_), - interface_(_source.interface_) { + : service_(_source.service_), + objectPath_(_source.objectPath_), + interface_(_source.interface_) { } DBusAddress::~DBusAddress() { @@ -29,72 +29,72 @@ DBusAddress::~DBusAddress() { bool DBusAddress::operator==(const DBusAddress &_other) const { - return (service_ == _other.service_ && - objectPath_ == _other.objectPath_ && - interface_ == _other.interface_); + return (service_ == _other.service_ && + objectPath_ == _other.objectPath_ && + interface_ == _other.interface_); } bool DBusAddress::operator !=(const DBusAddress &_other) const { - return (service_ != _other.service_ || - objectPath_ != _other.objectPath_ || - interface_ != _other.interface_); + return (service_ != _other.service_ || + objectPath_ != _other.objectPath_ || + interface_ != _other.interface_); } bool DBusAddress::operator<(const DBusAddress &_other) const { - if (service_ < _other.service_) - return true; + if (service_ < _other.service_) + return true; - if (service_ == _other.service_) { - if (objectPath_ < _other.objectPath_) - return true; + if (service_ == _other.service_) { + if (objectPath_ < _other.objectPath_) + return true; - if (objectPath_ == _other.objectPath_) { - if (interface_ < _other.interface_) - return true; - } - } + if (objectPath_ == _other.objectPath_) { + if (interface_ < _other.interface_) + return true; + } + } - return false; + return false; } const std::string & DBusAddress::getService() const { - return service_; + return service_; } void DBusAddress::setService(const std::string &_service) { - service_ = _service; + service_ = _service; } const std::string & DBusAddress::getObjectPath() const { - return objectPath_; + return objectPath_; } void DBusAddress::setObjectPath(const std::string &_objectPath) { - objectPath_ = _objectPath; + objectPath_ = _objectPath; } const std::string & DBusAddress::getInterface() const { - return interface_; + return interface_; } void DBusAddress::setInterface(const std::string &_interface) { - interface_ = _interface; + interface_ = _interface; } std::ostream & operator<<(std::ostream &_out, const DBusAddress &_dbusAddress) { - _out << "service=" << _dbusAddress.service_.c_str() - << ":path=" << _dbusAddress.objectPath_.c_str() - << ":interface=" << _dbusAddress.interface_.c_str(); - return _out; + _out << "service=" << _dbusAddress.service_.c_str() + << ":path=" << _dbusAddress.objectPath_.c_str() + << ":interface=" << _dbusAddress.interface_.c_str(); + return _out; } diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.cpp b/src/CommonAPI/DBus/DBusAddressTranslator.cpp index 0c653dc..cb208c0 100644 --- a/src/CommonAPI/DBus/DBusAddressTranslator.cpp +++ b/src/CommonAPI/DBus/DBusAddressTranslator.cpp @@ -26,314 +26,310 @@ const char *COMMONAPI_DBUS_DEFAULT_CONFIG_FOLDER = "/etc/"; std::shared_ptr<DBusAddressTranslator> DBusAddressTranslator::get() { - static std::shared_ptr<DBusAddressTranslator> theTranslator = std::make_shared<DBusAddressTranslator>(); - return theTranslator; + static std::shared_ptr<DBusAddressTranslator> theTranslator = std::make_shared<DBusAddressTranslator>(); + return theTranslator; } DBusAddressTranslator::DBusAddressTranslator() - : defaultDomain_("local"), orgFreedesktopDBusPeerMapped_(false) { - init(); + : defaultDomain_("local"), orgFreedesktopDBusPeerMapped_(false) { + init(); - isDefault_ = ("dbus" == Runtime::get()->getDefaultBinding()); + isDefault_ = ("dbus" == Runtime::get()->getDefaultBinding()); } void DBusAddressTranslator::init() { - // Determine default configuration file - const char *config = getenv("COMMONAPI_DBUS_DEFAULT_CONFIG"); - if (config) { - defaultConfig_ = config; - } else { - defaultConfig_ = COMMONAPI_DBUS_DEFAULT_CONFIG_FOLDER; - defaultConfig_ += "/"; - defaultConfig_ += COMMONAPI_DBUS_DEFAULT_CONFIG_FILE; - } - - (void)readConfiguration(); + // Determine default configuration file + const char *config = getenv("COMMONAPI_DBUS_CONFIG"); + if (config) { + defaultConfig_ = config; + } else { + defaultConfig_ = COMMONAPI_DBUS_DEFAULT_CONFIG_FOLDER; + defaultConfig_ += "/"; + defaultConfig_ += COMMONAPI_DBUS_DEFAULT_CONFIG_FILE; + } + + (void)readConfiguration(); } bool DBusAddressTranslator::translate(const std::string &_key, DBusAddress &_value) { - return translate(CommonAPI::Address(_key), _value); + return translate(CommonAPI::Address(_key), _value); } bool DBusAddressTranslator::translate(const CommonAPI::Address &_key, DBusAddress &_value) { - bool result(true); - std::lock_guard<std::mutex> itsLock(mutex_); - - const auto it = forwards_.find(_key); - if (it != forwards_.end()) { - _value = it->second; - } else if (isDefault_) { - std::string interfaceName(_key.getInterface()); - std::string objectPath("/" + _key.getInstance()); - std::replace(objectPath.begin(), objectPath.end(), '.', '/'); - std::string service(_key.getInterface() + "_" + _key.getInstance()); - - if (isValid(service, '.', false, false, true) - && isValid(objectPath, '/', true) - && isValid(interfaceName, '.')) { - _value.setInterface(interfaceName); - _value.setObjectPath(objectPath); - _value.setService(service); - - forwards_.insert({ _key, _value }); - backwards_.insert({ _value, _key }); - } - } else { - result = false; - } - - return result; + bool result(true); + std::lock_guard<std::mutex> itsLock(mutex_); + + const auto it = forwards_.find(_key); + if (it != forwards_.end()) { + _value = it->second; + } else if (isDefault_) { + std::string interfaceName(_key.getInterface()); + std::string objectPath("/" + _key.getInstance()); + std::replace(objectPath.begin(), objectPath.end(), '.', '/'); + std::string service(_key.getInterface() + "_" + _key.getInstance()); + + if (isValid(service, '.', false, false, true) + && isValid(objectPath, '/', true) + && isValid(interfaceName, '.')) { + _value.setInterface(interfaceName); + _value.setObjectPath(objectPath); + _value.setService(service); + + forwards_.insert({ _key, _value }); + backwards_.insert({ _value, _key }); + } + } else { + result = false; + } + + return result; } bool DBusAddressTranslator::translate(const DBusAddress &_key, std::string &_value) { - CommonAPI::Address address; - if (translate(_key, address)) { - _value = address.getAddress(); - return true; - } - return false; + CommonAPI::Address address; + if (translate(_key, address)) { + _value = address.getAddress(); + return true; + } + return false; } bool DBusAddressTranslator::translate(const DBusAddress &_key, CommonAPI::Address &_value) { - bool result(true); - std::lock_guard<std::mutex> itsLock(mutex_); - - const auto it = backwards_.find(_key); - if (it != backwards_.end()) { - _value = it->second; - } else if (isDefault_) { - if (isValid(_key.getObjectPath(), '/', true) && isValid(_key.getInterface(), '.')) { - std::string interfaceName(_key.getInterface()); - std::string instance(_key.getObjectPath().substr(1)); - std::replace(instance.begin(), instance.end(), '/', '.'); - - _value.setDomain(defaultDomain_); - _value.setInterface(interfaceName); - _value.setInstance(instance); - - forwards_.insert({_value, _key}); - backwards_.insert({_key, _value}); - } else { - result = false; - } - } else { - result = false; - } - - return result; + bool result(true); + std::lock_guard<std::mutex> itsLock(mutex_); + + const auto it = backwards_.find(_key); + if (it != backwards_.end()) { + _value = it->second; + } else if (isDefault_) { + if (isValid(_key.getObjectPath(), '/', true) && isValid(_key.getInterface(), '.')) { + std::string interfaceName(_key.getInterface()); + std::string instance(_key.getObjectPath().substr(1)); + std::replace(instance.begin(), instance.end(), '/', '.'); + + _value.setDomain(defaultDomain_); + _value.setInterface(interfaceName); + _value.setInstance(instance); + + std::string service = _key.getService(); + if(isValid(service, '.', + (service.length() > 0 && service[0] == ':'), + (service.length() > 0 && service[0] == ':'), + true)) { + forwards_.insert({_value, _key}); + backwards_.insert({_key, _value}); + } + } else { + result = false; + } + } else { + result = false; + } + + return result; } - void DBusAddressTranslator::insert( - const std::string &_address, - const std::string &_service, const std::string &_path, const std::string &_interface, const bool _objPathStartWithDigits) { - - if (isValid(_service, '.', - (_service.length() > 0 && _service[0] == ':'), - (_service.length() > 0 && _service[0] == ':'), - true) - && isValid(_path, '/', true, _objPathStartWithDigits) - && isValid(_interface, '.')) { - CommonAPI::Address address(_address); - DBusAddress dbusAddress(_service, _path, _interface); - - std::lock_guard<std::mutex> itsLock(mutex_); - auto fw = forwards_.find(address); - auto bw = backwards_.find(dbusAddress); - if (fw == forwards_.end() && bw == backwards_.end()) { - forwards_[address] = dbusAddress; - backwards_[dbusAddress] = address; - COMMONAPI_DEBUG( - "Added address mapping: ", address, " <--> ", dbusAddress); - if (!orgFreedesktopDBusPeerMapped_) { - orgFreedesktopDBusPeerMapped_ = (_interface == "org.freedesktop.DBus.Peer"); - if (orgFreedesktopDBusPeerMapped_) { - COMMONAPI_DEBUG("org.freedesktop.DBus.Peer mapped"); - } - } - } else if(bw != backwards_.end() && bw->second != address) { - COMMONAPI_ERROR("Trying to overwrite existing DBus address " - "which is already mapped to a CommonAPI address: ", - dbusAddress, " <--> ", _address); - } else if(fw != forwards_.end() && fw->second != dbusAddress) { - COMMONAPI_ERROR("Trying to overwrite existing CommonAPI address " - "which is already mapped to a DBus address: ", - _address, " <--> ", dbusAddress); - } - } + const std::string &_address, + const std::string &_service, const std::string &_path, const std::string &_interface, const bool _objPathStartWithDigits) { + + if (isValid(_service, '.', + (_service.length() > 0 && _service[0] == ':'), + (_service.length() > 0 && _service[0] == ':'), + true) + && isValid(_path, '/', true, _objPathStartWithDigits) + && isValid(_interface, '.')) { + CommonAPI::Address address(_address); + DBusAddress dbusAddress(_service, _path, _interface); + + std::lock_guard<std::mutex> itsLock(mutex_); + auto fw = forwards_.find(address); + auto bw = backwards_.find(dbusAddress); + if (fw == forwards_.end() && bw == backwards_.end()) { + forwards_[address] = dbusAddress; + backwards_[dbusAddress] = address; + COMMONAPI_DEBUG( + "Added address mapping: ", address, " <--> ", dbusAddress); + if (!orgFreedesktopDBusPeerMapped_) { + orgFreedesktopDBusPeerMapped_ = (_interface == "org.freedesktop.DBus.Peer"); + if (orgFreedesktopDBusPeerMapped_) { + COMMONAPI_DEBUG("org.freedesktop.DBus.Peer mapped"); + } + } + } else if(bw != backwards_.end() && bw->second != address) { + COMMONAPI_ERROR("Trying to overwrite existing DBus address " + "which is already mapped to a CommonAPI address: ", + dbusAddress, " <--> ", _address); + } else if(fw != forwards_.end() && fw->second != dbusAddress) { + COMMONAPI_ERROR("Trying to overwrite existing CommonAPI address " + "which is already mapped to a DBus address: ", + _address, " <--> ", dbusAddress); + } + } } bool DBusAddressTranslator::readConfiguration() { #define MAX_PATH_LEN 255 - std::string config; - char currentDirectory[MAX_PATH_LEN]; + std::string config; + char currentDirectory[MAX_PATH_LEN]; #ifdef WIN32 - if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { + if (GetCurrentDirectory(MAX_PATH_LEN, currentDirectory)) { #else - if (getcwd(currentDirectory, MAX_PATH_LEN)) { + if (getcwd(currentDirectory, MAX_PATH_LEN)) { #endif - config = currentDirectory; - config += "/"; - config += COMMONAPI_DBUS_DEFAULT_CONFIG_FILE; - - struct stat s; - if (stat(config.c_str(), &s) != 0) { - config = defaultConfig_; - } - } - - IniFileReader reader; - if (!reader.load(config)) - return false; - - for (auto itsMapping : reader.getSections()) { - if(itsMapping.first == "segments") { - std::map<std::string, std::string> mappings = itsMapping.second->getMappings(); - ConnectionId_t connectionId; - std::string busType; - for(auto const &it : mappings) { - connectionId = it.first; - busType = it.second; - if(busType == "SESSION") { - dbusTypes_.insert({ connectionId, DBusType_t::SESSION }); - } else if (busType == "SYSTEM") { - dbusTypes_.insert({ connectionId, DBusType_t::SYSTEM }); - } else { - COMMONAPI_FATAL("Invalid bus type specified in .ini file, " - "choose one of {SYSTEM, SESSION}"); - continue; - } - COMMONAPI_INFO("D-Bus bus type for connection: " + connectionId + - " is set to: " + busType + " via ini file"); - } - continue; - } - - CommonAPI::Address itsAddress(itsMapping.first); - - std::string service = itsMapping.second->getValue("service"); - std::string path = itsMapping.second->getValue("path"); - std::string interfaceName = itsMapping.second->getValue("interface"); - - insert(itsMapping.first, service, path, interfaceName); - } - - return true; + config = currentDirectory; + config += "/"; + config += COMMONAPI_DBUS_DEFAULT_CONFIG_FILE; + + struct stat s; + if (stat(config.c_str(), &s) != 0) { + config = defaultConfig_; + } + } + + IniFileReader reader; + if (!reader.load(config)) + return false; + + for (auto itsMapping : reader.getSections()) { + if(itsMapping.first == "segments") { + std::map<std::string, std::string> mappings = itsMapping.second->getMappings(); + ConnectionId_t connectionId; + std::string busType; + for(auto const &it : mappings) { + connectionId = it.first; + busType = it.second; + if(busType == "SESSION") { + dbusTypes_.insert({ connectionId, DBusType_t::SESSION }); + } else if (busType == "SYSTEM") { + dbusTypes_.insert({ connectionId, DBusType_t::SYSTEM }); + } else { + COMMONAPI_FATAL("Invalid bus type specified in .ini file, " + "choose one of {SYSTEM, SESSION}"); + continue; + } + COMMONAPI_INFO("D-Bus bus type for connection: " + connectionId + + " is set to: " + busType + " via ini file"); + } + continue; + } + + CommonAPI::Address itsAddress(itsMapping.first); + + std::string service = itsMapping.second->getValue("service"); + std::string path = itsMapping.second->getValue("path"); + std::string interfaceName = itsMapping.second->getValue("interface"); + + insert(itsMapping.first, service, path, interfaceName); + } + + return true; } bool DBusAddressTranslator::isValid( - const std::string &_name, const char _separator, - bool _ignoreFirst, bool _isAllowedToStartWithDigit, bool _isBusName) const { - // DBus addresses must contain at least one separator - std::size_t separatorPos = _name.find(_separator); - if (separatorPos == std::string::npos) { - COMMONAPI_ERROR( - "Invalid name \'", _name, - "\'. Contains no \'", _separator, "\'"); - return false; - } - - bool isInitial(true); - std::size_t start(0); - - if (_ignoreFirst) { - start = 1; - if (separatorPos == 0) { - // accept "root-only" i.e. '/' object path - if (1 == _name.length()) { - return true; - } - separatorPos = _name.find(_separator, separatorPos+1); - } - } - - while (start != std::string::npos) { - // DBus names parts must not be empty - std::string part; - - if (isInitial) { - isInitial = false; - } else { - start++; - } - - if (separatorPos == std::string::npos) { - part = _name.substr(start); - } else { - part = _name.substr(start, separatorPos-start); - } - - if ("" == part) { - COMMONAPI_ERROR( - "Invalid interface name \'", _name, - "\'. Must not contain empty parts."); - return false; - } - - // DBus name parts must not start with a digit (not valid for unique names) - if (!_isAllowedToStartWithDigit) { - if (part[0] >= '0' && part[0] <= '9') { - COMMONAPI_ERROR( - "Invalid interface name \'", _name, - "\'. First character must not be a digit."); - return false; - } - } - - // DBus name parts consist of the ASCII characters [0-9][A-Z][a-z]_, - for (auto c : part) { - // bus names may additionally contain [-] - if (_isBusName && c == '-') - continue; - - if (c < '0' || - (c > '9' && c < 'A') || - (c > 'Z' && c < '_') || - (c > '_' && c < 'a') || - c > 'z') { - COMMONAPI_ERROR( - "Invalid interface name \'", _name, - "\'. Contains illegal character \'", c, - "\'. Only \'[0-9][A-Z][a-z]_\' are allowed."); - return false; - } - } - - start = separatorPos; - separatorPos = _name.find(_separator, separatorPos+1); - } - - // DBus names must not exceed the maximum length - if (_name.length() > DBUS_MAXIMUM_NAME_LENGTH) { - COMMONAPI_ERROR( - "Invalid interface name \'", _name, - "\'. Size exceeds maximum size."); - return false; - } - - return true; + const std::string &_name, const char _separator, + bool _ignoreFirst, bool _isAllowedToStartWithDigit, bool _isBusName) const { + (void)_isAllowedToStartWithDigit; + // DBus addresses must contain at least one separator + std::size_t separatorPos = _name.find(_separator); + if (separatorPos == std::string::npos) { + COMMONAPI_ERROR( + "Invalid name \'", _name, + "\'. Contains no \'", _separator, "\'"); + return false; + } + + bool isInitial(true); + std::size_t start(0); + + if (_ignoreFirst) { + start = 1; + if (separatorPos == 0) { + // accept "root-only" i.e. '/' object path + if (1 == _name.length()) { + return true; + } + separatorPos = _name.find(_separator, separatorPos+1); + } + } + + while (start != std::string::npos) { + // DBus names parts must not be empty + std::string part; + + if (isInitial) { + isInitial = false; + } else { + start++; + } + + if (separatorPos == std::string::npos) { + part = _name.substr(start); + } else { + part = _name.substr(start, separatorPos-start); + } + + if ("" == part) { + COMMONAPI_ERROR( + "Invalid interface name \'", _name, + "\'. Must not contain empty parts."); + return false; + } + + // DBus name parts consist of the ASCII characters [0-9][A-Z][a-z]_, + for (auto c : part) { + // bus names may additionally contain [-] + if (_isBusName && c == '-') + continue; + + if (c < '0' || + (c > '9' && c < 'A') || + (c > 'Z' && c < '_') || + (c > '_' && c < 'a') || + c > 'z') { + COMMONAPI_ERROR( + "Invalid interface name \'", _name, + "\'. Contains illegal character \'", c, + "\'. Only \'[0-9][A-Z][a-z]_\' are allowed."); + return false; + } + } + + start = separatorPos; + separatorPos = _name.find(_separator, separatorPos+1); + } + + // DBus names must not exceed the maximum length + if (_name.length() > DBUS_MAXIMUM_NAME_LENGTH) { + COMMONAPI_ERROR( + "Invalid interface name \'", _name, + "\'. Size exceeds maximum size."); + return false; + } + + return true; } DBusType_t DBusAddressTranslator::getDBusBusType(const ConnectionId_t &_connectionId) const { - auto itsDbusTypesIterator = dbusTypes_.find(_connectionId); - if(itsDbusTypesIterator != dbusTypes_.end()) { - return itsDbusTypesIterator->second; - } else { - return DBusType_t::SESSION; - } + auto itsDbusTypesIterator = dbusTypes_.find(_connectionId); + if(itsDbusTypesIterator != dbusTypes_.end()) { + return itsDbusTypesIterator->second; + } else { + return DBusType_t::SESSION; + } } bool DBusAddressTranslator::isOrgFreedesktopDBusPeerMapped() const { - return orgFreedesktopDBusPeerMapped_; + return orgFreedesktopDBusPeerMapped_; } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp index e3fb4a4..c5ab406 100644 --- a/src/CommonAPI/DBus/DBusConnection.cpp +++ b/src/CommonAPI/DBus/DBusConnection.cpp @@ -13,6 +13,7 @@ #include <CommonAPI/Logger.hpp> #include <CommonAPI/DBus/DBusConnection.hpp> #include <CommonAPI/DBus/DBusInputStream.hpp> +#include <CommonAPI/DBus/DBusMainLoop.hpp> #include <CommonAPI/DBus/DBusProxy.hpp> #include <CommonAPI/DBus/DBusAddressTranslator.hpp> @@ -24,16 +25,21 @@ DBusConnectionStatusEvent::DBusConnectionStatusEvent(DBusConnection* dbusConnect dbusConnection_(dbusConnection) { } -void DBusConnectionStatusEvent::onListenerAdded(const Listener& listener, const Subscription subscription) { +void DBusConnectionStatusEvent::onListenerAdded(const Listener &_listener, const Subscription _subscription) { + (void)_subscription; if (dbusConnection_->isConnected()) - listener(AvailabilityStatus::AVAILABLE); + _listener(AvailabilityStatus::AVAILABLE); } const DBusObjectPathVTable* DBusConnection::getDBusObjectPathVTable() { static const DBusObjectPathVTable libdbusObjectPathVTable = { NULL, // no need to handle unregister callbacks - &DBusConnection::onLibdbusObjectPathMessageThunk + &DBusConnection::onLibdbusObjectPathMessageThunk, + NULL, // dbus_internal_pad1 reserved for future expansion + NULL, // dbus_internal_pad2 reserved for future expansion + NULL, // dbus_internal_pad3 reserved for future expansion + NULL // dbus_internal_pad4 reserved for future expansion }; return &libdbusObjectPathVTable; } @@ -44,30 +50,7 @@ const DBusObjectPathVTable* DBusConnection::getDBusObjectPathVTable() { const int32_t ownUseCount = 2; void DBusConnection::dispatch() { - std::shared_ptr<DBusConnection> selfReference = this->shared_from_this(); - while (!stopDispatching_ && readWriteDispatch(10) && selfReference.use_count() > ownUseCount) { - if (pauseDispatching_) { - dispatchSuspendLock_.lock(); - dispatchSuspendLock_.unlock(); - } - } -} - -bool DBusConnection::readWriteDispatch(int _timeout) { - if(isConnected()) { - return 0 != dbus_connection_read_write_dispatch(connection_, _timeout); - } - return false; -} - -void DBusConnection::suspendDispatching() const { - dispatchSuspendLock_.lock(); - pauseDispatching_ = true; -} - -void DBusConnection::resumeDispatching() const { - pauseDispatching_ = false; - dispatchSuspendLock_.unlock(); + loop_->run(); } DBusConnection::DBusConnection(DBusType_t busType) : @@ -116,8 +99,10 @@ bool DBusConnection::isObjectPathMessageHandlerSet() { DBusConnection::~DBusConnection() { if (auto lockedContext = mainLoopContext_.lock()) { - dbus_connection_set_watch_functions(connection_, NULL, NULL, NULL, NULL, NULL); - dbus_connection_set_timeout_functions(connection_, NULL, NULL, NULL, NULL, NULL); + if (isConnected()) { + dbus_connection_set_watch_functions(connection_, NULL, NULL, NULL, NULL, NULL); + dbus_connection_set_timeout_functions(connection_, NULL, NULL, NULL, NULL, NULL); + } lockedContext->deregisterDispatchSource(dispatchSource_); delete watchContext_; @@ -126,25 +111,57 @@ DBusConnection::~DBusConnection() { // ensure, the registry survives until disconnecting is done... //std::shared_ptr<DBusServiceRegistry> itsRegistry = DBusServiceRegistry::get(shared_from_this()); - disconnect(); + disconnect(); //Assert that the enforcerThread_ is in a position to finish itself correctly even after destruction //of the DBusConnection. Also assert all resources are cleaned up. auto it = timeoutMap_.begin(); while (it != timeoutMap_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); DBusPendingCall* libdbusPendingCall = it->first; - if (!dbus_pending_call_get_completed(libdbusPendingCall)) { + asyncHandler->lock(); + bool executionStarted = asyncHandler->getExecutionStarted(); + bool executionFinished = asyncHandler->getExecutionFinished(); + if (executionStarted && !executionFinished) { + asyncHandler->setHasToBeDeleted(); + it = timeoutMap_.erase(it); + asyncHandler->unlock(); + continue; + } + if (!executionStarted && !executionFinished && !dbus_pending_call_get_completed(libdbusPendingCall)) { dbus_pending_call_cancel(libdbusPendingCall); - DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); + } + asyncHandler->unlock(); + + if (!executionStarted && !executionFinished) { DBusMessage& dbusMessageCall = std::get<2>(it->second); asyncHandler->onDBusMessageReply(CallStatus::REMOTE_ERROR, dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT)); - delete asyncHandler; + dbus_pending_call_unref(libdbusPendingCall); } it = timeoutMap_.erase(it); - dbus_pending_call_unref(libdbusPendingCall); + delete asyncHandler; + } + + auto itTimeoutInf = timeoutInfiniteAsyncHandlers_.begin(); + while (itTimeoutInf != timeoutInfiniteAsyncHandlers_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = (*itTimeoutInf); + + asyncHandler->lock(); + bool executionStarted = asyncHandler->getExecutionStarted(); + bool executionFinished = asyncHandler->getExecutionFinished(); + if (executionStarted && !executionFinished) { + asyncHandler->setHasToBeDeleted(); + itTimeoutInf = timeoutInfiniteAsyncHandlers_.erase(itTimeoutInf); + asyncHandler->unlock(); + continue; + } + asyncHandler->unlock(); + + itTimeoutInf = timeoutInfiniteAsyncHandlers_.erase(itTimeoutInf); + delete asyncHandler; } } @@ -219,24 +236,37 @@ dbus_bool_t DBusConnection::onAddWatch(::DBusWatch* libdbusWatch, void* data) { void DBusConnection::onRemoveWatch(::DBusWatch* libdbusWatch, void* data) { assert(static_cast<WatchContext*>(data)); + (void)data; DBusWatch* dbusWatch = static_cast<DBusWatch*>(dbus_watch_get_data(libdbusWatch)); - if(dbusWatch->isReadyToBeWatched()) { - dbusWatch->stopWatching(); + if (dbusWatch != NULL) { + if(dbusWatch->isReadyToBeWatched()) { + dbusWatch->stopWatching(); + } + dbus_watch_set_data(libdbusWatch, NULL, NULL); } - dbus_watch_set_data(libdbusWatch, NULL, NULL); - delete dbusWatch; + // DBusWatch will be deleted in Mainloop } void DBusConnection::onToggleWatch(::DBusWatch* libdbusWatch, void* data) { - assert(static_cast<WatchContext*>(data)); + WatchContext* watchContext = static_cast<WatchContext*>(data); + assert(watchContext); DBusWatch* dbusWatch = static_cast<DBusWatch*>(dbus_watch_get_data(libdbusWatch)); - if (dbusWatch->isReadyToBeWatched()) { - dbusWatch->startWatching(); + if (dbusWatch == NULL) { + DBusWatch* dbusWatch = new DBusWatch(libdbusWatch, watchContext->mainLoopContext_); + dbusWatch->addDependentDispatchSource(watchContext->dispatchSource_); + dbus_watch_set_data(libdbusWatch, dbusWatch, NULL); + + if (dbusWatch->isReadyToBeWatched()) { + dbusWatch->startWatching(); + } } else { - dbusWatch->stopWatching(); + if (!dbusWatch->isReadyToBeWatched()) { + dbusWatch->stopWatching(); + dbus_watch_set_data(libdbusWatch, NULL, NULL); + } } } @@ -257,15 +287,19 @@ dbus_bool_t DBusConnection::onAddTimeout(::DBusTimeout* libdbusTimeout, void* da void DBusConnection::onRemoveTimeout(::DBusTimeout* libdbusTimeout, void* data) { assert(static_cast<std::weak_ptr<MainLoopContext>*>(data)); + (void)data; DBusTimeout* dbusTimeout = static_cast<DBusTimeout*>(dbus_timeout_get_data(libdbusTimeout)); - dbusTimeout->stopMonitoring(); + if (dbusTimeout) { + dbusTimeout->stopMonitoring(); + } dbus_timeout_set_data(libdbusTimeout, NULL, NULL); - delete dbusTimeout; + // DBusTimeout will be deleted in Mainloop } void DBusConnection::onToggleTimeout(::DBusTimeout* dbustimeout, void* data) { assert(static_cast<std::weak_ptr<MainLoopContext>*>(data)); + (void)data; DBusTimeout* timeout = static_cast<DBusTimeout*>(dbus_timeout_get_data(dbustimeout)); if (timeout->isReadyToBeMonitored()) { @@ -309,16 +343,19 @@ bool DBusConnection::connect(DBusError &dbusError, bool startDispatchThread) { initLibdbusSignalFilterAfterConnect(); - stopDispatching_ = !startDispatchThread; - if (startDispatchThread) { - dispatchThread_ = new std::thread(std::bind(&DBusConnection::dispatch, this->shared_from_this())); - } - enforcerThread_ = std::make_shared<std::thread>( - std::bind(&DBusConnection::enforceAsynchronousTimeouts, shared_from_this())); + std::bind(&DBusConnection::enforceAsynchronousTimeouts, shared_from_this())); dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::AVAILABLE); + stopDispatching_ = !startDispatchThread; + if (startDispatchThread) { + std::shared_ptr<MainLoopContext> itsContext = std::make_shared<MainLoopContext>(); + loop_ = std::make_shared<DBusMainLoop>(itsContext); + attachMainLoopContext(itsContext); + dispatchThread_ = new std::thread(std::bind(&DBusConnection::dispatch, shared_from_this())); + } + return true; } @@ -339,6 +376,7 @@ void DBusConnection::disconnect() { dbus_connection_close(connection_); if(dispatchThread_) { + loop_->stop(); //It is possible for the disconnect to be called from within a callback, i.e. from within the dispatch //thread. Self-join is prevented this way. if (dispatchThread_->joinable() && std::this_thread::get_id() != dispatchThread_->get_id()) { @@ -357,6 +395,10 @@ void DBusConnection::disconnect() { } enforcerThreadCancelled_ = false; + // remote mainloop watchers + dbus_connection_set_watch_functions(connection_, NULL, NULL, NULL, NULL, NULL); + dbus_connection_set_timeout_functions(connection_, NULL, NULL, NULL, NULL, NULL); + dbus_connection_unref(connection_); connection_ = nullptr; } @@ -389,32 +431,30 @@ bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) std::lock_guard<std::mutex> dbusConnectionLock(connectionGuard_); auto conIter = connectionNameCount_.find(serviceName); if (conIter == connectionNameCount_.end()) { - suspendDispatching(); - const int libdbusStatus = dbus_bus_request_name(connection_, serviceName.c_str(), DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbusError.libdbusError_); - resumeDispatching(); - isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); if (isServiceNameAcquired) { connectionNameCount_.insert( { serviceName, (uint16_t)1 } ); } else { - #ifdef _MSC_VER // Visual Studio - COMMONAPI_ERROR(std::string(__FUNCTION__) + - ": Name: " + dbusError.getName() + - " Message: " + dbusError.getMessage()) - #else - COMMONAPI_ERROR(std::string(__PRETTY_FUNCTION__) + - ": Name: " + dbusError.getName() + - " Message: " + dbusError.getMessage()) - #endif + if (libdbusStatus == -1) { + #ifdef _MSC_VER // Visual Studio + COMMONAPI_ERROR(std::string(__FUNCTION__) + + ": Name: " + dbusError.getName() + + " Message: " + dbusError.getMessage()) + #else + COMMONAPI_ERROR(std::string(__PRETTY_FUNCTION__) + + ": Name: " + dbusError.getName() + + " Message: " + dbusError.getMessage()) + #endif + } } } else { - conIter->second = conIter->second + 1; + conIter->second++; isServiceNameAcquired = true; } @@ -428,17 +468,15 @@ bool DBusConnection::releaseServiceName(const std::string& serviceName) const { auto conIter = connectionNameCount_.find(serviceName); if (conIter != connectionNameCount_.end()) { if (conIter->second == 1) { - suspendDispatching(); const int libdbusStatus = dbus_bus_release_name(connection_, serviceName.c_str(), &dbusError.libdbusError_); - resumeDispatching(); isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED); if (isServiceNameReleased) { connectionNameCount_.erase(conIter); } } else { - conIter->second = conIter->second - 1; + conIter->second--; isServiceNameReleased = true; } } @@ -455,19 +493,19 @@ bool DBusConnection::sendDBusMessage(const DBusMessage &_message) const { } DBusMessage DBusConnection::convertToDBusMessage(::DBusPendingCall* _libdbusPendingCall, - CallStatus& _callStatus) { - assert(_libdbusPendingCall); + CallStatus& _callStatus) { + assert(_libdbusPendingCall); - ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply(_libdbusPendingCall); - const bool increaseLibdbusMessageReferenceCount = false; - DBusMessage dbusMessage(libdbusMessage, increaseLibdbusMessageReferenceCount); - _callStatus = CallStatus::SUCCESS; + ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply(_libdbusPendingCall); + const bool increaseLibdbusMessageReferenceCount = false; + DBusMessage dbusMessage(libdbusMessage, increaseLibdbusMessageReferenceCount); + _callStatus = CallStatus::SUCCESS; - if (!dbusMessage.isMethodReturnType()) { - _callStatus = CallStatus::REMOTE_ERROR; - } + if (!dbusMessage.isMethodReturnType()) { + _callStatus = CallStatus::REMOTE_ERROR; + } - return dbusMessage; + return dbusMessage; } void DBusConnection::onLibdbusPendingCallNotifyThunk(::DBusPendingCall* _libdbusPendingCall, void *_userData) { @@ -476,19 +514,36 @@ void DBusConnection::onLibdbusPendingCallNotifyThunk(::DBusPendingCall* _libdbus auto dbusMessageReplyAsyncHandler = reinterpret_cast<DBusMessageReplyAsyncHandler*>(_userData); - DBusMessage dbusMessage; - CallStatus callStatus; - dbusMessage = DBusConnection::convertToDBusMessage(_libdbusPendingCall, callStatus); + dbusMessageReplyAsyncHandler->lock(); + bool processAsyncHandler = !dbusMessageReplyAsyncHandler->getTimeoutOccurred(); + dbusMessageReplyAsyncHandler->setExecutionStarted(); + dbusMessageReplyAsyncHandler->unlock(); - dbusMessageReplyAsyncHandler->onDBusMessageReply(callStatus, dbusMessage); + if (processAsyncHandler) { + DBusMessage dbusMessage; + CallStatus callStatus; + dbusMessage = DBusConnection::convertToDBusMessage(_libdbusPendingCall, callStatus); + dbusMessageReplyAsyncHandler->onDBusMessageReply(callStatus, dbusMessage); + } + + dbusMessageReplyAsyncHandler->lock(); // libdbus calls the cleanup method below dbus_pending_call_unref(_libdbusPendingCall); + + dbusMessageReplyAsyncHandler->setExecutionFinished(); + if (dbusMessageReplyAsyncHandler->hasToBeDeleted()) { + dbusMessageReplyAsyncHandler->unlock(); + delete dbusMessageReplyAsyncHandler; + return; + } + dbusMessageReplyAsyncHandler->unlock(); } -void DBusConnection::onLibdbusDataCleanup(void* userData) { - auto dbusMessageReplyAsyncHandler = reinterpret_cast<DBusMessageReplyAsyncHandler*>(userData); - delete dbusMessageReplyAsyncHandler; +void DBusConnection::onLibdbusDataCleanup(void *_data) { + // Dummy method -> deleting of userData is not executed in this method. Deleting is + // executed by handling of the timeouts. + (void)_data; } //Would not be needed if libdbus would actually handle its timeouts for pending calls. @@ -523,38 +578,103 @@ void DBusConnection::enforceAsynchronousTimeouts() const { while (it != timeoutMap_.end()) { std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now(); + DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); + DBusPendingCall* libdbusPendingCall = it->first; + if (now > std::get<0>(it->second)) { - DBusPendingCall* libdbusPendingCall = it->first; - - if (!dbus_pending_call_get_completed(libdbusPendingCall)) { - dbus_pending_call_cancel(libdbusPendingCall); - DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); - DBusMessage& dbusMessageCall = std::get<2>(it->second); - - if (mainLoopContext_.lock()) { - mainloopTimeouts_.push_back(std::make_tuple(asyncHandler, - dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT), - CallStatus::REMOTE_ERROR, - nullptr)); - mainLoopContext_.lock()->wakeup(); + + asyncHandler->lock(); + bool executionStarted = asyncHandler->getExecutionStarted(); + bool executionFinished = asyncHandler->getExecutionFinished(); + if (!executionStarted && !executionFinished) { + asyncHandler->setTimeoutOccurred(); + if (!dbus_pending_call_get_completed(libdbusPendingCall)) { + dbus_pending_call_cancel(libdbusPendingCall); + } + } + asyncHandler->unlock(); + + if (executionStarted && !executionFinished) { + // execution of asyncHandler is still running + // ==> add 100 ms for next timeout check + std::get<0>(it->second) = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(100); + } else { + if (!executionFinished) { + // execution of asyncHandler was not finished (and not started) + // => add asyncHandler to mainloopTimeouts list + DBusMessage& dbusMessageCall = std::get<2>(it->second); + + assert(mainLoopContext_.lock()); + { + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); + mainloopTimeouts_.push_back(std::make_tuple(asyncHandler, + dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT), + CallStatus::REMOTE_ERROR, + nullptr)); + } + mainLoopContext_.lock()->wakeup(); + it = timeoutMap_.erase(it); + + //This unref MIGHT cause the destruction of the last callback object that references the DBusConnection. + //So after this unref has been called, it has to be ensured that continuation of the loop is an option. + dbus_pending_call_unref(libdbusPendingCall); } else { - enforceTimeoutMutex_.unlock(); // unlock before making callbacks to application to avoid deadlocks - asyncHandler->onDBusMessageReply(CallStatus::REMOTE_ERROR, dbusMessageCall.createMethodError(DBUS_ERROR_TIMEOUT)); - enforceTimeoutMutex_.lock(); - delete asyncHandler; + // execution of asyncHandler was finished + it = timeoutMap_.erase(it); + delete asyncHandler; } } - it = timeoutMap_.erase(it); + } else { + asyncHandler->lock(); + bool executionFinished = asyncHandler->getExecutionFinished(); + asyncHandler->unlock(); + if (executionFinished) { + // execution of asyncHandler was finished but timeout is not expired + it = timeoutMap_.erase(it); + delete asyncHandler; + } else { + ++it; + } + } + } + enforceTimeoutMutex_.unlock(); + } else { + std::lock_guard<std::mutex> itsLock(enforceTimeoutMutex_); - //This unref MIGHT cause the destruction of the last callback object that references the DBusConnection. - //So after this unref has been called, it has to be ensured that continuation of the loop is an option. - dbus_pending_call_unref(libdbusPendingCall); + auto it = timeoutMap_.begin(); + while (it != timeoutMap_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = std::get<1>(it->second); + asyncHandler->lock(); + bool executionFinished = asyncHandler->getExecutionFinished(); + asyncHandler->unlock(); + if (executionFinished) { + // execution of asyncHandler was finished but timeout is not expired + it = timeoutMap_.erase(it); + delete asyncHandler; } else { ++it; } } - enforceTimeoutMutex_.unlock(); } + + { + std::lock_guard<std::mutex> itsLock(timeoutInfiniteAsyncHandlersMutex_); + // check for asyncHandler with infinite timeout whose execution is finished + auto it = timeoutInfiniteAsyncHandlers_.begin(); + while (it != timeoutInfiniteAsyncHandlers_.end()) { + DBusMessageReplyAsyncHandler* asyncHandler = (*it); + asyncHandler->lock(); + bool executionFinished = asyncHandler->getExecutionFinished(); + asyncHandler->unlock(); + if ( executionFinished ) { + it = timeoutInfiniteAsyncHandlers_.erase(it); + delete asyncHandler; + } else { + it++; + } + } + } + } } @@ -569,39 +689,45 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( DBusPendingCall* libdbusPendingCall; dbus_bool_t libdbusSuccess; - suspendDispatching(); + DBusMessageReplyAsyncHandler* replyAsyncHandler = dbusMessageReplyAsyncHandler.release(); + + std::future<CallStatus> callStatusFuture = replyAsyncHandler->getFuture(); + libdbusSuccess = dbus_connection_send_with_reply_set_notify(connection_, - dbusMessage.message_, - &libdbusPendingCall, - onLibdbusPendingCallNotifyThunk, - dbusMessageReplyAsyncHandler.get(), - onLibdbusDataCleanup, - _info->timeout_); + dbusMessage.message_, + &libdbusPendingCall, + onLibdbusPendingCallNotifyThunk, + replyAsyncHandler, + onLibdbusDataCleanup, + _info->timeout_); if (_info->sender_ != 0) { COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); } if (!libdbusSuccess || !libdbusPendingCall) { - #ifdef _MSC_VER // Visual Studio + #ifdef _MSC_VER // Visual Studio COMMONAPI_ERROR(std::string(__FUNCTION__) + ": (!libdbusSuccess || !libdbusPendingCall) == true") #else COMMONAPI_ERROR(std::string(__PRETTY_FUNCTION__) + ": (!libdbusSuccess || !libdbusPendingCall) == true") #endif - if (libdbusPendingCall) { - dbus_pending_call_unref(libdbusPendingCall); - } - dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::CONNECTION_FAILED, dbusMessage.createMethodError(DBUS_ERROR_DISCONNECTED)); - resumeDispatching(); - return dbusMessageReplyAsyncHandler->getFuture(); + if (libdbusPendingCall) { + dbus_pending_call_unref(libdbusPendingCall); + } + { + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); + mainloopTimeouts_.push_back(std::make_tuple(replyAsyncHandler, + dbusMessage.createMethodError(DBUS_ERROR_DISCONNECTED), + CallStatus::CONNECTION_FAILED, + nullptr)); + } + mainLoopContext_.lock()->wakeup(); + return callStatusFuture; } - DBusMessageReplyAsyncHandler* replyAsyncHandler = dbusMessageReplyAsyncHandler.release(); - if (_info->timeout_ != DBUS_TIMEOUT_INFINITE) { - dbus_pending_call_ref(libdbusPendingCall); auto timeoutPoint = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(_info->timeout_); std::tuple< std::chrono::time_point<std::chrono::high_resolution_clock>, @@ -616,14 +742,16 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync( timeoutMap_.insert( { libdbusPendingCall, toInsert } ); enforceTimeoutMutex_.unlock(); + enforcerThreadMutex_.lock(); enforceTimeoutCondition_.notify_all(); + enforcerThreadMutex_.unlock(); + } else { + // add asyncHandler with infinite timeout to corresponding list + std::lock_guard<std::mutex> itsLock(timeoutInfiniteAsyncHandlersMutex_); + timeoutInfiniteAsyncHandlers_.insert(replyAsyncHandler); } - std::future<CallStatus> result = replyAsyncHandler->getFuture(); - - resumeDispatching(); - - return result; + return callStatusFuture; } DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage, @@ -633,8 +761,6 @@ DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& assert(!dbusError); assert(isConnected()); - suspendDispatching(); - ::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(connection_, dbusMessage.message_, _info->timeout_, @@ -644,8 +770,6 @@ DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& COMMONAPI_DEBUG("Message sent: SenderID: ", _info->sender_, " - Serial number: ", dbusMessage.getSerial()); } - resumeDispatching(); - if (dbusError) { return DBusMessage(); } @@ -656,19 +780,23 @@ DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& bool DBusConnection::singleDispatch() { - for (auto t : mainloopTimeouts_) { - std::get<0>(t)->onDBusMessageReply(std::get<2>(t), std::get<1>(t)); - if (std::get<3>(t) != nullptr) { - dbus_pending_call_unref(std::get<3>(t)); - } - delete std::get<0>(t); + { + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); + for (auto t : mainloopTimeouts_) { + std::get<0>(t)->onDBusMessageReply(std::get<2>(t), std::get<1>(t)); + if (std::get<3>(t) != nullptr) { + dbus_pending_call_unref(std::get<3>(t)); + } + delete std::get<0>(t); + } + mainloopTimeouts_.clear(); } - mainloopTimeouts_.clear(); return (dbus_connection_dispatch(connection_) == DBUS_DISPATCH_DATA_REMAINS); } bool DBusConnection::isDispatchReady() { + std::lock_guard<std::mutex> itsLock(mainloopTimeoutsMutex_); return (dbus_connection_get_dispatch_status(connection_) == DBUS_DISPATCH_DATA_REMAINS || !mainloopTimeouts_.empty()); } @@ -778,11 +906,11 @@ bool DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken &dbu } if (lastHandlerRemoved) { - dbusSignalHandlerTable_.erase(signalEntry); - removeLibdbusSignalMatchRule(std::get<0>(dbusSignalHandlerToken), - std::get<1>(dbusSignalHandlerToken), - std::get<2>(dbusSignalHandlerToken)); - } + dbusSignalHandlerTable_.erase(signalEntry); + removeLibdbusSignalMatchRule(std::get<0>(dbusSignalHandlerToken), + std::get<1>(dbusSignalHandlerToken), + std::get<2>(dbusSignalHandlerToken)); + } return lastHandlerRemoved; } @@ -810,6 +938,7 @@ bool DBusConnection::addObjectManagerSignalMemberHandler(const std::string& dbus if (isConnected()) { const bool isRemoveSignalMatchRuleSuccessful = removeObjectManagerSignalMatchRule(dbusBusName); assert(isRemoveSignalMatchRuleSuccessful); + (void)isRemoveSignalMatchRuleSuccessful; } return false; } @@ -891,8 +1020,6 @@ bool DBusConnection::removeObjectManagerSignalMatchRule(const std::string& dbusB bool DBusConnection::addLibdbusSignalMatchRule(const std::string& dbusMatchRule) { bool libdbusSuccess = true; - suspendDispatching(); - // add the libdbus message signal filter if (!libdbusSignalMatchRulesCount_) { libdbusSuccess = 0 != dbus_connection_add_filter( @@ -914,8 +1041,6 @@ bool DBusConnection::addLibdbusSignalMatchRule(const std::string& dbusMatchRule) libdbusSignalMatchRulesCount_++; } - resumeDispatching(); - return libdbusSuccess; } @@ -929,8 +1054,6 @@ bool DBusConnection::removeLibdbusSignalMatchRule(const std::string& dbusMatchRu if(libdbusSignalMatchRulesCount_ == 0) return true; - suspendDispatching(); - dbus_bus_remove_match(connection_, dbusMatchRule.c_str(), NULL); libdbusSignalMatchRulesCount_--; @@ -938,8 +1061,6 @@ bool DBusConnection::removeLibdbusSignalMatchRule(const std::string& dbusMatchRu dbus_connection_remove_filter(connection_, &onLibdbusSignalFilterThunk, this); } - resumeDispatching(); - return true; } @@ -967,6 +1088,8 @@ void DBusConnection::registerObjectPath(const std::string& objectPath) { &dbusError.libdbusError_); assert(libdbusSuccess); assert(!dbusError); + (void)libdbusSuccess; + (void)dbusError; } } @@ -978,6 +1101,7 @@ void DBusConnection::unregisterObjectPath(const std::string& objectPath) { const bool foundRegisteredObjectPathHandler = handlerIterator != libdbusRegisteredObjectPaths_.end(); assert(foundRegisteredObjectPathHandler); + (void)foundRegisteredObjectPathHandler; uint32_t& referenceCount = handlerIterator->second; if (referenceCount > 1) { @@ -991,6 +1115,7 @@ void DBusConnection::unregisterObjectPath(const std::string& objectPath) { dbus_bool_t libdbusSuccess = dbus_connection_unregister_object_path(connection_, objectPath.c_str()); assert(libdbusSuccess); + (void)libdbusSuccess; } } @@ -1024,10 +1149,10 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath, DBusSignalMatchRulesMap::value_type(dbusSignalMatchRuleTuple, DBusSignalMatchRuleMapping(1, matchRuleString))); assert(success.second); + (void)success; if (isConnected()) { bool libdbusSuccess = true; - suspendDispatching(); // add the libdbus message signal filter if (isFirstMatchRule) { @@ -1046,13 +1171,12 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath, DBusError dbusError; dbus_bus_add_match(connection_, matchRuleString.c_str(), &dbusError.libdbusError_); assert(!dbusError); + (void)dbusError; } if (libdbusSuccess) { libdbusSignalMatchRulesCount_++; } - - resumeDispatching(); } } @@ -1065,6 +1189,7 @@ void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath, const bool matchRuleFound = matchRuleIterator != dbusSignalMatchRulesMap_.end(); assert(matchRuleFound); + (void)matchRuleFound; uint32_t& matchRuleReferenceCount = matchRuleIterator->second.first; if (matchRuleReferenceCount > 1) { @@ -1076,6 +1201,7 @@ void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath, const std::string& matchRuleString = matchRuleIterator->second.second; const bool libdbusSuccess = removeLibdbusSignalMatchRule(matchRuleString); assert(libdbusSuccess); + (void)libdbusSuccess; } dbusSignalMatchRulesMap_.erase(matchRuleIterator); @@ -1105,6 +1231,8 @@ void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() { this, &dbusError.libdbusError_); assert(libdbusSuccess); + (void)libdbusSuccess; + assert(!dbusError); } } @@ -1118,6 +1246,7 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() { const std::string& dbusMatchRuleString = dbusSignalMatchRuleMapping.second; const bool libdbusSuccess = addLibdbusSignalMatchRule(dbusMatchRuleString); assert(libdbusSuccess); + (void)libdbusSuccess; } // object manager match rules (see DBusServiceRegistry) @@ -1125,11 +1254,13 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() { const std::string& dbusBusName = dbusObjectManagerSignalMatchRuleIterator.first; const bool libdbusSuccess = addObjectManagerSignalMatchRule(dbusBusName); assert(libdbusSuccess); + (void)libdbusSuccess; } } ::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) { assert(libdbusMessage); + (void)libdbusMessage; // handle only method call messages if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_METHOD_CALL) { @@ -1167,6 +1298,8 @@ void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable typename DBusSignalHandlersTable::iterator>& equalRange, const CommonAPI::DBus::DBusMessage &dbusMessage, ::DBusHandlerResult &dbusHandlerResult) { + (void)dbusSignalHandlerstable; + if (equalRange.first != equalRange.second) { dbusHandlerResult = DBUS_HANDLER_RESULT_HANDLED; } @@ -1233,6 +1366,7 @@ void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable assert(_dbusConnection); assert(libdbusMessage); assert(userData); + (void)_dbusConnection; DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData); assert(dbusConnection->connection_ == _dbusConnection); @@ -1245,6 +1379,7 @@ void notifyDBusOMSignalHandlers(DBusSignalHandlersTable& dbusSignalHandlerstable assert(_dbusConnection); assert(libdbusMessage); assert(userData); + (void)_dbusConnection; DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData); assert(dbusConnection->connection_ == _dbusConnection); diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/src/CommonAPI/DBus/DBusDaemonProxy.cpp index fe87335..ee434b1 100644 --- a/src/CommonAPI/DBus/DBusDaemonProxy.cpp +++ b/src/CommonAPI/DBus/DBusDaemonProxy.cpp @@ -16,13 +16,16 @@ StaticInterfaceVersionAttribute::StaticInterfaceVersionAttribute(const uint32_t& } void StaticInterfaceVersionAttribute::getValue(CallStatus &_status, Version &_version, - const CommonAPI::CallInfo *_info) const { + const CommonAPI::CallInfo *_info) const { + (void)_info; _version = version_; _status = CallStatus::SUCCESS; } std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(AttributeAsyncCallback attributeAsyncCallback, - const CommonAPI::CallInfo *_info) { + const CommonAPI::CallInfo *_info) { + (void)_info; + attributeAsyncCallback(CallStatus::SUCCESS, version_); std::promise<CallStatus> versionPromise; @@ -41,8 +44,8 @@ static CommonAPI::CallInfo daemonProxyInfo(30000); DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection): DBusProxyBase(dbusProxyAddress, dbusConnection), nameOwnerChangedEvent_(*this, - "NameOwnerChanged", "sss", - std::tuple<std::string, std::string, std::string>()), + "NameOwnerChanged", "sss", + std::tuple<std::string, std::string, std::string>()), interfaceVersionAttribute_(1, 0) { } @@ -74,7 +77,7 @@ void DBusDaemonProxy::listNames(CommonAPI::CallStatus& callStatus, std::vector<s DBusError dbusError; DBusMessage dbusMessageReply - = getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError, &daemonProxyInfo); + = getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError, &daemonProxyInfo); if (dbusError || !dbusMessageReply.isMethodReturnType()) { callStatus = CallStatus::REMOTE_ERROR; @@ -114,7 +117,7 @@ void DBusDaemonProxy::nameHasOwner(const std::string& busName, CommonAPI::CallSt DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock( dbusMethodCall, dbusError, - &daemonProxyInfo); + &daemonProxyInfo); if (dbusError || !dbusMessageReply.isMethodReturnType()) { callStatus = CallStatus::REMOTE_ERROR; return; @@ -144,7 +147,7 @@ std::future<CallStatus> DBusDaemonProxy::nameHasOwnerAsync(const std::string& bu return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, DBusProxyAsyncCallbackHandler<bool>::create(nameHasOwnerAsyncCallback, std::tuple<bool>()), - &daemonProxyInfo); + &daemonProxyInfo); } std::future<CallStatus> DBusDaemonProxy::getManagedObjectsAsync(const std::string& forDBusServiceName, GetManagedObjectsAsyncCallback callback) const { @@ -154,9 +157,9 @@ std::future<CallStatus> DBusDaemonProxy::getManagedObjectsAsync(const std::strin return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMethodCallMessage, DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create( - callback, std::tuple<DBusObjectToInterfaceDict>() + callback, std::tuple<DBusObjectToInterfaceDict>() ), - &daemonProxyInfo); + &daemonProxyInfo); } std::future<CallStatus> DBusDaemonProxy::getNameOwnerAsync(const std::string& busName, GetNameOwnerAsyncCallback getNameOwnerAsyncCallback) const { @@ -174,7 +177,7 @@ std::future<CallStatus> DBusDaemonProxy::getNameOwnerAsync(const std::string& bu return getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, DBusProxyAsyncCallbackHandler<std::string>::create(getNameOwnerAsyncCallback, std::tuple<std::string>()), - &daemonProxyInfo); + &daemonProxyInfo); } const char* DBusDaemonProxy::getInterfaceId() { diff --git a/src/CommonAPI/DBus/DBusDeployment.cpp b/src/CommonAPI/DBus/DBusDeployment.cpp deleted file mode 100644 index 973d5ff..0000000 --- a/src/CommonAPI/DBus/DBusDeployment.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <CommonAPI/DBus/DBusDeployment.hpp> - -namespace CommonAPI { -namespace DBus { - - COMMONAPI_IMPORT_EXPORT VariantDeployment<> freedesktopVariant(true); - -} // namespace DBus -} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusError.cpp b/src/CommonAPI/DBus/DBusError.cpp index 9dfb082..b5f5d5c 100644 --- a/src/CommonAPI/DBus/DBusError.cpp +++ b/src/CommonAPI/DBus/DBusError.cpp @@ -12,31 +12,29 @@ namespace CommonAPI { namespace DBus { DBusError::DBusError() { - dbus_error_init(&libdbusError_); + dbus_error_init(&libdbusError_); } DBusError::~DBusError() { - dbus_error_free(&libdbusError_); + dbus_error_free(&libdbusError_); } DBusError::operator bool() const { - return 0 != dbus_error_is_set(&libdbusError_); + return 0 != dbus_error_is_set(&libdbusError_); } void DBusError::clear() { - dbus_error_free(&libdbusError_); + dbus_error_free(&libdbusError_); } std::string DBusError::getName() const { - assert(*this); - return std::string(libdbusError_.name); + return std::string(libdbusError_.name); } std::string DBusError::getMessage() const { - assert(*this); - return std::string(libdbusError_.message); + return std::string(libdbusError_.message); } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp index afe5ad7..6371da9 100644 --- a/src/CommonAPI/DBus/DBusFactory.cpp +++ b/src/CommonAPI/DBus/DBusFactory.cpp @@ -18,13 +18,13 @@ namespace CommonAPI { namespace DBus { INITIALIZER(FactoryInit) { - Runtime::get()->registerFactory("dbus", Factory::get()); + Runtime::get()->registerFactory("dbus", Factory::get()); } std::shared_ptr<CommonAPI::DBus::Factory> Factory::get() { - static std::shared_ptr<Factory> theFactory = std::make_shared<Factory>(); - return theFactory; + static std::shared_ptr<Factory> theFactory = std::make_shared<Factory>(); + return theFactory; } Factory::Factory() { @@ -35,180 +35,185 @@ Factory::~Factory() { void Factory::registerProxyCreateMethod( - const std::string &_interface, ProxyCreateFunction _function) { - proxyCreateFunctions_[_interface] = _function; + const std::string &_interface, ProxyCreateFunction _function) { + proxyCreateFunctions_[_interface] = _function; } void Factory::registerStubAdapterCreateMethod( - const std::string &_interface, StubAdapterCreateFunction _function) { - stubAdapterCreateFunctions_[_interface] = _function; + const std::string &_interface, StubAdapterCreateFunction _function) { + stubAdapterCreateFunctions_[_interface] = _function; } std::shared_ptr<Proxy> Factory::createProxy( - const std::string &_domain, const std::string &_interface, const std::string &_instance, - const ConnectionId_t &_connectionId) { - auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface); - if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { - CommonAPI::Address address(_domain, _interface, _instance); - DBusAddress dbusAddress; - - if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { - std::shared_ptr<DBusProxy> proxy - = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId)); - if (proxy) - proxy->init(); - return proxy; - } - } - return nullptr; + const std::string &_domain, const std::string &_interface, const std::string &_instance, + const ConnectionId_t &_connectionId) { + auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface); + if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { + CommonAPI::Address address(_domain, _interface, _instance); + DBusAddress dbusAddress; + + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { + std::shared_ptr<DBusProxy> proxy + = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId)); + if (proxy) + proxy->init(); + return proxy; + } + } + return nullptr; } std::shared_ptr<Proxy> Factory::createProxy( - const std::string &_domain, const std::string &_interface, const std::string &_instance, - std::shared_ptr<MainLoopContext> _context) { - - auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface); - if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { - CommonAPI::Address address(_domain, _interface, _instance); - DBusAddress dbusAddress; - - if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { - std::shared_ptr<DBusProxy> proxy - = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_context)); - if (proxy) - proxy->init(); - return proxy; - } - } - - return nullptr; + const std::string &_domain, const std::string &_interface, const std::string &_instance, + std::shared_ptr<MainLoopContext> _context) { + + auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface); + if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) { + CommonAPI::Address address(_domain, _interface, _instance); + DBusAddress dbusAddress; + + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { + std::shared_ptr<DBusProxy> proxy + = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_context)); + if (proxy) + proxy->init(); + return proxy; + } + } + + return nullptr; } bool Factory::registerStub( - const std::string &_domain, const std::string &_interface, const std::string &_instance, - std::shared_ptr<StubBase> _stub, const ConnectionId_t &_connectionId) { - auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface); - if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) { - CommonAPI::Address address(_domain, _interface, _instance); - DBusAddress dbusAddress; - if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { - std::shared_ptr<DBusStubAdapter> adapter - = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId), _stub); - if (adapter) { - adapter->init(adapter); - return registerStubAdapter(adapter); - } - } - } - - return false; + const std::string &_domain, const std::string &_interface, const std::string &_instance, + std::shared_ptr<StubBase> _stub, const ConnectionId_t &_connectionId) { + auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface); + if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) { + CommonAPI::Address address(_domain, _interface, _instance); + DBusAddress dbusAddress; + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { + std::shared_ptr<DBusStubAdapter> adapter + = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId), _stub); + if (adapter) { + adapter->init(adapter); + return registerStubAdapter(adapter); + } + } + } + + return false; } bool Factory::registerStub( - const std::string &_domain, const std::string &_interface, const std::string &_instance, - std::shared_ptr<StubBase> _stub, std::shared_ptr<MainLoopContext> _context) { - auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface); - if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) { - CommonAPI::Address address(_domain, _interface, _instance); - DBusAddress dbusAddress; - if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { - std::shared_ptr<DBusStubAdapter> adapter - = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_context), _stub); - if (adapter) { - adapter->init(adapter); - return registerStubAdapter(adapter); - } - } - } - return false; + const std::string &_domain, const std::string &_interface, const std::string &_instance, + std::shared_ptr<StubBase> _stub, std::shared_ptr<MainLoopContext> _context) { + auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface); + if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) { + CommonAPI::Address address(_domain, _interface, _instance); + DBusAddress dbusAddress; + if (DBusAddressTranslator::get()->translate(address, dbusAddress)) { + std::shared_ptr<DBusStubAdapter> adapter + = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_context), _stub); + if (adapter) { + adapter->init(adapter); + return registerStubAdapter(adapter); + } + } + } + return false; } bool Factory::unregisterStub(const std::string &_domain, const std::string &_interface, const std::string &_instance) { - CommonAPI::Address address(_domain, _interface, _instance); - const auto &adapterResult = services_.find(address.getAddress()); - if (adapterResult != services_.end()) { - const auto _adapter = adapterResult->second; - const auto &connection = _adapter->getDBusConnection(); - const auto objectManager = connection->getDBusObjectManager(); - - if (!objectManager->unregisterDBusStubAdapter(_adapter)) { - return false; - } - - if (!connection->releaseServiceName(_adapter->getDBusAddress().getService())) { - return false; - } - - if (!unregisterStubAdapter(_adapter)) { - return false; - } - - services_.erase(adapterResult->first); - - return true; - } - - return false; + CommonAPI::Address address(_domain, _interface, _instance); + const auto &adapterResult = services_.find(address.getAddress()); + if (adapterResult != services_.end()) { + const auto _adapter = adapterResult->second; + const auto &connection = _adapter->getDBusConnection(); + const auto objectManager = connection->getDBusObjectManager(); + + if (!objectManager->unregisterDBusStubAdapter(_adapter)) { + return false; + } + + if (!connection->releaseServiceName(_adapter->getDBusAddress().getService())) { + return false; + } + + if (!unregisterStubAdapter(_adapter)) { + return false; + } + + services_.erase(adapterResult->first); + + return true; + } + + return false; } bool Factory::registerStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) { - CommonAPI::Address address; - DBusAddress dbusAddress = _adapter->getDBusAddress(); - if (DBusAddressTranslator::get()->translate(dbusAddress, address)) { - const auto &insertResult = services_.insert( { address.getAddress(), _adapter } ); - - const auto &connection = _adapter->getDBusConnection(); - const auto objectManager = connection->getDBusObjectManager(); - if (!objectManager->registerDBusStubAdapter(_adapter)) { - services_.erase(insertResult.first); - return false; - } - - const bool isServiceNameAcquired - = connection->requestServiceNameAndBlock(dbusAddress.getService()); - if (!isServiceNameAcquired) { - (void)objectManager->unregisterDBusStubAdapter(_adapter); - services_.erase(insertResult.first); - return false; - } - - std::shared_ptr<DBusObjectManagerStub> root - = connection->getDBusObjectManager()->getRootDBusObjectManagerStub(); - if (!root->exportManagedDBusStubAdapter(_adapter)) { - (void)unregisterManagedService(address.getAddress()); - return false; - } - - return true; - } - - return false; + CommonAPI::Address address; + DBusAddress dbusAddress = _adapter->getDBusAddress(); + if (DBusAddressTranslator::get()->translate(dbusAddress, address)) { + const auto &insertResult = services_.insert( { address.getAddress(), _adapter } ); + + const auto &connection = _adapter->getDBusConnection(); + + std::shared_ptr<DBusObjectManagerStub> root + = connection->getDBusObjectManager()->getRootDBusObjectManagerStub(); + if (!root->exportManagedDBusStubAdapter(_adapter)) { + (void)unregisterManagedService(address.getAddress()); + return false; + } + + const auto objectManager = connection->getDBusObjectManager(); + if (!objectManager->registerDBusStubAdapter(_adapter)) { + (void)root->unexportManagedDBusStubAdapter(_adapter); + (void)unregisterManagedService(address.getAddress()); + services_.erase(insertResult.first); + return false; + } + + const bool isServiceNameAcquired + = connection->requestServiceNameAndBlock(dbusAddress.getService()); + if (!isServiceNameAcquired) { + (void)root->unexportManagedDBusStubAdapter(_adapter); + (void)objectManager->unregisterDBusStubAdapter(_adapter); + (void)unregisterManagedService(address.getAddress()); + services_.erase(insertResult.first); + return false; + } + + return true; + } + + return false; } bool Factory::unregisterStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) { - CommonAPI::Address address; - DBusAddress dbusAddress = _adapter->getDBusAddress(); - if (DBusAddressTranslator::get()->translate(dbusAddress, address)) { - const auto &connection = _adapter->getDBusConnection(); - - std::shared_ptr<DBusObjectManagerStub> root - = connection->getDBusObjectManager()->getRootDBusObjectManagerStub(); - if (!root->unexportManagedDBusStubAdapter(_adapter)) { - //(void)unregisterManagedService(address.getAddress()); - return false; - } - - return true; - } - return false; + CommonAPI::Address address; + DBusAddress dbusAddress = _adapter->getDBusAddress(); + if (DBusAddressTranslator::get()->translate(dbusAddress, address)) { + const auto &connection = _adapter->getDBusConnection(); + + std::shared_ptr<DBusObjectManagerStub> root + = connection->getDBusObjectManager()->getRootDBusObjectManagerStub(); + if (!root->unexportManagedDBusStubAdapter(_adapter)) { + //(void)unregisterManagedService(address.getAddress()); + return false; + } + + return true; + } + return false; } /////////////////////////////////////////////////////////////////////////////// @@ -217,41 +222,41 @@ Factory::unregisterStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) { std::shared_ptr<DBusConnection> Factory::getConnection(const ConnectionId_t &_connectionId) { - auto itsConnectionIterator = connections_.find(_connectionId); - if (itsConnectionIterator != connections_.end()) { - return itsConnectionIterator->second; - } + auto itsConnectionIterator = connections_.find(_connectionId); + if (itsConnectionIterator != connections_.end()) { + return itsConnectionIterator->second; + } - // No connection found, lets create and initialize one - DBusType_t dbusType = DBusAddressTranslator::get()->getDBusBusType(_connectionId); - std::shared_ptr<DBusConnection> itsConnection - = std::make_shared<DBusConnection>(dbusType); - connections_.insert({ _connectionId, itsConnection }); + // No connection found, lets create and initialize one + DBusType_t dbusType = DBusAddressTranslator::get()->getDBusBusType(_connectionId); + std::shared_ptr<DBusConnection> itsConnection + = std::make_shared<DBusConnection>(dbusType); + connections_.insert({ _connectionId, itsConnection }); - itsConnection->connect(true); - return itsConnection; + itsConnection->connect(true); + return itsConnection; } std::shared_ptr<DBusConnection> Factory::getConnection(std::shared_ptr<MainLoopContext> _context) { - if (!_context) - return getConnection(DEFAULT_CONNECTION_ID); + if (!_context) + return getConnection(DEFAULT_CONNECTION_ID); - auto itsConnectionIterator = contextConnections_.find(_context.get()); - if (itsConnectionIterator != contextConnections_.end()) { - return itsConnectionIterator->second; - } + auto itsConnectionIterator = contextConnections_.find(_context.get()); + if (itsConnectionIterator != contextConnections_.end()) { + return itsConnectionIterator->second; + } - // No connection found, lets create and initialize one - std::shared_ptr<DBusConnection> itsConnection - = std::make_shared<DBusConnection>(DBusType_t::SESSION); - contextConnections_.insert({ _context.get(), itsConnection } ); + // No connection found, lets create and initialize one + std::shared_ptr<DBusConnection> itsConnection + = std::make_shared<DBusConnection>(DBusType_t::SESSION); + contextConnections_.insert({ _context.get(), itsConnection } ); - itsConnection->connect(false); - if (_context) - itsConnection->attachMainLoopContext(_context); + itsConnection->connect(false); + if (_context) + itsConnection->attachMainLoopContext(_context); - return itsConnection; + return itsConnection; } /////////////////////////////////////////////////////////////////////////////// @@ -271,18 +276,18 @@ Factory::getRegisteredService(const std::string &_address) { /////////////////////////////////////////////////////////////////////////////// std::shared_ptr<DBusStubAdapter> Factory::createDBusStubAdapter( - const std::shared_ptr<StubBase> &_stub, + const std::shared_ptr<StubBase> &_stub, const std::string &_interface, - const DBusAddress &_dbusAddress, - const std::shared_ptr<DBusProxyConnection> &_connection) { + const DBusAddress &_dbusAddress, + const std::shared_ptr<DBusProxyConnection> &_connection) { std::shared_ptr<DBusStubAdapter> stubAdapter; auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface); if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) { stubAdapter = stubAdapterCreateFunctionsIterator->second( - _dbusAddress, _connection, _stub); + _dbusAddress, _connection, _stub); if (stubAdapter) - stubAdapter->init(stubAdapter); + stubAdapter->init(stubAdapter); } return stubAdapter; } @@ -293,24 +298,25 @@ Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAda const auto &insertResult = services_.insert( { itsAddress, _stubAdapter} ); if (insertResult.second) { - const auto &connection = _stubAdapter->getDBusConnection(); - const auto objectManager = connection->getDBusObjectManager(); - const bool isRegistered = objectManager->registerDBusStubAdapter(_stubAdapter); - if (!isRegistered) { - services_.erase(insertResult.first); - return false; - } - - const auto &serviceName = _stubAdapter->getDBusAddress().getService(); - const bool isAcquired = connection->requestServiceNameAndBlock(serviceName); - if (!isAcquired) { - const bool isDeregistered = objectManager->unregisterDBusStubAdapter(_stubAdapter); - assert(isDeregistered); - - services_.erase(insertResult.first); - } - - return isAcquired; + const auto &connection = _stubAdapter->getDBusConnection(); + const auto objectManager = connection->getDBusObjectManager(); + const bool isRegistered = objectManager->registerDBusStubAdapter(_stubAdapter); + if (!isRegistered) { + services_.erase(insertResult.first); + return false; + } + + const auto &serviceName = _stubAdapter->getDBusAddress().getService(); + const bool isAcquired = connection->requestServiceNameAndBlock(serviceName); + if (!isAcquired) { + const bool isDeregistered = objectManager->unregisterDBusStubAdapter(_stubAdapter); + assert(isDeregistered); + (void)isDeregistered; + + services_.erase(insertResult.first); + } + + return isAcquired; } return false; @@ -319,24 +325,24 @@ Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAda bool Factory::unregisterManagedService(const std::string &_address) { - return unregisterManagedService(services_.find(_address)); + return unregisterManagedService(services_.find(_address)); } bool Factory::unregisterManagedService(const ServicesMap::iterator &iterator) { - if (iterator == services_.end()) - return true; + if (iterator == services_.end()) + return true; - const auto &stubAdapter = iterator->second; + const auto &stubAdapter = iterator->second; const auto &connection = stubAdapter->getDBusConnection(); const auto objectManager = connection->getDBusObjectManager(); const auto &serviceName = stubAdapter->getDBusAddress().getService(); const bool isUnregistered - = objectManager->unregisterDBusStubAdapter(stubAdapter); + = objectManager->unregisterDBusStubAdapter(stubAdapter); if (isUnregistered) { - connection->releaseServiceName(serviceName); - services_.erase(iterator); + connection->releaseServiceName(serviceName); + services_.erase(iterator); } // TODO: log error return isUnregistered; diff --git a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp index 7d9ce62..75fc0b5 100644 --- a/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp +++ b/src/CommonAPI/DBus/DBusFreedesktopPropertiesStub.cpp @@ -15,12 +15,12 @@ namespace CommonAPI { namespace DBus { DBusFreedesktopPropertiesStub::DBusFreedesktopPropertiesStub( - const std::string &_path, const std::string &_interface, - const std::shared_ptr<DBusProxyConnection> &_connection, - const std::shared_ptr<DBusStubAdapter> &_adapter) - : path_(_path), - connection_(_connection), - adapter_(_adapter) { + const std::string &_path, const std::string &_interface, + const std::shared_ptr<DBusProxyConnection> &_connection, + const std::shared_ptr<DBusStubAdapter> &_adapter) + : path_(_path), + connection_(_connection), + adapter_(_adapter) { assert(!path_.empty()); assert(path_[0] == '/'); assert(_connection); @@ -66,9 +66,9 @@ DBusFreedesktopPropertiesStub::onInterfaceDBusMessage(const DBusMessage &_messag } if (!_message.isMethodCallType() || - !(_message.hasMemberName("Get") || - _message.hasMemberName("GetAll") || - _message.hasMemberName("Set"))) { + !(_message.hasMemberName("Get") || + _message.hasMemberName("GetAll") || + _message.hasMemberName("Set"))) { return false; } @@ -89,7 +89,7 @@ DBusFreedesktopPropertiesStub::onInterfaceDBusMessage(const DBusMessage &_messag return it->second->onInterfaceDBusFreedesktopPropertiesMessage(_message); } -const bool DBusFreedesktopPropertiesStub::hasFreedesktopProperties() { +bool DBusFreedesktopPropertiesStub::hasFreedesktopProperties() { return false; } @@ -98,7 +98,7 @@ const std::string &DBusFreedesktopPropertiesStub::getObjectPath() const { } const std::string &DBusFreedesktopPropertiesStub::getInterface() { - static std::string theInterface("org.freedesktop.DBus.Properties"); + static std::string theInterface("org.freedesktop.DBus.Properties"); return theInterface; } diff --git a/src/CommonAPI/DBus/DBusFunctionalHash.cpp b/src/CommonAPI/DBus/DBusFunctionalHash.cpp index 7eeb67f..00b5da6 100644 --- a/src/CommonAPI/DBus/DBusFunctionalHash.cpp +++ b/src/CommonAPI/DBus/DBusFunctionalHash.cpp @@ -13,7 +13,7 @@ /* * @see http://code.google.com/p/smhasher/ */ -#define SMHASHER_SEED_VALUE 0xc70f6907UL +#define SMHASHER_SEED_VALUE 0xc70f6907UL namespace std { @@ -25,15 +25,15 @@ size_t hash<pair<const char*, const char*> >::operator()(const pair<const char*, assert(b); uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a, strlen(a), seed, &seed); - MurmurHash3_x86_32(b, strlen(b), seed, &seed); + MurmurHash3_x86_32(a, static_cast<int>(strlen(a)), seed, &seed); + MurmurHash3_x86_32(b, static_cast<int>(strlen(b)), seed, &seed); return static_cast<size_t>(seed); } size_t hash<const char*>::operator()(const char* const t) const { uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(t, strlen(t), seed, &seed); + MurmurHash3_x86_32(t, static_cast<int>(strlen(t)), seed, &seed); return static_cast<size_t>(seed); } @@ -42,8 +42,8 @@ size_t hash<pair<string, string> >::operator()(const pair<string, string>& t) co const string& b = t.second; uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); - MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); + MurmurHash3_x86_32(a.c_str(), static_cast<int>(a.length()), seed, &seed); + MurmurHash3_x86_32(b.c_str(), static_cast<int>(b.length()), seed, &seed); return static_cast<size_t>(seed); } @@ -54,9 +54,9 @@ size_t hash<tuple<string, string, string> >::operator()(const tuple<string, stri const string& c = get<2>(t); uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); - MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); - MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); + MurmurHash3_x86_32(a.c_str(), static_cast<int>(a.length()), seed, &seed); + MurmurHash3_x86_32(b.c_str(), static_cast<int>(b.length()), seed, &seed); + MurmurHash3_x86_32(c.c_str(), static_cast<int>(c.length()), seed, &seed); return static_cast<size_t>(seed); } @@ -68,9 +68,9 @@ size_t hash<tuple<string, string, string, bool> >::operator()(const tuple<string const bool d = get<3>(t); uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); - MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); - MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); + MurmurHash3_x86_32(a.c_str(), static_cast<int>(a.length()), seed, &seed); + MurmurHash3_x86_32(b.c_str(), static_cast<int>(b.length()), seed, &seed); + MurmurHash3_x86_32(c.c_str(), static_cast<int>(c.length()), seed, &seed); MurmurHash3_x86_32(&d, sizeof(bool), seed, &seed); return static_cast<size_t>(seed); @@ -83,9 +83,9 @@ size_t hash<tuple<string, string, string, int> >::operator()(const tuple<string, const int d = get<3>(t); uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); - MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); - MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); + MurmurHash3_x86_32(a.c_str(), static_cast<int>(a.length()), seed, &seed); + MurmurHash3_x86_32(b.c_str(), static_cast<int>(b.length()), seed, &seed); + MurmurHash3_x86_32(c.c_str(), static_cast<int>(c.length()), seed, &seed); MurmurHash3_x86_32(&d, sizeof(d), seed, &seed); return static_cast<size_t>(seed); @@ -98,10 +98,10 @@ size_t hash<tuple<string, string, string, string> >::operator()(const tuple<stri const string& d = get<3>(t); uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE); - MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed); - MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed); - MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed); - MurmurHash3_x86_32(d.c_str(), d.length(), seed, &seed); + MurmurHash3_x86_32(a.c_str(), static_cast<int>(a.length()), seed, &seed); + MurmurHash3_x86_32(b.c_str(), static_cast<int>(b.length()), seed, &seed); + MurmurHash3_x86_32(c.c_str(), static_cast<int>(c.length()), seed, &seed); + MurmurHash3_x86_32(d.c_str(), static_cast<int>(d.length()), seed, &seed); return static_cast<size_t>(seed); } diff --git a/src/CommonAPI/DBus/DBusInputStream.cpp b/src/CommonAPI/DBus/DBusInputStream.cpp index 07964d8..ae2201a 100644 --- a/src/CommonAPI/DBus/DBusInputStream.cpp +++ b/src/CommonAPI/DBus/DBusInputStream.cpp @@ -11,7 +11,7 @@ namespace CommonAPI { namespace DBus { DBusInputStream::DBusInputStream(const CommonAPI::DBus::DBusMessage &_message) - : begin_(_message.getBodyData()), + : begin_(_message.getBodyData()), current_(0), size_(_message.getBodyLength()), exception_(nullptr), @@ -33,7 +33,7 @@ void DBusInputStream::clearError() { } void DBusInputStream::align(const size_t _boundary) { - const unsigned int mask = _boundary - 1; + const unsigned int mask = static_cast<unsigned int>(_boundary) - 1; current_ = (current_ + mask) & (~mask); } @@ -50,75 +50,86 @@ void DBusInputStream::setError() { } void DBusInputStream::pushPosition() { - positions_.push(current_); + positions_.push(current_); } size_t DBusInputStream::popPosition() { - size_t itsPosition = positions_.top(); - positions_.pop(); - return itsPosition; + size_t itsPosition = positions_.top(); + positions_.pop(); + return itsPosition; } void DBusInputStream::pushSize(size_t _size) { - sizes_.push(_size); + sizes_.push(static_cast<unsigned int>(_size)); } size_t DBusInputStream::popSize() { - size_t itsSize = sizes_.top(); - sizes_.pop(); - return itsSize; + size_t itsSize = sizes_.top(); + sizes_.pop(); + return itsSize; } InputStream<DBusInputStream> &DBusInputStream::readValue(bool &_value, const EmptyDeployment *_depl) { - uint32_t tmp; - readValue(tmp, _depl); - if (tmp > 1) - setError(); - _value = (tmp != 0); - return (*this); + uint32_t tmp; + readValue(tmp, _depl); + if (tmp > 1) + setError(); + _value = (tmp != 0); + return (*this); } InputStream<DBusInputStream> &DBusInputStream::readValue(int8_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(int16_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(int32_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(int64_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(uint8_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(uint16_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(uint32_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(uint64_t &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(float &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(double &_value, const EmptyDeployment *_depl) { + (void)_depl; return _readValue(_value); } InputStream<DBusInputStream> &DBusInputStream::readValue(std::string &_value, const EmptyDeployment *_depl) { + (void)_depl; uint32_t length; _readValue(length); @@ -132,6 +143,7 @@ InputStream<DBusInputStream> &DBusInputStream::readValue(std::string &_value, co } InputStream<DBusInputStream> &DBusInputStream::readValue(Version &_value, const EmptyDeployment *_depl) { + (void)_depl; align(8); _readValue(_value.Major); _readValue(_value.Minor); diff --git a/src/CommonAPI/DBus/DBusMainLoop.cpp b/src/CommonAPI/DBus/DBusMainLoop.cpp new file mode 100755 index 0000000..f674387 --- /dev/null +++ b/src/CommonAPI/DBus/DBusMainLoop.cpp @@ -0,0 +1,697 @@ +// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifdef WIN32 +#include <WinSock2.h> +#include <ws2tcpip.h> +#define DEFAULT_BUFLEN 512 +#else +#include <poll.h> +#include <sys/eventfd.h> +#include <unistd.h> +#endif + +#include <iostream> +#include <thread> +#include <cstdio> + +#include <CommonAPI/DBus/DBusMainLoop.hpp> + +namespace CommonAPI { +namespace DBus { + +DBusMainLoop::DBusMainLoop(std::shared_ptr<MainLoopContext> context) + : context_(context), + currentMinimalTimeoutInterval_(TIMEOUT_INFINITE), + hasToStop_(false), + isBroken_(false) { +#ifdef WIN32 + WSADATA wsaData; + int iResult; + + SOCKET ListenSocket = INVALID_SOCKET; + + struct addrinfo *result = NULL; + struct addrinfo hints; + + // Initialize Winsock + iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + printf("WSAStartup failed with error: %d\n", iResult); + } + + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + + // Resolve the server address and port + iResult = getaddrinfo(NULL, "0", &hints, &result); + if (iResult != 0) { + printf("getaddrinfo failed with error: %d\n", iResult); + WSACleanup(); + } + + // Create a SOCKET for connecting to server + ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (ListenSocket == INVALID_SOCKET) { + printf("socket failed with error: %ld\n", WSAGetLastError()); + freeaddrinfo(result); + WSACleanup(); + } + + // Setup the TCP listening socket + iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); + if (iResult == SOCKET_ERROR) { + printf("bind failed with error: %d\n", WSAGetLastError()); + freeaddrinfo(result); + closesocket(ListenSocket); + WSACleanup(); + } + + sockaddr* connected_addr = new sockaddr(); + USHORT port = 0; + int namelength = sizeof(sockaddr); + iResult = getsockname(ListenSocket, connected_addr, &namelength); + if (iResult == SOCKET_ERROR) { + printf("getsockname failed with error: %d\n", WSAGetLastError()); + } else if (connected_addr->sa_family == AF_INET) { + port = ((struct sockaddr_in*)connected_addr)->sin_port; + } + delete connected_addr; + + freeaddrinfo(result); + + iResult = listen(ListenSocket, SOMAXCONN); + if (iResult == SOCKET_ERROR) { + printf("listen failed with error: %d\n", WSAGetLastError()); + closesocket(ListenSocket); + WSACleanup(); + } + + wsaData; + wakeFd_.fd = INVALID_SOCKET; + struct addrinfo *ptr = NULL; + + // Initialize Winsock + iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != 0) { + printf("WSAStartup failed with error: %d\n", iResult); + } + + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + // Resolve the server address and port + iResult = getaddrinfo("127.0.0.1", std::to_string(ntohs(port)).c_str(), &hints, &result); + if (iResult != 0) { + printf("getaddrinfo failed with error: %d\n", iResult); + WSACleanup(); + } + + // Attempt to connect to an address until one succeeds + for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { + + // Create a SOCKET for connecting to server + wakeFd_.fd = socket(ptr->ai_family, ptr->ai_socktype, + ptr->ai_protocol); + if (wakeFd_.fd == INVALID_SOCKET) { + printf("socket failed with error: %ld\n", WSAGetLastError()); + WSACleanup(); + } + + // Connect to server. + iResult = connect(wakeFd_.fd, ptr->ai_addr, (int)ptr->ai_addrlen); + if (iResult == SOCKET_ERROR) { + printf("connect failed with error: %ld\n", WSAGetLastError()); + closesocket(wakeFd_.fd); + wakeFd_.fd = INVALID_SOCKET; + continue; + } + break; + } + + freeaddrinfo(result); + + if (wakeFd_.fd == INVALID_SOCKET) { + printf("Unable to connect to server!\n"); + WSACleanup(); + } + + // Accept a client socket + sendFd_.fd = accept(ListenSocket, NULL, NULL); + if (sendFd_.fd == INVALID_SOCKET) { + printf("accept failed with error: %d\n", WSAGetLastError()); + closesocket(ListenSocket); + WSACleanup(); + } + + wakeFd_.events = POLLIN; + registerFileDescriptor(wakeFd_); +#else + wakeFd_.fd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK); + wakeFd_.events = POLLIN; + registerFileDescriptor(wakeFd_); +#endif + + dispatchSourceListenerSubscription_ = context_->subscribeForDispatchSources( + std::bind(&DBusMainLoop::registerDispatchSource, this, + std::placeholders::_1, std::placeholders::_2), + std::bind(&DBusMainLoop::unregisterDispatchSource, + this, std::placeholders::_1)); + watchListenerSubscription_ = context_->subscribeForWatches( + std::bind(&DBusMainLoop::registerWatch, this, + std::placeholders::_1, std::placeholders::_2), + std::bind(&DBusMainLoop::unregisterWatch, this, + std::placeholders::_1)); + timeoutSourceListenerSubscription_ = context_->subscribeForTimeouts( + std::bind(&DBusMainLoop::registerTimeout, this, + std::placeholders::_1, std::placeholders::_2), + std::bind(&DBusMainLoop::unregisterTimeout, this, + std::placeholders::_1)); + wakeupListenerSubscription_ = context_->subscribeForWakeupEvents( + std::bind(&DBusMainLoop::wakeup, this)); +} + +DBusMainLoop::~DBusMainLoop() { + unregisterFileDescriptor (wakeFd_); + + context_->unsubscribeForDispatchSources( + dispatchSourceListenerSubscription_); + context_->unsubscribeForWatches(watchListenerSubscription_); + context_->unsubscribeForTimeouts(timeoutSourceListenerSubscription_); + context_->unsubscribeForWakeupEvents(wakeupListenerSubscription_); + +#ifdef WIN32 + // shutdown the connection since no more data will be sent + int iResult = shutdown(wakeFd_.fd, SD_SEND); + if (iResult == SOCKET_ERROR) { + printf("shutdown failed with error: %d\n", WSAGetLastError()); + closesocket(wakeFd_.fd); + WSACleanup(); + } + + // cleanup + closesocket(wakeFd_.fd); + WSACleanup(); +#else + close(wakeFd_.fd); +#endif +} + +void DBusMainLoop::run(const int64_t& timeoutInterval) { + while (!hasToStop_) { + doSingleIteration(timeoutInterval); + } +} + +void DBusMainLoop::stop() { + hasToStop_ = true; + wakeup(); +} + +void DBusMainLoop::doSingleIteration(const int64_t& timeout) { + { + std::lock_guard<std::mutex> itsLock(dispatchSourcesMutex_); + for (auto dispatchSourceIterator = registeredDispatchSources_.begin(); + dispatchSourceIterator != registeredDispatchSources_.end(); + dispatchSourceIterator++) { + + (dispatchSourceIterator->second)->mutex_->lock(); + if ((dispatchSourceIterator->second)->deleteObject_) { + if (!(dispatchSourceIterator->second)->isExecuted_) { + (dispatchSourceIterator->second)->mutex_->unlock(); + bool contained = false; + for (std::set<DispatchSourceToDispatchStruct*>::iterator dispatchSourceIteratorInner = sourcesToDispatch_.begin(); + dispatchSourceIteratorInner != sourcesToDispatch_.end(); dispatchSourceIteratorInner++) { + if ((*dispatchSourceIteratorInner)->dispatchSource_ == (dispatchSourceIterator->second)->dispatchSource_) { + contained = true; + break; + } + } + if (!contained) { + delete (dispatchSourceIterator->second)->dispatchSource_; + (dispatchSourceIterator->second)->dispatchSource_ = NULL; + delete (dispatchSourceIterator->second)->mutex_; + (dispatchSourceIterator->second)->mutex_ = NULL; + delete dispatchSourceIterator->second; + dispatchSourceIterator = registeredDispatchSources_.erase(dispatchSourceIterator); + } + if (dispatchSourceIterator == registeredDispatchSources_.end()) { + break; + } + } + else { + (dispatchSourceIterator->second)->mutex_->unlock(); + } + } + else { + (dispatchSourceIterator->second)->mutex_->unlock(); + } + } + } + + { + std::lock_guard<std::mutex> itsLock(timeoutsMutex_); + for (auto timeoutIterator = registeredTimeouts_.begin(); + timeoutIterator != registeredTimeouts_.end(); + timeoutIterator++) { + + (timeoutIterator->second)->mutex_->lock(); + if ((timeoutIterator->second)->deleteObject_) { + if (!(timeoutIterator->second)->isExecuted_) { + (timeoutIterator->second)->mutex_->unlock(); + bool contained = false; + for (std::set<TimeoutToDispatchStruct*>::iterator timeoutIteratorInner = timeoutsToDispatch_.begin(); + timeoutIteratorInner != timeoutsToDispatch_.end(); timeoutIteratorInner++) { + if ((*timeoutIteratorInner)->timeout_ == (timeoutIterator->second)->timeout_) { + contained = true; + break; + } + } + if (!contained) { + delete (timeoutIterator->second)->timeout_; + (timeoutIterator->second)->timeout_ = NULL; + delete (timeoutIterator->second)->mutex_; + (timeoutIterator->second)->mutex_ = NULL; + delete timeoutIterator->second; + timeoutIterator = registeredTimeouts_.erase(timeoutIterator); + } + if (timeoutIterator == registeredTimeouts_.end()) { + break; + } + } + else { + (timeoutIterator->second)->mutex_->unlock(); + } + } + else { + (timeoutIterator->second)->mutex_->unlock(); + } + } + } + + { + std::lock_guard<std::mutex> itsLock(watchesMutex_); + for (auto watchesIterator = registeredWatches_.begin(); + watchesIterator != registeredWatches_.end(); + watchesIterator++) { + + (watchesIterator->second)->mutex_->lock(); + if ((watchesIterator->second)->deleteObject_) { + if (!(watchesIterator->second)->isExecuted_) { + (watchesIterator->second)->mutex_->unlock(); + bool contained = false; + for (auto watchesIteratorInner = watchesToDispatch_.begin(); + watchesIteratorInner != watchesToDispatch_.end(); watchesIteratorInner++) { + if ((*watchesIteratorInner)->watch_ == (watchesIterator->second)->watch_) { + contained = true; + break; + } + } + if (!contained) { + delete (watchesIterator->second)->watch_; + (watchesIterator->second)->watch_ = NULL; + delete (watchesIterator->second)->mutex_; + (watchesIterator->second)->mutex_ = NULL; + delete watchesIterator->second; + watchesIterator = registeredWatches_.erase(watchesIterator); + } + if (watchesIterator == registeredWatches_.end()) { + break; + } + } + else { + (watchesIterator->second)->mutex_->unlock(); + } + } + else { + (watchesIterator->second)->mutex_->unlock(); + } + } + } + + if (prepare(timeout)) { + dispatch(); + } else { + poll(); + if (check()) { + dispatch(); + } + } +} + +bool DBusMainLoop::prepare(const int64_t& timeout) { + currentMinimalTimeoutInterval_ = timeout; + + { + std::lock_guard<std::mutex> itsLock(dispatchSourcesMutex_); + for (auto dispatchSourceIterator = registeredDispatchSources_.begin(); + dispatchSourceIterator != registeredDispatchSources_.end(); + dispatchSourceIterator++) { + + int64_t dispatchTimeout = TIMEOUT_INFINITE; + if ((dispatchSourceIterator->second)->dispatchSource_->prepare(dispatchTimeout)) { + sourcesToDispatch_.insert(dispatchSourceIterator->second); + } else if (dispatchTimeout < currentMinimalTimeoutInterval_) { + currentMinimalTimeoutInterval_ = dispatchTimeout; + } + } + } + + int64_t currentContextTime = getCurrentTimeInMs(); + + { + std::lock_guard<std::mutex> itsLock(timeoutsMutex_); + for (auto timeoutPriorityRange = registeredTimeouts_.begin(); + timeoutPriorityRange != registeredTimeouts_.end(); + timeoutPriorityRange++) { + + (timeoutPriorityRange->second)->mutex_->lock(); + bool deleteObject = (timeoutPriorityRange->second)->deleteObject_; + (timeoutPriorityRange->second)->mutex_->unlock(); + + if (!deleteObject) { + if (!(timeoutPriorityRange->second)->timeoutElapsed_) { // check that timeout is not elapsed + int64_t intervalToReady = (timeoutPriorityRange->second)->timeout_->getReadyTime() + - currentContextTime; + + if (intervalToReady <= 0) { + // set information that timeout is elapsed + (timeoutPriorityRange->second)->timeoutElapsed_ = true; + + timeoutsToDispatch_.insert(timeoutPriorityRange->second); + currentMinimalTimeoutInterval_ = TIMEOUT_NONE; + } else if (intervalToReady < currentMinimalTimeoutInterval_) { + currentMinimalTimeoutInterval_ = intervalToReady; + } + } + } + } + } + + return (!sourcesToDispatch_.empty() || !timeoutsToDispatch_.empty()); +} + +void DBusMainLoop::poll() { + int managedFileDescriptorOffset = 0; + + for (auto fileDescriptor = managedFileDescriptors_.begin() + managedFileDescriptorOffset; fileDescriptor != managedFileDescriptors_.end(); ++fileDescriptor) { + (*fileDescriptor).revents = 0; + } + +#ifdef WIN32 + size_t numReadyFileDescriptors = WSAPoll(&managedFileDescriptors_[0], managedFileDescriptors_.size(), -1); +#else + size_t numReadyFileDescriptors = ::poll(&(managedFileDescriptors_[0]), + managedFileDescriptors_.size(), -1); +#endif + if (!numReadyFileDescriptors) { + int64_t currentContextTime = getCurrentTimeInMs(); + + { + std::lock_guard<std::mutex> itsLock(timeoutsMutex_); + for (auto timeoutPriorityRange = registeredTimeouts_.begin(); + timeoutPriorityRange != registeredTimeouts_.end(); + timeoutPriorityRange++) { + + (timeoutPriorityRange->second)->mutex_->lock(); + bool deleteObject = (timeoutPriorityRange->second)->deleteObject_; + (timeoutPriorityRange->second)->mutex_->unlock(); + + if (!deleteObject) { + if (!(timeoutPriorityRange->second)->timeoutElapsed_) { // check that timeout is not elapsed + int64_t intervalToReady = + (timeoutPriorityRange->second)->timeout_->getReadyTime() + - currentContextTime; + + if (intervalToReady <= 0) { + // set information that timeout is elapsed + (timeoutPriorityRange->second)->timeoutElapsed_ = true; + + timeoutsToDispatch_.insert(timeoutPriorityRange->second); + } + } + } + } + } + } + + // If the wakeup descriptor woke us up, we must acknowledge + if (managedFileDescriptors_[0].revents) { + wakeupAck(); + } +} + +bool DBusMainLoop::check() { +//The first file descriptor always is the loop's wakeup-descriptor (but not for windows anymore). All others need to be linked to a watch. + int managedFileDescriptorOffset = 1; + { + std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); + for (auto fileDescriptor = managedFileDescriptors_.begin() + managedFileDescriptorOffset; + fileDescriptor != managedFileDescriptors_.end(); ++fileDescriptor) { + { + std::lock_guard<std::mutex> itsWatchesLock(watchesMutex_); + for (auto registeredWatchIterator = registeredWatches_.begin(); + registeredWatchIterator != registeredWatches_.end(); + registeredWatchIterator++) { + + (registeredWatchIterator->second)->mutex_->lock(); + bool deleteObject = (registeredWatchIterator->second)->deleteObject_; + (registeredWatchIterator->second)->mutex_->unlock(); + + if (!deleteObject) { + if ((registeredWatchIterator->second)->fd_ == fileDescriptor->fd + && fileDescriptor->revents) { + watchesToDispatch_.insert(registeredWatchIterator->second); + } + } + } + } + } + } + { + std::lock_guard<std::mutex> itsLock(dispatchSourcesMutex_); + for (auto dispatchSourceIterator = registeredDispatchSources_.begin(); + dispatchSourceIterator != registeredDispatchSources_.end(); + ++dispatchSourceIterator) { + if ((dispatchSourceIterator->second)->dispatchSource_->check()) { + sourcesToDispatch_.insert(dispatchSourceIterator->second); + } + } + } + + return (!timeoutsToDispatch_.empty() || + !watchesToDispatch_.empty() || + !sourcesToDispatch_.empty()); +} + +void DBusMainLoop::dispatch() { + if (timeoutsToDispatch_.size() > 0) + { + for (auto timeoutIterator = timeoutsToDispatch_.begin(); + timeoutIterator != timeoutsToDispatch_.end(); timeoutIterator++) { + (*timeoutIterator)->mutex_->lock(); + if (!(*timeoutIterator)->deleteObject_) { + (*timeoutIterator)->isExecuted_ = true; + (*timeoutIterator)->mutex_->unlock(); + (*timeoutIterator)->timeout_->dispatch(); + (*timeoutIterator)->mutex_->lock(); + (*timeoutIterator)->isExecuted_ = false; + } + (*timeoutIterator)->mutex_->unlock(); + } + + timeoutsToDispatch_.clear(); + } + + if (watchesToDispatch_.size() > 0) + { + for (auto watchIterator = watchesToDispatch_.begin(); + watchIterator != watchesToDispatch_.end(); watchIterator++) { + (*watchIterator)->mutex_->lock(); + if (!(*watchIterator)->deleteObject_) { + (*watchIterator)->isExecuted_ = true; + (*watchIterator)->mutex_->unlock(); + Watch* watch = (*watchIterator)->watch_; + const unsigned int flags = watch->getAssociatedFileDescriptor().events; + watch->dispatch(flags); + (*watchIterator)->mutex_->lock(); + (*watchIterator)->isExecuted_ = false; + } + (*watchIterator)->mutex_->unlock(); + } + watchesToDispatch_.clear(); + } + + if (sourcesToDispatch_.size() > 0) + { + isBroken_ = false; + for (auto dispatchSourceIterator = sourcesToDispatch_.begin(); + dispatchSourceIterator != sourcesToDispatch_.end() && !isBroken_; + dispatchSourceIterator++) { + (*dispatchSourceIterator)->mutex_->lock(); + if (!(*dispatchSourceIterator)->deleteObject_) { + (*dispatchSourceIterator)->isExecuted_ = true; + (*dispatchSourceIterator)->mutex_->unlock(); + while ((*dispatchSourceIterator)->dispatchSource_->dispatch()); + (*dispatchSourceIterator)->mutex_->lock(); + (*dispatchSourceIterator)->isExecuted_ = false; + } + (*dispatchSourceIterator)->mutex_->unlock(); + } + { + sourcesToDispatch_.clear(); + } + } +} + +void DBusMainLoop::wakeup() { +#ifdef WIN32 + // Send an initial buffer + char *sendbuf = "1"; + + int iResult = send(sendFd_.fd, sendbuf, (int)strlen(sendbuf), 0); + if (iResult == SOCKET_ERROR) { + printf("send failed with error: %d\n", WSAGetLastError()); + } +#else + int64_t wake = 1; + if(::write(wakeFd_.fd, &wake, sizeof(int64_t)) == -1) { + std::perror("DBusMainLoop::wakeup"); + } +#endif +} + +void DBusMainLoop::wakeupAck() { +#ifdef WIN32 + // Receive until the peer closes the connection + int iResult; + char recvbuf[DEFAULT_BUFLEN]; + int recvbuflen = DEFAULT_BUFLEN; + + iResult = recv(wakeFd_.fd, recvbuf, recvbuflen, 0); + if (iResult > 0) { + //printf("Bytes received from %d: %d\n", wakeFd_.fd, iResult); + } + else if (iResult == 0) { + printf("Connection closed\n"); + } + else { + printf("recv failed with error: %d\n", WSAGetLastError()); + } + +#else + int64_t buffer; + while(::read(wakeFd_.fd, &buffer, sizeof(int64_t)) == sizeof(buffer)); +#endif +} + +void DBusMainLoop::registerFileDescriptor( + const DBusMainLoopPollFd& fileDescriptor) { + std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); + managedFileDescriptors_.push_back(fileDescriptor); +} + +void DBusMainLoop::unregisterFileDescriptor( + const DBusMainLoopPollFd& fileDescriptor) { + wakeup(); + std::lock_guard<std::mutex> itsLock(fileDescriptorsMutex_); + for (auto it = managedFileDescriptors_.begin(); + it != managedFileDescriptors_.end(); it++) { + if ((*it).fd == fileDescriptor.fd && (*it).events == fileDescriptor.events) { + managedFileDescriptors_.erase(it); + break; + } + } +} + +void DBusMainLoop::registerDispatchSource(DispatchSource* dispatchSource, + const DispatchPriority dispatchPriority) { + DispatchSourceToDispatchStruct* dispatchSourceStruct = new DispatchSourceToDispatchStruct(dispatchSource, new std::mutex, false, false); + std::lock_guard<std::mutex> itsLock(dispatchSourcesMutex_); + registeredDispatchSources_.insert({ dispatchPriority, dispatchSourceStruct }); +} + +void DBusMainLoop::unregisterDispatchSource(DispatchSource* dispatchSource) { + { + std::lock_guard<std::mutex> itsLock(dispatchSourcesMutex_); + for (auto dispatchSourceIterator = registeredDispatchSources_.begin(); + dispatchSourceIterator != registeredDispatchSources_.end(); + dispatchSourceIterator++) { + + if ((dispatchSourceIterator->second)->dispatchSource_ == dispatchSource){ + (dispatchSourceIterator->second)->mutex_->lock(); + (dispatchSourceIterator->second)->deleteObject_ = true; + (dispatchSourceIterator->second)->mutex_->unlock(); + break; + } + } + isBroken_ = true; + } +} + +void DBusMainLoop::registerWatch(Watch* watch, + const DispatchPriority dispatchPriority) { + + std::lock_guard<std::mutex> itsLock(watchesMutex_); + DBusMainLoopPollFd fdToRegister = watch->getAssociatedFileDescriptor(); + + registerFileDescriptor(fdToRegister); + std::mutex* mtx = new std::mutex; +#ifndef WIN32 + asm volatile ("":::"memory"); +#endif + WatchToDispatchStruct* watchStruct = new WatchToDispatchStruct(fdToRegister.fd, watch, mtx, false, false); + registeredWatches_.insert({ dispatchPriority, watchStruct}); +} + +void DBusMainLoop::unregisterWatch(Watch* watch) { + unregisterFileDescriptor(watch->getAssociatedFileDescriptor()); + { + std::lock_guard<std::mutex> itsLock(watchesMutex_); + + for (auto watchIterator = registeredWatches_.begin(); + watchIterator != registeredWatches_.end(); watchIterator++) { + + if ((watchIterator->second)->watch_ == watch) { + (watchIterator->second)->mutex_->lock(); + (watchIterator->second)->deleteObject_ = true; + (watchIterator->second)->mutex_->unlock(); + break; + } + } + } +} + +void DBusMainLoop::registerTimeout(Timeout* timeout, + const DispatchPriority dispatchPriority) { + TimeoutToDispatchStruct* timeoutStruct = new TimeoutToDispatchStruct(timeout, new std::mutex, false, false, false); + std::lock_guard<std::mutex> itsLock(timeoutsMutex_); + registeredTimeouts_.insert({ dispatchPriority, timeoutStruct }); +} + +void DBusMainLoop::unregisterTimeout(Timeout* timeout) { + { + std::lock_guard<std::mutex> itsLock(timeoutsMutex_); + for (auto timeoutIterator = registeredTimeouts_.begin(); + timeoutIterator != registeredTimeouts_.end(); + timeoutIterator++) { + + if ((timeoutIterator->second)->timeout_ == timeout) { + (timeoutIterator->second)->mutex_->lock(); + (timeoutIterator->second)->deleteObject_ = true; + (timeoutIterator->second)->mutex_->unlock(); + break; + } + } + } +} + +} // namespace DBus +} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.cpp b/src/CommonAPI/DBus/DBusMainLoopContext.cpp index c20beb9..1c795ad 100644 --- a/src/CommonAPI/DBus/DBusMainLoopContext.cpp +++ b/src/CommonAPI/DBus/DBusMainLoopContext.cpp @@ -24,7 +24,8 @@ DBusDispatchSource::DBusDispatchSource(DBusConnection* dbusConnection): DBusDispatchSource::~DBusDispatchSource() { } -bool DBusDispatchSource::prepare(int64_t& timeout) { +bool DBusDispatchSource::prepare(int64_t &_timeout) { + (void)_timeout; return dbusConnection_->isDispatchReady(); } @@ -44,7 +45,7 @@ DBusWatch::DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& } bool DBusWatch::isReadyToBeWatched() { - return 0 != dbus_watch_get_enabled(libdbusWatch_); + return 0 != dbus_watch_get_enabled(libdbusWatch_); } void DBusWatch::startWatching() { @@ -54,7 +55,7 @@ void DBusWatch::startWatching() { #ifdef WIN32 short int pollFlags = 0; #else - short int pollFlags = POLLERR | POLLHUP; + short int pollFlags = POLLERR | POLLHUP; #endif if(channelFlags_ & DBUS_WATCH_READABLE) { pollFlags |= POLLIN; @@ -64,11 +65,11 @@ void DBusWatch::startWatching() { } #ifdef WIN32 - pollFileDescriptor_.fd = dbus_watch_get_socket(libdbusWatch_); - wsaEvent_ = WSACreateEvent(); - WSAEventSelect(pollFileDescriptor_.fd, wsaEvent_, FD_READ); + pollFileDescriptor_.fd = dbus_watch_get_socket(libdbusWatch_); + wsaEvent_ = WSACreateEvent(); + WSAEventSelect(pollFileDescriptor_.fd, wsaEvent_, FD_READ); #else - pollFileDescriptor_.fd = dbus_watch_get_unix_fd(libdbusWatch_); + pollFileDescriptor_.fd = dbus_watch_get_unix_fd(libdbusWatch_); #endif pollFileDescriptor_.events = pollFlags; @@ -82,7 +83,7 @@ void DBusWatch::startWatching() { void DBusWatch::stopWatching() { auto lockedContext = mainLoopContext_.lock(); if (lockedContext) { - lockedContext->deregisterWatch(this); + lockedContext->deregisterWatch(this); } } @@ -92,7 +93,7 @@ const pollfd& DBusWatch::getAssociatedFileDescriptor() { #ifdef WIN32 const HANDLE& DBusWatch::getAssociatedEvent() { - return wsaEvent_; + return wsaEvent_; } #endif @@ -142,7 +143,7 @@ DBusTimeout::DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopCo } bool DBusTimeout::isReadyToBeMonitored() { - return 0 != dbus_timeout_get_enabled(libdbusTimeout_); + return 0 != dbus_timeout_get_enabled(libdbusTimeout_); } void DBusTimeout::startMonitoring() { @@ -156,7 +157,7 @@ void DBusTimeout::stopMonitoring() { dueTimeInMs_ = TIMEOUT_INFINITE; auto lockedContext = mainLoopContext_.lock(); if (lockedContext) { - lockedContext->deregisterTimeoutSource(this); + lockedContext->deregisterTimeoutSource(this); } } diff --git a/src/CommonAPI/DBus/DBusMessage.cpp b/src/CommonAPI/DBus/DBusMessage.cpp index e041b79..5a6a549 100644 --- a/src/CommonAPI/DBus/DBusMessage.cpp +++ b/src/CommonAPI/DBus/DBusMessage.cpp @@ -13,7 +13,7 @@ namespace CommonAPI { namespace DBus { DBusMessage::DBusMessage() - : message_(NULL) { + : message_(NULL) { } DBusMessage::DBusMessage(::DBusMessage *_message) { @@ -27,7 +27,7 @@ DBusMessage::DBusMessage(::DBusMessage *_message, bool reference) { DBusMessage::DBusMessage(const DBusMessage &_source) { message_ = (_source.message_ != nullptr ? - dbus_message_ref(_source.message_) : nullptr); + dbus_message_ref(_source.message_) : nullptr); } DBusMessage::DBusMessage(DBusMessage &&_source) { @@ -47,7 +47,7 @@ DBusMessage::operator=(const DBusMessage &_source) { dbus_message_unref(message_); message_ = (_source.message_ != nullptr ? - dbus_message_ref(_source.message_) : nullptr); + dbus_message_ref(_source.message_) : nullptr); } return (*this); } @@ -70,24 +70,24 @@ DBusMessage::operator bool() const { DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall( - const std::string &_method, const std::string &_signature) { + const std::string &_method, const std::string &_signature) { - static DBusAddress address("org.freedesktop.DBus", "/", "org.freedesktop.DBus"); + static DBusAddress address("org.freedesktop.DBus", "/", "org.freedesktop.DBus"); return DBusMessage::createMethodCall(address, _method, _signature); } DBusMessage DBusMessage::createMethodCall( - const DBusAddress &_address, + const DBusAddress &_address, const std::string &_method, const std::string &_signature) { - std::string service = _address.getService(); - std::string path = _address.getObjectPath(); - std::string interface = _address.getInterface(); + std::string service = _address.getService(); + std::string path = _address.getObjectPath(); + std::string interface = _address.getInterface(); ::DBusMessage *methodCall = dbus_message_new_method_call( - service.c_str(), path.c_str(), - interface.c_str(), _method.c_str()); + service.c_str(), path.c_str(), + interface.c_str(), _method.c_str()); assert(methodCall); if ("" != _signature) @@ -109,10 +109,10 @@ DBusMessage::createMethodReturn(const std::string &_signature) const { DBusMessage DBusMessage::createMethodError( - const std::string &_code, const std::string &_info) const { + const std::string &_code, const std::string &_info) const { - ::DBusMessage *methodError - = dbus_message_new_error(message_, _code.c_str(), _info.c_str()); + ::DBusMessage *methodError + = dbus_message_new_error(message_, _code.c_str(), _info.c_str()); assert(methodError); return DBusMessage(methodError, false); @@ -120,11 +120,11 @@ DBusMessage::createMethodError( DBusMessage DBusMessage::createSignal( - const std::string &_path, const std::string &_interface, + const std::string &_path, const std::string &_interface, const std::string &_signal, const std::string &_signature) { ::DBusMessage *messageSignal - = dbus_message_new_signal(_path.c_str(), _interface.c_str(), _signal.c_str()); + = dbus_message_new_signal(_path.c_str(), _interface.c_str(), _signal.c_str()); assert(messageSignal); if ("" != _signature) @@ -169,8 +169,8 @@ DBusMessage::getDestination() const { return dbus_message_get_destination(message_); } -const uint32_t DBusMessage::getSerial() const { - return dbus_message_get_serial(message_); +uint32_t DBusMessage::getSerial() const { + return dbus_message_get_serial(message_); } bool @@ -210,7 +210,7 @@ bool DBusMessage::hasSignature(const char *_signature) const { return (!strcmp(signature, _signature)); } -const DBusMessage::Type DBusMessage::getType() const { +DBusMessage::Type DBusMessage::getType() const { return static_cast<Type>(dbus_message_get_type(message_)); } @@ -227,12 +227,12 @@ int DBusMessage::getBodySize() const { } bool DBusMessage::setBodyLength(const int _length) { - return 0 != dbus_message_set_body_length(message_, _length); + return 0 != dbus_message_set_body_length(message_, _length); } bool DBusMessage::setDestination(const char *_destination) { - return 0 != dbus_message_set_destination(message_, _destination); + return 0 != dbus_message_set_destination(message_, _destination); } bool DBusMessage::hasObjectPath(const std::string &_path) const { diff --git a/src/CommonAPI/DBus/DBusObjectManager.cpp b/src/CommonAPI/DBus/DBusObjectManager.cpp index 35a3d4f..3d10c6d 100644 --- a/src/CommonAPI/DBus/DBusObjectManager.cpp +++ b/src/CommonAPI/DBus/DBusObjectManager.cpp @@ -55,12 +55,12 @@ bool DBusObjectManager::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> if (isRegistrationSuccessful && dbusStubAdapter->hasFreedesktopProperties()) { const std::shared_ptr<DBusFreedesktopPropertiesStub> dbusFreedesktopPropertiesStub = - std::make_shared<DBusFreedesktopPropertiesStub>(dbusStubAdapterObjectPath, + std::make_shared<DBusFreedesktopPropertiesStub>(dbusStubAdapterObjectPath, dbusStubAdapterInterfaceName, dbusStubAdapter->getDBusConnection(), dbusStubAdapter); isRegistrationSuccessful = isRegistrationSuccessful - && addDBusInterfaceHandler({ dbusFreedesktopPropertiesStub->getObjectPath(), + && addDBusInterfaceHandler({ dbusFreedesktopPropertiesStub->getObjectPath(), dbusFreedesktopPropertiesStub->getInterface() }, dbusFreedesktopPropertiesStub); } @@ -71,10 +71,10 @@ bool DBusObjectManager::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> if (!managerStubExists) { const std::shared_ptr<DBusObjectManagerStub> newManagerStub - = std::make_shared<DBusObjectManagerStub>( - dbusStubAdapterObjectPath, - dbusStubAdapter->getDBusConnection() - ); + = std::make_shared<DBusObjectManagerStub>( + dbusStubAdapterObjectPath, + dbusStubAdapter->getDBusConnection() + ); auto insertResult = managerStubs_.insert( {dbusStubAdapterObjectPath, {newManagerStub, 1} }); assert(insertResult.second); managerStubIterator = insertResult.first; @@ -92,6 +92,7 @@ bool DBusObjectManager::registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> if (!isRegistrationSuccessful) { const bool isDBusStubAdapterRemoved = removeDBusInterfaceHandler(dbusStubAdapterHandlerPath, dbusStubAdapter); assert(isDBusStubAdapterRemoved); + (void)isDBusStubAdapterRemoved; } } @@ -164,11 +165,12 @@ bool DBusObjectManager::exportManagedDBusStubAdapter(const std::string& parentOb bool DBusObjectManager::unexportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter) { auto foundManagerStubIterator = managerStubs_.find(parentObjectPath); - assert(foundManagerStubIterator != managerStubs_.end()); - - if (std::get<0>(foundManagerStubIterator->second)->unexportManagedDBusStubAdapter(dbusStubAdapter)) { - // Check if other handling is necessary? - return true; + if (foundManagerStubIterator != managerStubs_.end()) { + if (std::get<0>(foundManagerStubIterator->second)->unexportManagedDBusStubAdapter( + dbusStubAdapter)) { + // Check if other handling is necessary? + return true; + } } return false; } @@ -205,8 +207,10 @@ bool DBusObjectManager::addDBusInterfaceHandler(const DBusInterfaceHandlerPath& const bool isDBusInterfaceHandlerAlreadyAdded = (dbusRegisteredObjectsTableIter != dbusRegisteredObjectsTable_.end()); if (isDBusInterfaceHandlerAlreadyAdded) { - //If another ObjectManager is to be registered, you can go on and just use the first one. - if (dbusInterfaceHandlerPath.second == "org.freedesktop.DBus.ObjectManager") { + //If another ObjectManager or a freedesktop properties stub is to be registered, + //you can go on and just use the first one. + if (dbusInterfaceHandlerPath.second == "org.freedesktop.DBus.ObjectManager" || + dbusInterfaceHandlerPath.second == "org.freedesktop.DBus.Properties") { return true; } return false; @@ -226,7 +230,7 @@ bool DBusObjectManager::removeDBusInterfaceHandler(const DBusInterfaceHandlerPat if (isDBusInterfaceHandlerAdded) { auto registeredDBusStubAdapter = dbusRegisteredObjectsTableIter->second; assert(registeredDBusStubAdapter == dbusInterfaceHandler); - + (void)dbusInterfaceHandler; dbusRegisteredObjectsTable_.erase(dbusRegisteredObjectsTableIter); } diff --git a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp index e292473..7516994 100644 --- a/src/CommonAPI/DBus/DBusObjectManagerStub.cpp +++ b/src/CommonAPI/DBus/DBusObjectManagerStub.cpp @@ -30,7 +30,7 @@ DBusObjectManagerStub::~DBusObjectManagerStub() { for (auto& dbusInterfaceIterator : registeredDBusInterfacesMap) { auto managedDBusStubAdapter = dbusInterfaceIterator.second; auto managedDBusStubAdapterServiceAddress = managedDBusStubAdapter->getDBusAddress(); -#ifdef LB_TODO +#ifdef COMMONAPI_TODO const bool isServiceUnregistered = DBusServicePublisher::getInstance()->unregisterManagedService( managedDBusStubAdapterServiceAddress); assert(isServiceUnregistered); @@ -284,7 +284,7 @@ bool DBusObjectManagerStub::onInterfaceDBusMessage(const DBusMessage& dbusMessag } -const bool DBusObjectManagerStub::hasFreedesktopProperties() { +bool DBusObjectManagerStub::hasFreedesktopProperties() { return false; } diff --git a/src/CommonAPI/DBus/DBusOutputStream.cpp b/src/CommonAPI/DBus/DBusOutputStream.cpp index 7d59360..728c017 100644 --- a/src/CommonAPI/DBus/DBusOutputStream.cpp +++ b/src/CommonAPI/DBus/DBusOutputStream.cpp @@ -16,22 +16,22 @@ namespace CommonAPI { namespace DBus { DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage) - : dbusMessage_(dbusMessage) { + : dbusMessage_(dbusMessage) { } // Internal size_t DBusOutputStream::getPosition() { - return payload_.size(); + return payload_.size(); } void DBusOutputStream::pushPosition() { - positions_.push(payload_.size()); + positions_.push(payload_.size()); } size_t DBusOutputStream::popPosition() { - size_t itsPosition = positions_.top(); - positions_.pop(); - return itsPosition; + size_t itsPosition = positions_.top(); + positions_.pop(); + return itsPosition; } // TODO Check where dbusError_ is set @@ -45,8 +45,8 @@ bool DBusOutputStream::hasError() const { // #DBusMessage. The data that is buffered in this #DBusOutputMessageStream // is not deleted by calling flush(). void DBusOutputStream::flush() { - const int toWrite = payload_.size(); - dbusMessage_.setBodyLength(toWrite); + const std::string::size_type toWrite = payload_.size(); + dbusMessage_.setBodyLength(static_cast<int>(toWrite)); char* destinationDataPtr = dbusMessage_.getBodyData(); memcpy(destinationDataPtr, payload_.c_str(), toWrite); } @@ -63,7 +63,7 @@ void DBusOutputStream::setError() { * @param numOfBytes The number of bytes that should be reserved for writing. */ void DBusOutputStream::reserveMemory(size_t numOfBytes) { - assert(numOfBytes >= 0); + assert(numOfBytes > 0); payload_.reserve(numOfBytes); } @@ -82,7 +82,7 @@ static const char eightByteZeroString[] = "\0\0\0\0\0\0\0"; void DBusOutputStream::align(const size_t _boundary) { assert(_boundary > 0 && _boundary <= 8 && - (_boundary % 2 == 0 || _boundary == 1)); + (_boundary % 2 == 0 || _boundary == 1)); size_t mask = _boundary - 1; size_t necessary = ((mask - (payload_.size() & mask)) + 1) & mask; diff --git a/src/CommonAPI/DBus/DBusProxy.cpp b/src/CommonAPI/DBus/DBusProxy.cpp index 1de88fc..19f2eb0 100644 --- a/src/CommonAPI/DBus/DBusProxy.cpp +++ b/src/CommonAPI/DBus/DBusProxy.cpp @@ -16,12 +16,13 @@ namespace CommonAPI { namespace DBus { DBusProxyStatusEvent::DBusProxyStatusEvent(DBusProxy *_dbusProxy) - : dbusProxy_(_dbusProxy) { + : dbusProxy_(_dbusProxy) { } -void DBusProxyStatusEvent::onListenerAdded(const Listener& listener, const Subscription subscription) { +void DBusProxyStatusEvent::onListenerAdded(const Listener &_listener, const Subscription _subscription) { + (void)_subscription; if (dbusProxy_->isAvailable()) - listener(AvailabilityStatus::AVAILABLE); + _listener(AvailabilityStatus::AVAILABLE); } DBusProxy::DBusProxy(const DBusAddress &_dbusAddress, @@ -31,7 +32,7 @@ DBusProxy::DBusProxy(const DBusAddress &_dbusAddress, availabilityStatus_(AvailabilityStatus::UNKNOWN), interfaceVersionAttribute_(*this, "uu", "getInterfaceVersion"), dbusServiceRegistry_(DBusServiceRegistry::get(_connection)), - signalMemberHandlerInfo_(3000) + signalMemberHandlerInfo_(3000) { } @@ -73,80 +74,85 @@ InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() { return interfaceVersionAttribute_; } -void DBusProxy::signalMemberCallback(const CallStatus dbusMessageCallStatus, - const DBusMessage& dbusMessage, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, - const uint32_t tag) { - dbusSignalHandler->onSignalDBusMessage(dbusMessage); +void DBusProxy::signalMemberCallback(const CallStatus _status, + const DBusMessage& dbusMessage, + DBusProxyConnection::DBusSignalHandler *_handler, + const uint32_t _tag) { + (void)_status; + (void)_tag; + _handler->onSignalDBusMessage(dbusMessage); } -void DBusProxy::signalInitialValueCallback(const CallStatus dbusMessageCallStatus, - const DBusMessage& dbusMessage, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, - const uint32_t tag) { - dbusSignalHandler->onInitialValueSignalDBusMessage(dbusMessage, tag); +void DBusProxy::signalInitialValueCallback(const CallStatus _status, + const DBusMessage &_message, + DBusProxyConnection::DBusSignalHandler *_handler, + const uint32_t _tag) { + (void)_status; + _handler->onInitialValueSignalDBusMessage(_message, _tag); } void DBusProxy::onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus) { - if (availabilityStatus != availabilityStatus_) { - availabilityStatusMutex_.lock(); - availabilityStatus_ = availabilityStatus; - availabilityStatusMutex_.unlock(); - - dbusProxyStatusEvent_.notifyListeners(availabilityStatus); - - if (availabilityStatus == AvailabilityStatus::AVAILABLE) { - std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); - - for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); - signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); - signalMemberHandlerIterator++) { - - if (!std::get<7>(*signalMemberHandlerIterator)) { - connection_->addSignalMemberHandler( - std::get<0>(*signalMemberHandlerIterator), - std::get<1>(*signalMemberHandlerIterator), - std::get<2>(*signalMemberHandlerIterator), - std::get<3>(*signalMemberHandlerIterator), - std::get<5>(*signalMemberHandlerIterator), - std::get<6>(*signalMemberHandlerIterator)); - std::get<7>(*signalMemberHandlerIterator) = true; - - DBusMessage message = createMethodCall(std::get<4>(*signalMemberHandlerIterator), ""); - - DBusProxyAsyncSignalMemberCallbackHandler::FunctionType myFunc = std::bind( - &DBusProxy::signalMemberCallback, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3, - std::placeholders::_4); - connection_->sendDBusMessageWithReplyAsync( - message, - DBusProxyAsyncSignalMemberCallbackHandler::create(myFunc, std::get<5>(*signalMemberHandlerIterator), 0), - &signalMemberHandlerInfo_); - } - } - } else { - std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); - - for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); - signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); - signalMemberHandlerIterator++) { - - if (std::get<7>(*signalMemberHandlerIterator)) { - DBusProxyConnection::DBusSignalHandlerToken signalHandlerToken ( - std::get<0>(*signalMemberHandlerIterator), - std::get<1>(*signalMemberHandlerIterator), - std::get<2>(*signalMemberHandlerIterator), - std::get<3>(*signalMemberHandlerIterator)); - connection_->removeSignalMemberHandler(signalHandlerToken, std::get<5>(*signalMemberHandlerIterator)); - std::get<7>(*signalMemberHandlerIterator) = false; - } - } - } - } + if (availabilityStatus != availabilityStatus_) { + availabilityStatusMutex_.lock(); + availabilityStatus_ = availabilityStatus; + availabilityStatusMutex_.unlock(); + + dbusProxyStatusEvent_.notifyListeners(availabilityStatus); + + if (availabilityStatus == AvailabilityStatus::AVAILABLE) { + std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); + + for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); + signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); + signalMemberHandlerIterator++) { + + if (!std::get<7>(*signalMemberHandlerIterator)) { + connection_->addSignalMemberHandler( + std::get<0>(*signalMemberHandlerIterator), + std::get<1>(*signalMemberHandlerIterator), + std::get<2>(*signalMemberHandlerIterator), + std::get<3>(*signalMemberHandlerIterator), + std::get<5>(*signalMemberHandlerIterator), + std::get<6>(*signalMemberHandlerIterator)); + std::get<7>(*signalMemberHandlerIterator) = true; + + DBusMessage message = createMethodCall(std::get<4>(*signalMemberHandlerIterator), ""); + + DBusProxyAsyncSignalMemberCallbackHandler::FunctionType myFunc = std::bind( + &DBusProxy::signalMemberCallback, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4); + connection_->sendDBusMessageWithReplyAsync( + message, + DBusProxyAsyncSignalMemberCallbackHandler::create(myFunc, std::get<5>(*signalMemberHandlerIterator), 0), + &signalMemberHandlerInfo_); + } + } + } else { + std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); + + for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); + signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); + signalMemberHandlerIterator++) { + + if (std::get<7>(*signalMemberHandlerIterator)) { + DBusProxyConnection::DBusSignalHandlerToken signalHandlerToken ( + std::get<0>(*signalMemberHandlerIterator), + std::get<1>(*signalMemberHandlerIterator), + std::get<2>(*signalMemberHandlerIterator), + std::get<3>(*signalMemberHandlerIterator)); + connection_->removeSignalMemberHandler(signalHandlerToken, std::get<5>(*signalMemberHandlerIterator)); + std::get<7>(*signalMemberHandlerIterator) = false; + } + } + } + } + availabilityStatusMutex_.lock(); availabilityCondition_.notify_one(); + availabilityStatusMutex_.unlock(); } DBusProxyConnection::DBusSignalHandlerToken DBusProxy::subscribeForSelectiveBroadcastOnConnection( @@ -194,101 +200,101 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxy::addSignalMemberHandler( const std::string &interfaceName, const std::string &signalName, const std::string &signalSignature, - const std::string &getMethodName, + const std::string &getMethodName, DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, const bool justAddFilter) { - DBusProxyConnection::DBusSignalHandlerToken signalHandlerToken ( - objectPath, - interfaceName, - signalName, - signalSignature); - - if (getMethodName != "") { - - SignalMemberHandlerTuple signalMemberHandler( - objectPath, - interfaceName, - signalName, - signalSignature, - getMethodName, - dbusSignalHandler, - justAddFilter, - false); - - availabilityStatusMutex_.lock(); - if (availabilityStatus_ == AvailabilityStatus::AVAILABLE) { - availabilityStatusMutex_.unlock(); - signalHandlerToken = connection_->addSignalMemberHandler( - objectPath, - interfaceName, - signalName, - signalSignature, - dbusSignalHandler, - justAddFilter); - std::get<7>(signalMemberHandler) = true; - } else { - availabilityStatusMutex_.unlock(); - } - addSignalMemberHandlerToQueue(signalMemberHandler); - } else { - signalHandlerToken = connection_->addSignalMemberHandler( - objectPath, - interfaceName, - signalName, - signalSignature, - dbusSignalHandler, - justAddFilter); - } + DBusProxyConnection::DBusSignalHandlerToken signalHandlerToken ( + objectPath, + interfaceName, + signalName, + signalSignature); + + if (getMethodName != "") { + + SignalMemberHandlerTuple signalMemberHandler( + objectPath, + interfaceName, + signalName, + signalSignature, + getMethodName, + dbusSignalHandler, + justAddFilter, + false); + + availabilityStatusMutex_.lock(); + if (availabilityStatus_ == AvailabilityStatus::AVAILABLE) { + availabilityStatusMutex_.unlock(); + signalHandlerToken = connection_->addSignalMemberHandler( + objectPath, + interfaceName, + signalName, + signalSignature, + dbusSignalHandler, + justAddFilter); + std::get<7>(signalMemberHandler) = true; + } else { + availabilityStatusMutex_.unlock(); + } + addSignalMemberHandlerToQueue(signalMemberHandler); + } else { + signalHandlerToken = connection_->addSignalMemberHandler( + objectPath, + interfaceName, + signalName, + signalSignature, + dbusSignalHandler, + justAddFilter); + } return signalHandlerToken; } void DBusProxy::addSignalMemberHandlerToQueue(SignalMemberHandlerTuple& _signalMemberHandler) { - std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); - bool found = false; - - for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); - signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); - signalMemberHandlerIterator++) { - - if ( (std::get<0>(*signalMemberHandlerIterator) == std::get<0>(_signalMemberHandler)) && - (std::get<1>(*signalMemberHandlerIterator) == std::get<1>(_signalMemberHandler)) && - (std::get<2>(*signalMemberHandlerIterator) == std::get<2>(_signalMemberHandler)) && - (std::get<3>(*signalMemberHandlerIterator) == std::get<3>(_signalMemberHandler))) { - - found = true; - break; - } - } - if (!found) { - signalMemberHandlerQueue_.push_back(_signalMemberHandler); - } + std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); + bool found = false; + + for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); + signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); + signalMemberHandlerIterator++) { + + if ( (std::get<0>(*signalMemberHandlerIterator) == std::get<0>(_signalMemberHandler)) && + (std::get<1>(*signalMemberHandlerIterator) == std::get<1>(_signalMemberHandler)) && + (std::get<2>(*signalMemberHandlerIterator) == std::get<2>(_signalMemberHandler)) && + (std::get<3>(*signalMemberHandlerIterator) == std::get<3>(_signalMemberHandler))) { + + found = true; + break; + } + } + if (!found) { + signalMemberHandlerQueue_.push_back(_signalMemberHandler); + } } bool DBusProxy::removeSignalMemberHandler( - const DBusProxyConnection::DBusSignalHandlerToken &_dbusSignalHandlerToken, - const DBusProxyConnection::DBusSignalHandler *_dbusSignalHandler) { - - { - std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); - for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); - signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); - signalMemberHandlerIterator++) { - - if ( (std::get<0>(*signalMemberHandlerIterator) == std::get<0>(_dbusSignalHandlerToken)) && - (std::get<1>(*signalMemberHandlerIterator) == std::get<1>(_dbusSignalHandlerToken)) && - (std::get<2>(*signalMemberHandlerIterator) == std::get<2>(_dbusSignalHandlerToken)) && - (std::get<3>(*signalMemberHandlerIterator) == std::get<3>(_dbusSignalHandlerToken))) { - signalMemberHandlerIterator = signalMemberHandlerQueue_.erase(signalMemberHandlerIterator); - - if (signalMemberHandlerIterator == signalMemberHandlerQueue_.end()) { - break; - } - } - } - } + const DBusProxyConnection::DBusSignalHandlerToken &_dbusSignalHandlerToken, + const DBusProxyConnection::DBusSignalHandler *_dbusSignalHandler) { + + { + std::lock_guard < std::mutex > queueLock(signalMemberHandlerQueueMutex_); + for(auto signalMemberHandlerIterator = signalMemberHandlerQueue_.begin(); + signalMemberHandlerIterator != signalMemberHandlerQueue_.end(); + signalMemberHandlerIterator++) { + + if ( (std::get<0>(*signalMemberHandlerIterator) == std::get<0>(_dbusSignalHandlerToken)) && + (std::get<1>(*signalMemberHandlerIterator) == std::get<1>(_dbusSignalHandlerToken)) && + (std::get<2>(*signalMemberHandlerIterator) == std::get<2>(_dbusSignalHandlerToken)) && + (std::get<3>(*signalMemberHandlerIterator) == std::get<3>(_dbusSignalHandlerToken))) { + signalMemberHandlerIterator = signalMemberHandlerQueue_.erase(signalMemberHandlerIterator); + + if (signalMemberHandlerIterator == signalMemberHandlerQueue_.end()) { + break; + } + } + } + } return connection_->removeSignalMemberHandler(_dbusSignalHandlerToken, _dbusSignalHandler); } @@ -296,28 +302,64 @@ bool DBusProxy::removeSignalMemberHandler( void DBusProxy::getCurrentValueForSignalListener( const std::string &getMethodName, DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, - const uint32_t subscription) { - - availabilityStatusMutex_.lock(); - if (availabilityStatus_ == AvailabilityStatus::AVAILABLE) { - availabilityStatusMutex_.unlock(); - - DBusMessage message = createMethodCall(getMethodName, ""); - - DBusProxyAsyncSignalMemberCallbackHandler::FunctionType myFunc = std::bind(&DBusProxy::signalInitialValueCallback, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3, - std::placeholders::_4); - connection_->sendDBusMessageWithReplyAsync( - message, - DBusProxyAsyncSignalMemberCallbackHandler::create(myFunc, dbusSignalHandler, subscription), - &signalMemberHandlerInfo_); - } else { - availabilityStatusMutex_.unlock(); - } + const uint32_t subscription) { + + availabilityStatusMutex_.lock(); + if (availabilityStatus_ == AvailabilityStatus::AVAILABLE) { + availabilityStatusMutex_.unlock(); + + DBusMessage message = createMethodCall(getMethodName, ""); + + DBusProxyAsyncSignalMemberCallbackHandler::FunctionType myFunc = std::bind(&DBusProxy::signalInitialValueCallback, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4); + connection_->sendDBusMessageWithReplyAsync( + message, + DBusProxyAsyncSignalMemberCallbackHandler::create(myFunc, dbusSignalHandler, subscription), + &signalMemberHandlerInfo_); + } else { + availabilityStatusMutex_.unlock(); + } +} + +void DBusProxy::freeDesktopGetCurrentValueForSignalListener( + DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + const uint32_t subscription, + const std::string &interfaceName, + const std::string &propertyName) { + + availabilityStatusMutex_.lock(); + if (availabilityStatus_ == AvailabilityStatus::AVAILABLE) { + availabilityStatusMutex_.unlock(); + + DBusAddress itsAddress(getDBusAddress()); + itsAddress.setInterface("org.freedesktop.DBus.Properties"); + DBusMessage _message = DBusMessage::createMethodCall(itsAddress, "Get", "ss"); + DBusOutputStream output(_message); + const bool success = DBusSerializableArguments<const std::string, const std::string> + ::serialize(output, interfaceName, propertyName); + if (success) { + output.flush(); + DBusProxyAsyncSignalMemberCallbackHandler::FunctionType myFunc = std::bind(&DBusProxy::signalInitialValueCallback, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4); + + connection_->sendDBusMessageWithReplyAsync( + _message, + DBusProxyAsyncSignalMemberCallbackHandler::create(myFunc, dbusSignalHandler, subscription), + &signalMemberHandlerInfo_); + } + } else { + availabilityStatusMutex_.unlock(); + } } + } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusProxyBase.cpp b/src/CommonAPI/DBus/DBusProxyBase.cpp index ae8faac..0b1ebe4 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.cpp +++ b/src/CommonAPI/DBus/DBusProxyBase.cpp @@ -12,11 +12,11 @@ namespace CommonAPI { namespace DBus { DBusProxyBase::DBusProxyBase( - const DBusAddress &_dbusAddress, - const std::shared_ptr<DBusProxyConnection> &_connection) - : dbusAddress_(_dbusAddress), - connection_(_connection) { - DBusAddressTranslator::get()->translate(dbusAddress_, address_); + const DBusAddress &_dbusAddress, + const std::shared_ptr<DBusProxyConnection> &_connection) + : dbusAddress_(_dbusAddress), + connection_(_connection) { + DBusAddressTranslator::get()->translate(dbusAddress_, address_); } DBusMessage @@ -27,7 +27,7 @@ DBusProxyBase::createMethodCall(const std::string &_method, const std::string &_ const DBusAddress & DBusProxyBase::getDBusAddress() const { - return dbusAddress_; + return dbusAddress_; } const std::shared_ptr<DBusProxyConnection> & @@ -52,20 +52,21 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle } DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandler( - const std::string &objectPath, - const std::string &interfaceName, - const std::string &signalName, - const std::string &signalSignature, - const std::string &getMethodName, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, - const bool justAddFilter) { + const std::string &objectPath, + const std::string &interfaceName, + const std::string &signalName, + const std::string &signalSignature, + const std::string &getMethodName, + DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + const bool justAddFilter) { + (void)getMethodName; return addSignalMemberHandler( - objectPath, - interfaceName, - signalName, - signalSignature, - dbusSignalHandler, - justAddFilter); + objectPath, + interfaceName, + signalName, + signalSignature, + dbusSignalHandler, + justAddFilter); } bool DBusProxyBase::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& _dbusSignalHandlerToken, const DBusProxyConnection::DBusSignalHandler* _dbusSignalHandler) { diff --git a/src/CommonAPI/DBus/DBusProxyManager.cpp b/src/CommonAPI/DBus/DBusProxyManager.cpp index 5a69083..6a48994 100644 --- a/src/CommonAPI/DBus/DBusProxyManager.cpp +++ b/src/CommonAPI/DBus/DBusProxyManager.cpp @@ -11,9 +11,9 @@ namespace CommonAPI { namespace DBus { DBusProxyManager::DBusProxyManager( - DBusProxy &_proxy, + DBusProxy &_proxy, const std::string &_interfaceId) - : proxy_(_proxy), + : proxy_(_proxy), instanceAvailabilityStatusEvent_(_proxy, _interfaceId), interfaceId_(_interfaceId), registry_(DBusServiceRegistry::get(_proxy.getDBusConnection())) @@ -22,23 +22,23 @@ DBusProxyManager::DBusProxyManager( const std::string & DBusProxyManager::getDomain() const { - static std::string domain("local"); - return domain; + static std::string domain("local"); + return domain; } const std::string & DBusProxyManager::getInterface() const { - return interfaceId_; + return interfaceId_; } const ConnectionId_t & DBusProxyManager::getConnectionId() const { - return connectionId_; + return connectionId_; } void DBusProxyManager::instancesAsyncCallback( - const CommonAPI::CallStatus &_status, + const CommonAPI::CallStatus &_status, const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, GetAvailableInstancesCallback &_call) { std::vector<std::string> result; @@ -50,20 +50,20 @@ DBusProxyManager::instancesAsyncCallback( void DBusProxyManager::getAvailableInstances( - CommonAPI::CallStatus &_status, - std::vector<std::string> &_availableInstances) { + CommonAPI::CallStatus &_status, + std::vector<std::string> &_availableInstances) { DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dict; DBusProxyHelper< - DBusSerializableArguments<>, + DBusSerializableArguments<>, DBusSerializableArguments< - DBusObjectManagerStub::DBusObjectPathAndInterfacesDict - > + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict + > >::callMethodWithReply(proxy_, DBusObjectManagerStub::getInterfaceName(), "GetManagedObjects", "", - &defaultCallInfo, + &defaultCallInfo, _status, dict); @@ -74,44 +74,44 @@ DBusProxyManager::getAvailableInstances( std::future<CallStatus> DBusProxyManager::getAvailableInstancesAsync( - GetAvailableInstancesCallback _callback) { + GetAvailableInstancesCallback _callback) { return CommonAPI::DBus::DBusProxyHelper< - CommonAPI::DBus::DBusSerializableArguments<>, - CommonAPI::DBus::DBusSerializableArguments< - DBusObjectManagerStub::DBusObjectPathAndInterfacesDict - > - >::callMethodAsync( - proxy_, - DBusObjectManagerStub::getInterfaceName(), - "GetManagedObjects", - "a{oa{sa{sv}}}", - &defaultCallInfo, - std::move( - std::bind( - &DBusProxyManager::instancesAsyncCallback, - this, - std::placeholders::_1, std::placeholders::_2, - _callback - ) - ), - std::tuple<DBusObjectManagerStub::DBusObjectPathAndInterfacesDict>()); + CommonAPI::DBus::DBusSerializableArguments<>, + CommonAPI::DBus::DBusSerializableArguments< + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict + > + >::callMethodAsync( + proxy_, + DBusObjectManagerStub::getInterfaceName(), + "GetManagedObjects", + "", + &defaultCallInfo, + std::move( + std::bind( + &DBusProxyManager::instancesAsyncCallback, + this, + std::placeholders::_1, std::placeholders::_2, + _callback + ) + ), + std::tuple<DBusObjectManagerStub::DBusObjectPathAndInterfacesDict>()); } void DBusProxyManager::getInstanceAvailabilityStatus( - const std::string &_address, - CallStatus &_callStatus, - AvailabilityStatus &_availabilityStatus) { + const std::string &_address, + CallStatus &_callStatus, + AvailabilityStatus &_availabilityStatus) { - CommonAPI::Address itsAddress("local", interfaceId_, _address); - DBusAddress itsDBusAddress; - DBusAddressTranslator::get()->translate(itsAddress, itsDBusAddress); + CommonAPI::Address itsAddress("local", interfaceId_, _address); + DBusAddress itsDBusAddress; + DBusAddressTranslator::get()->translate(itsAddress, itsDBusAddress); - _availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; + _availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; if (registry_->isServiceInstanceAlive( - itsDBusAddress.getInterface(), - itsDBusAddress.getService(), - itsDBusAddress.getObjectPath())) { + itsDBusAddress.getInterface(), + itsDBusAddress.getService(), + itsDBusAddress.getObjectPath())) { _availabilityStatus = AvailabilityStatus::AVAILABLE; } _callStatus = CallStatus::SUCCESS; @@ -119,19 +119,19 @@ DBusProxyManager::getInstanceAvailabilityStatus( void DBusProxyManager::instanceAliveAsyncCallback( - const AvailabilityStatus &_alive, - GetInstanceAvailabilityStatusCallback &_call, - std::shared_ptr<std::promise<CallStatus> > &_status) { + const AvailabilityStatus &_alive, + GetInstanceAvailabilityStatusCallback &_call, + std::shared_ptr<std::promise<CallStatus> > &_status) { _call(CallStatus::SUCCESS, _alive); _status->set_value(CallStatus::SUCCESS); } std::future<CallStatus> DBusProxyManager::getInstanceAvailabilityStatusAsync( - const std::string &_instance, + const std::string &_instance, GetInstanceAvailabilityStatusCallback _callback) { - CommonAPI::Address itsAddress("local", interfaceId_, _instance); + CommonAPI::Address itsAddress("local", interfaceId_, _instance); std::shared_ptr<std::promise<CallStatus> > promise = std::make_shared<std::promise<CallStatus>>(); registry_->subscribeAvailabilityListener( @@ -153,22 +153,24 @@ DBusProxyManager::getInstanceAvailabilityStatusChangedEvent() { void DBusProxyManager::translateCommonApiAddresses( - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, - std::vector<std::string> &_instances) { + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, + std::vector<std::string> &_instances) { - CommonAPI::Address itsAddress; - DBusAddress itsDBusAddress; + CommonAPI::Address itsAddress; + DBusAddress itsDBusAddress; for (const auto &objectPathIter : _dict) { itsDBusAddress.setObjectPath(objectPathIter.first); const auto &interfacesDict = objectPathIter.second; for (const auto &interfaceIter : interfacesDict) { - itsDBusAddress.setInterface(interfaceIter.first); - - DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress); - _instances.push_back(itsAddress.getInstance()); + // return only those addresses whose interface matches with ours + if (interfaceIter.first == interfaceId_) { + itsDBusAddress.setInterface(interfaceIter.first); + DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress); + _instances.push_back(itsAddress.getInstance()); + } } } } diff --git a/src/CommonAPI/DBus/DBusServiceRegistry.cpp b/src/CommonAPI/DBus/DBusServiceRegistry.cpp index f18ff44..55e0239 100644 --- a/src/CommonAPI/DBus/DBusServiceRegistry.cpp +++ b/src/CommonAPI/DBus/DBusServiceRegistry.cpp @@ -23,18 +23,18 @@ static CommonAPI::CallInfo serviceRegistryInfo(10000); std::shared_ptr<DBusServiceRegistry> DBusServiceRegistry::get(std::shared_ptr<DBusProxyConnection> _connection) { - std::lock_guard<std::mutex> itsGuard(registriesMutex_); - auto registryIterator = registries_.find(_connection); - if (registryIterator != registries_.end()) - return registryIterator->second; - - std::shared_ptr<DBusServiceRegistry> registry - = std::make_shared<DBusServiceRegistry>(_connection); - if (registry) { - registry->init(); - registries_.insert( { _connection, registry } ); - } - return registry; + std::lock_guard<std::mutex> itsGuard(registriesMutex_); + auto registryIterator = registries_.find(_connection); + if (registryIterator != registries_.end()) + return registryIterator->second; + + std::shared_ptr<DBusServiceRegistry> registry + = std::make_shared<DBusServiceRegistry>(_connection); + if (registry) { + registry->init(); + registries_.insert( { _connection, registry } ); + } + return registry; } DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection) : @@ -46,11 +46,11 @@ DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> db } DBusServiceRegistry::~DBusServiceRegistry() { - if (!initialized_) { - return; - } + if (!initialized_) { + return; + } - dbusDaemonProxy_->getNameOwnerChangedEvent().unsubscribe(dbusDaemonProxyNameOwnerChangedEventSubscription_); + dbusDaemonProxy_->getNameOwnerChangedEvent().unsubscribe(dbusDaemonProxyNameOwnerChangedEventSubscription_); dbusDaemonProxy_->getProxyStatusEvent().unsubscribe(dbusDaemonProxyStatusEventSubscription_); // notify only listeners of resolved services (online > offline) @@ -71,11 +71,12 @@ DBusServiceRegistry::~DBusServiceRegistry() { dbusServiceUniqueName, this); assert(isSubscriptionCancelled); + (void)isSubscriptionCancelled; } } void DBusServiceRegistry::init() { - translator_ = DBusAddressTranslator::get(); + translator_ = DBusAddressTranslator::get(); dbusDaemonProxyStatusEventSubscription_ = dbusDaemonProxy_->getProxyStatusEvent().subscribe( @@ -96,13 +97,13 @@ void DBusServiceRegistry::init() { DBusServiceRegistry::DBusServiceSubscription DBusServiceRegistry::subscribeAvailabilityListener( - const std::string &_address, DBusServiceListener serviceListener) { - DBusAddress dbusAddress; - translator_->translate(_address, dbusAddress); + const std::string &_address, DBusServiceListener serviceListener) { + DBusAddress dbusAddress; + translator_->translate(_address, dbusAddress); if (notificationThread_ == std::this_thread::get_id()) { - COMMONAPI_ERROR( - "You must not build proxies in callbacks of ProxyStatusEvent.", + COMMONAPI_ERROR( + "You must not build proxies in callbacks of ProxyStatusEvent.", " Please refer to the documentation for suggestions how to avoid this."); assert(false); } @@ -124,7 +125,7 @@ DBusServiceRegistry::subscribeAvailabilityListener( } else if (dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::NOT_AVAILABLE) { availabilityStatus = AvailabilityStatus::NOT_AVAILABLE; } else if (dbusServiceListenersRecord.uniqueBusNameState != DBusRecordState::RESOLVING && - dbusInterfaceNameListenersRecord.state == DBusRecordState::UNKNOWN) { + dbusInterfaceNameListenersRecord.state == DBusRecordState::UNKNOWN) { dbusInterfaceNameListenersRecord.state = resolveDBusInterfaceNameState(dbusAddress, dbusServiceListenersRecord); } @@ -156,9 +157,9 @@ DBusServiceRegistry::subscribeAvailabilityListener( void DBusServiceRegistry::unsubscribeAvailabilityListener( - const std::string &_address, DBusServiceSubscription& listenerSubscription) { - DBusAddress dbusAddress; - translator_->translate(_address, dbusAddress); + const std::string &_address, DBusServiceSubscription& listenerSubscription) { + DBusAddress dbusAddress; + translator_->translate(_address, dbusAddress); std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); auto dbusServiceListenersIterator = dbusServiceListenersMap.find(dbusAddress.getService()); @@ -277,11 +278,24 @@ bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& dbusInterfac if(dbusObjectPathCacheIterator != dbusObjectPathsCache.end()) { dbusObjectPathCache = &(dbusObjectPathCacheIterator->second); + if (dbusObjectPathCache->state != DBusRecordState::RESOLVED) { + dbusObjectPathCache->state = DBusRecordState::RESOLVING; + dbusServicesMutex_.lock(); + + dbusObjectPathCache = &(dbusObjectPathCacheIterator->second); + + std::future<DBusRecordState> futureObjectPathResolved = dbusObjectPathCache->promiseOnResolve.get_future(); + dbusServicesMutex_.unlock(); + + introspectDBusObjectPath(uniqueName, dbusObjectPath); + futureObjectPathResolved.wait_for(timeout); + } } else { // try to resolve object paths DBusObjectPathCache newDbusObjectPathCache; newDbusObjectPathCache.state = DBusRecordState::RESOLVING; + newDbusObjectPathCache.serviceName = dbusServiceName; dbusServicesMutex_.lock(); @@ -314,11 +328,11 @@ bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& dbusInterfac } void DBusServiceRegistry::fetchAllServiceNames() { - if (!dbusDaemonProxy_->isAvailable()) { + if (!dbusDaemonProxy_->isAvailable()) { return; } - CallStatus callStatus; + CallStatus callStatus; std::vector<std::string> availableServiceNames; dbusDaemonProxy_->listNames(callStatus, availableServiceNames); @@ -335,6 +349,7 @@ void DBusServiceRegistry::fetchAllServiceNames() { // d-feet mode std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const std::string& interfaceName, const std::string& domainName) { + (void)domainName; std::vector<std::string> availableServiceInstances; // resolve all service names @@ -412,7 +427,7 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const != dbusObjectPathCacheIterator->second.dbusInterfaceNamesCache.end()) { std::string commonApiAddress; translator_->translate( - dbusObjectPathCacheIterator->first + "/" + interfaceName + "/" + serviceName, commonApiAddress); + dbusObjectPathCacheIterator->first + "/" + interfaceName + "/" + serviceName, commonApiAddress); availableServiceInstances.push_back(commonApiAddress); } } @@ -432,6 +447,7 @@ void DBusServiceRegistry::getAvailableServiceInstancesAsync(CommonAPI::Factory:: //shall return without delay. std::thread( [this, _cbk, _interface, _domain](std::shared_ptr<DBusServiceRegistry> selfRef) { + (void)selfRef; auto instances = getAvailableServiceInstances(_interface, _domain); _cbk(instances); }, this->shared_from_this() @@ -491,30 +507,38 @@ void DBusServiceRegistry::onSignalDBusMessage(const DBusMessage &_dbusMessage) { const bool isDBusServiceUniqueNameFound = (dbusServiceUniqueNameIterator != dbusUniqueNamesMap_.end()); if (!isDBusServiceUniqueNameFound) { - // LB TODO: unsubscribe here! - // Needs to be reworked in order to store the subscription identifier! + // LB TODO: unsubscribe here! + // Needs to be reworked in order to store the subscription identifier! return; } auto& dbusUniqueNameRecord = dbusServiceUniqueNameIterator->second; - DBusObjectPathCache& dbusObjectPathRecord = dbusUniqueNameRecord.dbusObjectPathsCache[dbusObjectPath]; + DBusObjectPathCache *dbusObjectPathRecord; + auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); + if(dbusObjectPathCacheIterator != dbusUniqueNameRecord.dbusObjectPathsCache.end()) + dbusObjectPathRecord = &(dbusObjectPathCacheIterator->second); + else + return; - if (dbusObjectPathRecord.state != DBusRecordState::RESOLVED) { + if (dbusObjectPathRecord->state != DBusRecordState::RESOLVED) { return; } for (const auto& dbusInterfaceName : dbusInterfaceNames) { if (dbusInterfaceNameState == DBusRecordState::AVAILABLE) { - dbusObjectPathRecord.dbusInterfaceNamesCache.insert(dbusInterfaceName); + dbusObjectPathRecord->dbusInterfaceNamesCache.insert(dbusInterfaceName); } else { - dbusObjectPathRecord.dbusInterfaceNamesCache.erase(dbusInterfaceName); + dbusObjectPathRecord->dbusInterfaceNamesCache.erase(dbusInterfaceName); } } notifyDBusServiceListeners(dbusUniqueNameRecord, dbusObjectPath, dbusInterfaceNames, dbusInterfaceNameState); } +void DBusServiceRegistry::setDBusServicePredefined(const std::string& _serviceName) { + dbusPredefinedServices_.insert(_serviceName); +} void DBusServiceRegistry::resolveDBusServiceName(const std::string& dbusServiceName, DBusServiceListenersRecord& dbusServiceListenersRecord) { @@ -575,7 +599,7 @@ void DBusServiceRegistry::onGetNameOwnerCallback(const CallStatus& status, DBusServiceRegistry::DBusRecordState DBusServiceRegistry::resolveDBusInterfaceNameState( - const DBusAddress &_dbusAddress, DBusServiceListenersRecord &dbusServiceListenersRecord) { + const DBusAddress &_dbusAddress, DBusServiceListenersRecord &dbusServiceListenersRecord) { assert(dbusServiceListenersRecord.uniqueBusNameState == DBusRecordState::RESOLVED); assert(!dbusServiceListenersRecord.uniqueBusName.empty()); @@ -583,7 +607,8 @@ DBusServiceRegistry::resolveDBusInterfaceNameState( assert(!dbusServiceUniqueNameRecord.ownedBusNames.empty()); auto& dbusObjectPathRecord = getDBusObjectPathCacheReference( - _dbusAddress.getObjectPath(), + _dbusAddress.getObjectPath(), + _dbusAddress.getService(), dbusServiceListenersRecord.uniqueBusName, dbusServiceUniqueNameRecord); @@ -592,7 +617,7 @@ DBusServiceRegistry::resolveDBusInterfaceNameState( } auto dbusInterfaceNameIterator - = dbusObjectPathRecord.dbusInterfaceNamesCache.find(_dbusAddress.getInterface()); + = dbusObjectPathRecord.dbusInterfaceNamesCache.find(_dbusAddress.getInterface()); const bool isDBusInterfaceNameFound = (dbusInterfaceNameIterator != dbusObjectPathRecord.dbusInterfaceNamesCache.end()); @@ -602,14 +627,17 @@ DBusServiceRegistry::resolveDBusInterfaceNameState( DBusServiceRegistry::DBusObjectPathCache & DBusServiceRegistry::getDBusObjectPathCacheReference( - const std::string& dbusObjectPath, - const std::string& dbusServiceUniqueName, + const std::string& dbusObjectPath, + const std::string& dbusServiceName, + const std::string& dbusServiceUniqueName, DBusUniqueNameRecord& dbusUniqueNameRecord) { const bool isFirstDBusObjectPathCache = dbusUniqueNameRecord.dbusObjectPathsCache.empty(); auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); if(dbusObjectPathCacheIterator == dbusUniqueNameRecord.dbusObjectPathsCache.end()) { - std::unordered_map<std::string, DBusObjectPathCache>::value_type value (dbusObjectPath, DBusObjectPathCache()); + DBusObjectPathCache objectPathCache; + objectPathCache.serviceName = dbusServiceName; + std::unordered_map<std::string, DBusObjectPathCache>::value_type value (dbusObjectPath, std::move(objectPathCache)); dbusUniqueNameRecord.dbusObjectPathsCache.insert(std::move(value)); dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); } @@ -620,10 +648,11 @@ DBusServiceRegistry::getDBusObjectPathCacheReference( dbusServiceUniqueName, this); assert(isSubscriptionSuccessful); + (void)isSubscriptionSuccessful; } if (dbusObjectPathCacheIterator->second.state == DBusRecordState::UNKNOWN - && introspectDBusObjectPath(dbusServiceUniqueName, dbusObjectPath)) { + && resolveObjectPathWithObjectManager(dbusServiceUniqueName, dbusObjectPath)) { dbusObjectPathCacheIterator->second.state = DBusRecordState::RESOLVING; } @@ -649,6 +678,7 @@ void DBusServiceRegistry::releaseDBusObjectPathCacheReference(const std::string& auto dbusObjectPathCacheIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); const bool isDBusObjectPathCacheFound = (dbusObjectPathCacheIterator != dbusUniqueNameRecord.dbusObjectPathsCache.end()); assert(isDBusObjectPathCacheFound); + (void)isDBusObjectPathCacheFound; auto& dbusObjectPathCache = dbusObjectPathCacheIterator->second; assert(dbusObjectPathCache.referenceCount > 0); @@ -665,10 +695,196 @@ void DBusServiceRegistry::releaseDBusObjectPathCacheReference(const std::string& dbusServiceListenersRecord.uniqueBusName, this); assert(isSubscriptionCancelled); + (void)isSubscriptionCancelled; } } } +bool DBusServiceRegistry::resolveObjectPathWithObjectManager(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath) { + // get managed objects from root object manager + auto getManagedObjectsCallback = std::bind( + &DBusServiceRegistry::onGetManagedObjectsCallbackResolve, + this->shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + dbusServiceUniqueName, + dbusObjectPath); + return getManagedObjects(dbusServiceUniqueName, "/", getManagedObjectsCallback); +} + +bool DBusServiceRegistry::getManagedObjects(const std::string& dbusServiceUniqueName, + const std::string& dbusObjectPath, + GetManagedObjectsCallback callback) { + bool isSendingInProgress = false; + auto dbusConnection = dbusDaemonProxy_->getDBusConnection(); + + assert(!dbusServiceUniqueName.empty()); + + if(dbusConnection->isConnected()) { + + if(dbusObjectPath != "/") { + mutexObjectPathsResolveCount.lock(); + objectPathsToResolve++; + mutexObjectPathsResolveCount.unlock(); + } + + DBusAddress dbusAddress(dbusServiceUniqueName, dbusObjectPath, "org.freedesktop.DBus.ObjectManager"); + DBusMessage dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall( + dbusAddress, + "GetManagedObjects"); + + auto getManagedObjectsCallback = std::bind( + callback, + std::placeholders::_1, + std::placeholders::_2, + dbusServiceUniqueName, + dbusObjectPath); + + dbusConnection->sendDBusMessageWithReplyAsync( + dbusMessageCall, + DBusProxyAsyncCallbackHandler< + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict + >::create(getManagedObjectsCallback, std::tuple<DBusObjectManagerStub::DBusObjectPathAndInterfacesDict>()), + &serviceRegistryInfo); + + isSendingInProgress = true; + } + return isSendingInProgress; +} + +void DBusServiceRegistry::onGetManagedObjectsCallbackResolve(const CallStatus& callStatus, + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict, + const std::string& dbusServiceUniqueName, + const std::string& dbusObjectPath) { + + if(callStatus == CallStatus::SUCCESS) { + //has object manager + bool objectPathFound = false; + for(auto objectPathDict : dbusObjectPathAndInterfacesDict) + { + std::string objectPath = objectPathDict.first; + if(objectPath != dbusObjectPath) + continue; + + // object path that should be resolved is found --> resolve + objectPathFound = true; + CommonAPI::DBus::DBusObjectManagerStub::DBusInterfacesAndPropertiesDict interfacesAndPropertiesDict = objectPathDict.second; + for(auto interfaceDict : interfacesAndPropertiesDict) + { + std::string interfaceName = interfaceDict.first; + dbusServicesMutex_.lock(); + processManagedObject(dbusObjectPath, dbusServiceUniqueName, interfaceName); + dbusServicesMutex_.unlock(); + } + + // resolve further managed objects + auto callback = std::bind( + &DBusServiceRegistry::onGetManagedObjectsCallbackResolveFurther, + this->shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4); + getManagedObjects(dbusServiceUniqueName, dbusObjectPath, callback); + } + + if(!objectPathFound) { + // object path is managed. Try to resolve object path with the help of the manager + auto getManagedObjectsCallback = std::bind( + &DBusServiceRegistry::onGetManagedObjectsCallbackResolve, + this->shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + dbusServiceUniqueName, + dbusObjectPath); + std::string objectPathManager = dbusObjectPath.substr(0, dbusObjectPath.find_last_of("\\/")); + getManagedObjects(dbusServiceUniqueName, objectPathManager, getManagedObjectsCallback); + } + } else { + COMMONAPI_ERROR("There is no Object Manager that manages " + dbusObjectPath + ". Resolving failed!"); + } +} + +void DBusServiceRegistry::onGetManagedObjectsCallbackResolveFurther(const CallStatus& callStatus, + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict, + const std::string& dbusServiceUniqueName, + const std::string& dbusObjectPath) { + + if(callStatus == CallStatus::SUCCESS) { + for(auto objectPathDict : dbusObjectPathAndInterfacesDict) + { + //resolve + std::string objectPath = objectPathDict.first; + CommonAPI::DBus::DBusObjectManagerStub::DBusInterfacesAndPropertiesDict interfacesAndPropertiesDict = objectPathDict.second; + for(auto interfaceDict : interfacesAndPropertiesDict) + { + std::string interfaceName = interfaceDict.first; + dbusServicesMutex_.lock(); + processManagedObject(objectPath, dbusServiceUniqueName, interfaceName); + dbusServicesMutex_.unlock(); + } + + // resolve further managed objects + auto callback = std::bind( + &DBusServiceRegistry::onGetManagedObjectsCallbackResolveFurther, + this->shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4); + getManagedObjects(dbusServiceUniqueName, objectPath, callback); + } + } else { + // No further managed objects + } + + std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_); + + auto dbusServiceUniqueNameIterator = dbusUniqueNamesMap_.find(dbusServiceUniqueName); + const bool isDBusServiceUniqueNameFound = (dbusServiceUniqueNameIterator != dbusUniqueNamesMap_.end()); + + if (!isDBusServiceUniqueNameFound) { + return; + } + + DBusUniqueNameRecord& dbusUniqueNameRecord = dbusServiceUniqueNameIterator->second; + auto dbusObjectPathIterator = dbusUniqueNameRecord.dbusObjectPathsCache.find(dbusObjectPath); + const bool isDBusObjectPathFound = (dbusObjectPathIterator != dbusUniqueNameRecord.dbusObjectPathsCache.end()); + + if (!isDBusObjectPathFound) { + return; + } + + DBusObjectPathCache& dbusObjectPathRecord = dbusObjectPathIterator->second; + + dbusObjectPathRecord.state = DBusRecordState::RESOLVED; + dbusObjectPathRecord.promiseOnResolve.set_value(dbusObjectPathRecord.state); + mutexObjectPathsResolveCount.lock(); + objectPathsToResolve--; + mutexObjectPathsResolveCount.unlock(); + monitorResolveAllObjectPaths_.notify_all(); + + dbusUniqueNameRecord.objectPathsState = DBusRecordState::RESOLVED; + + notifyDBusServiceListeners( + dbusUniqueNameRecord, + dbusObjectPath, + dbusObjectPathRecord.dbusInterfaceNamesCache, + DBusRecordState::RESOLVED); +} + +void DBusServiceRegistry::processManagedObject(const std::string& dbusObjectPath, + const std::string& dbusServiceUniqueName, + const std::string& interfaceName) { + DBusUniqueNameRecord& dbusUniqueNameRecord = dbusUniqueNamesMap_[dbusServiceUniqueName]; + DBusObjectPathCache& dbusObjectPathCache = dbusUniqueNameRecord.dbusObjectPathsCache[dbusObjectPath]; + + if(!isOrgFreedesktopDBusInterface(interfaceName)) { + dbusObjectPathCache.dbusInterfaceNamesCache.insert(interfaceName); + } else if (translator_->isOrgFreedesktopDBusPeerMapped() && (interfaceName == "org.freedesktop.DBus.Peer")) { + dbusObjectPathCache.dbusInterfaceNamesCache.insert(interfaceName); + } +} bool DBusServiceRegistry::introspectDBusObjectPath(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath) { @@ -697,13 +913,12 @@ bool DBusServiceRegistry::introspectDBusObjectPath(const std::string& dbusServic dbusConnection->sendDBusMessageWithReplyAsync( dbusMessageCall, DBusProxyAsyncCallbackHandler< - std::string + std::string >::create(instrospectAsyncCallback, std::tuple<std::string>()), &serviceRegistryInfo); isResolvingInProgress = true; } - return isResolvingInProgress; } @@ -765,7 +980,7 @@ void DBusServiceRegistry::onIntrospectCallback(const CallStatus& callStatus, } void DBusServiceRegistry::parseIntrospectionNode(const pugi::xml_node& node, const std::string& rootObjectPath, const std::string& fullObjectPath, const std::string& dbusServiceUniqueName) { - std::string nodeName; + std::string nodeName; for(pugi::xml_node& subNode : node.children()) { nodeName = std::string(subNode.name()); @@ -909,19 +1124,35 @@ void DBusServiceRegistry::onDBusServiceAvailable(const std::string& dbusServiceN if (!isDBusServiceNameObserved) { return; } - - // resolve object path and notify service listners for (auto dbusObjectPathListenersIterator = dbusServiceListenersRecord.dbusObjectPathListenersMap.begin(); dbusObjectPathListenersIterator != dbusServiceListenersRecord.dbusObjectPathListenersMap.end();) { const std::string& listenersDBusObjectPath = dbusObjectPathListenersIterator->first; auto& dbusInterfaceNameListenersMap = dbusObjectPathListenersIterator->second; - auto& dbusObjectPathRecord = getDBusObjectPathCacheReference( - listenersDBusObjectPath, - dbusServiceUniqueName, - *dbusUniqueNameRecord); - if (dbusObjectPathRecord.state == DBusRecordState::RESOLVED) { - notifyDBusObjectPathResolved(dbusInterfaceNameListenersMap, dbusObjectPathRecord.dbusInterfaceNamesCache); + if(dbusPredefinedServices_.find(dbusServiceName) == dbusPredefinedServices_.end()) { + //service not predefined -> resolve object path and notify service listeners + auto& dbusObjectPathRecord = getDBusObjectPathCacheReference( + listenersDBusObjectPath, + dbusServiceName, + dbusServiceUniqueName, + *dbusUniqueNameRecord); + + if (dbusObjectPathRecord.state == DBusRecordState::RESOLVED) { + notifyDBusObjectPathResolved(dbusInterfaceNameListenersMap, dbusObjectPathRecord.dbusInterfaceNamesCache); + } + } else { + //service is predefined -> notify service listeners about availability + for(auto dbusInterfaceNameListenerRecordIterator = dbusInterfaceNameListenersMap.begin(); + dbusInterfaceNameListenerRecordIterator != dbusInterfaceNameListenersMap.end(); + ++dbusInterfaceNameListenerRecordIterator) { + auto& dbusInterfaceNameListenerRecord = dbusInterfaceNameListenerRecordIterator->second; + dbusInterfaceNameListenerRecord.state = DBusRecordState::RESOLVED; + for(auto dbusServiceListenerIterator = dbusInterfaceNameListenerRecord.listenerList.begin(); + dbusServiceListenerIterator != dbusInterfaceNameListenerRecord.listenerList.end(); + ++dbusServiceListenerIterator) { + (*dbusServiceListenerIterator)(AvailabilityStatus::AVAILABLE); + } + } } if (dbusInterfaceNameListenersMap.empty()) { @@ -939,7 +1170,7 @@ void DBusServiceRegistry::onDBusServiceNotAvailable(DBusServiceListenersRecord& const DBusUniqueNamesMapIterator dbusUniqueNameRecordIterator = dbusUniqueNamesMap_.find(dbusServiceListenersRecord.uniqueBusName); if (dbusUniqueNameRecordIterator != dbusUniqueNamesMap_.end()) { - removeUniqueName(dbusUniqueNameRecordIterator, _serviceName); + removeUniqueName(dbusUniqueNameRecordIterator, _serviceName); } dbusServiceListenersRecord.uniqueBusName.clear(); @@ -1068,17 +1299,31 @@ void DBusServiceRegistry::removeUniqueName(const DBusUniqueNamesMapIterator& dbu dbusUniqueNamesIterator->first, this); assert(isSubscriptionCancelled); + (void)isSubscriptionCancelled; if ("" != _serviceName) { - auto findServiceName = dbusUniqueNamesIterator->second.ownedBusNames.find(_serviceName); - if (findServiceName != dbusUniqueNamesIterator->second.ownedBusNames.end()) - dbusUniqueNamesIterator->second.ownedBusNames.erase(findServiceName); + auto findServiceName = dbusUniqueNamesIterator->second.ownedBusNames.find(_serviceName); + if (findServiceName != dbusUniqueNamesIterator->second.ownedBusNames.end()) + dbusUniqueNamesIterator->second.ownedBusNames.erase(findServiceName); } else { - dbusUniqueNamesIterator->second.ownedBusNames.clear(); + dbusUniqueNamesIterator->second.ownedBusNames.clear(); } - if (dbusUniqueNamesIterator->second.ownedBusNames.size() == 0) - dbusUniqueNamesMap_.erase(dbusUniqueNamesIterator); + if (dbusUniqueNamesIterator->second.ownedBusNames.size() == 0) { + dbusUniqueNamesMap_.erase(dbusUniqueNamesIterator); + } else { + //delete object path cache entry of service + auto& dbusObjectPathsCache = dbusUniqueNamesIterator->second.dbusObjectPathsCache; + auto dbusObjectPathCacheIterator = dbusObjectPathsCache.begin(); + while(dbusObjectPathCacheIterator != dbusObjectPathsCache.end()) { + DBusObjectPathCache *objectPathCache = &(dbusObjectPathCacheIterator->second); + if(objectPathCache->serviceName == _serviceName) { + dbusObjectPathCacheIterator = dbusUniqueNamesIterator->second.dbusObjectPathsCache.erase(dbusObjectPathCacheIterator); + } else { + ++dbusObjectPathCacheIterator; + } + } + } } DBusServiceRegistry::DBusUniqueNameRecord* DBusServiceRegistry::insertServiceNameMapping(const std::string& dbusUniqueName, diff --git a/src/CommonAPI/DBus/DBusStubAdapter.cpp b/src/CommonAPI/DBus/DBusStubAdapter.cpp index 03fa6c3..6a3a8cf 100644 --- a/src/CommonAPI/DBus/DBusStubAdapter.cpp +++ b/src/CommonAPI/DBus/DBusStubAdapter.cpp @@ -12,8 +12,8 @@ namespace DBus { DBusStubAdapter::DBusStubAdapter(const DBusAddress &_dbusAddress, const std::shared_ptr<DBusProxyConnection> &_connection, const bool _isManaging) - : dbusAddress_(_dbusAddress), - connection_(_connection), + : dbusAddress_(_dbusAddress), + connection_(_connection), isManaging_(_isManaging) { } @@ -22,7 +22,8 @@ DBusStubAdapter::~DBusStubAdapter() { } void DBusStubAdapter::init(std::shared_ptr<DBusStubAdapter> _instance) { - DBusAddressTranslator::get()->translate(dbusAddress_, address_); + (void)_instance; + DBusAddressTranslator::get()->translate(dbusAddress_, address_); } void DBusStubAdapter::deinit() { @@ -36,11 +37,11 @@ const std::shared_ptr<DBusProxyConnection> &DBusStubAdapter::getDBusConnection() return connection_; } -const bool DBusStubAdapter::isManaging() const { +bool DBusStubAdapter::isManaging() const { return isManaging_; } -const bool DBusStubAdapter::hasFreedesktopProperties() { +bool DBusStubAdapter::hasFreedesktopProperties() { return false; } |